Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/ir/possible-contents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1776,6 +1776,7 @@ void TNHOracle::scan(Function* func,
void visitStructCmpxchg(StructCmpxchg* curr) {
notePossibleTrap(curr->ref);
}
// TODO: visitStructWait
void visitArrayGet(ArrayGet* curr) { notePossibleTrap(curr->ref); }
void visitArraySet(ArraySet* curr) { notePossibleTrap(curr->ref); }
void visitArrayLoad(ArrayLoad* curr) { notePossibleTrap(curr->ref); }
Expand Down
2 changes: 2 additions & 0 deletions src/ir/struct-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ struct StructScanner : public WalkerPass<PostWalker<SubType>> {
noteExpressionOrCopy(curr->replacement, type, index, info);
}

// TODO: visitStructWait

void visitRefCast(RefCast* curr) {
if (curr->desc) {
// We may try to read a descriptor from anything arriving in |curr->ref|,
Expand Down
2 changes: 2 additions & 0 deletions src/passes/GlobalTypeOptimization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,8 @@ struct GlobalTypeOptimization : public Pass {
assert(newIndex != RemovedField);
curr->index = newIndex;
}

// TODO: visitStructWait
};

PassRunner runner(getPassRunner());
Expand Down
9 changes: 8 additions & 1 deletion src/passes/TypeRefining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,12 @@ struct TypeRefining : public Pass {
}

void visitStructCmpxchg(StructCmpxchg* curr) {
if (curr->type == Type::unreachable) {
if (curr->ref->type == Type::unreachable) {
// Ignore unreachable code. Note that we check curr->ref, not curr,
// as curr may be unreachable because of another operand than the ref
// and the replacement value (the expected value may be the
// unreachable one). In that case, the replacement must still validate
// as if it were written, so we must fix it up below.
Comment on lines +558 to +559

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could relax this in the validator. I don't think we're consistent about how we enforce requirements on non-unreachable children of unreachable expressions.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, that might be another option. Though I think stricter validation (like we have now) is generally the thing to aim for?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Agree the current validator might not be consistent on this, though...)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, sounds fine to me.

return;
}
auto type = curr->ref->type.getHeapType();
Expand All @@ -563,6 +568,8 @@ struct TypeRefining : public Pass {
curr->replacement = fixType(curr->replacement, fieldType);
}

// TODO: visitStructWait

bool refinalize = false;

// Fix up a given value so it fits into the type the location it is
Expand Down
59 changes: 59 additions & 0 deletions test/lit/passes/type-refining-gufa-rmw.wast
Original file line number Diff line number Diff line change
Expand Up @@ -415,3 +415,62 @@
)
)
)

(module
;; NRML: (type $struct (sub (struct (field (mut (ref null $struct))))))
;; GUFA: (rec
;; GUFA-NEXT: (type $struct (sub (struct (field (mut nullref)))))
(type $struct (sub (struct (field (mut (ref null $struct))))))

;; NRML: (type $1 (func (param (ref null $struct))))

;; NRML: (func $test (type $1) (param $struct (ref null $struct))
;; NRML-NEXT: (drop
;; NRML-NEXT: (struct.new_default $struct)
;; NRML-NEXT: )
;; NRML-NEXT: (drop
;; NRML-NEXT: (struct.atomic.rmw.cmpxchg acqrel acqrel $struct 0
;; NRML-NEXT: (local.get $struct)
;; NRML-NEXT: (unreachable)
;; NRML-NEXT: (local.get $struct)
;; NRML-NEXT: )
;; NRML-NEXT: )
;; NRML-NEXT: )
;; GUFA: (type $1 (func (param (ref null $struct))))

;; GUFA: (func $test (type $1) (param $struct (ref null $struct))
;; GUFA-NEXT: (drop
;; GUFA-NEXT: (struct.new_default $struct)
;; GUFA-NEXT: )
;; GUFA-NEXT: (drop
;; GUFA-NEXT: (struct.atomic.rmw.cmpxchg acqrel acqrel $struct 0
;; GUFA-NEXT: (local.get $struct)
;; GUFA-NEXT: (unreachable)
;; GUFA-NEXT: (block (result nullref)
;; GUFA-NEXT: (drop
;; GUFA-NEXT: (local.get $struct)
;; GUFA-NEXT: )
;; GUFA-NEXT: (ref.null none)
;; GUFA-NEXT: )
;; GUFA-NEXT: )
;; GUFA-NEXT: )
;; GUFA-NEXT: )
(func $test (param $struct (ref null $struct))
;; Use the type, writing only nulls.
(drop
(struct.new_default $struct)
)
;; An unreachable cmpxchg, but where the ref and value are not unreachable.
;; The value must still validate as if it were written, so we will fix it up
;; with a null, as the field is refined to a null (in GUFA mode, which
;; does that refining).
(drop
(struct.atomic.rmw.cmpxchg acqrel acqrel $struct 0
(local.get $struct)
(unreachable)
(local.get $struct)
)
)
)
)

Loading