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
4 changes: 4 additions & 0 deletions src/passes/Heap2Local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,10 @@ struct Struct2Local : PostWalker<Struct2Local> {
auto descIndex = localIndexes[fields.size()];
Expression* value = builder.makeLocalGet(descIndex, descType);
replaceCurrent(builder.blockify(builder.makeDrop(curr->ref), value));

// After removing the ref.get_desc, a null may be falling through,
// requiring refinalization to update parents.
refinalize = true;
}

void visitStructSet(StructSet* curr) {
Expand Down
54 changes: 53 additions & 1 deletion test/lit/passes/heap2local-desc.wast
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@
;; CHECK-NEXT: (local $1 (ref (exact $sub.desc)))
;; CHECK-NEXT: (block (result (ref (exact $sub.desc)))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result (ref null $super))
;; CHECK-NEXT: (block (result nullref)
;; CHECK-NEXT: (block (result nullref)
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (struct.new_default $sub.desc)
Expand Down Expand Up @@ -1004,3 +1004,55 @@
)
)
)

(module
(rec
(type $A (descriptor $B (struct)))
(type $B (sub (describes $A (struct))))
)
;; CHECK: (type $0 (func))

;; CHECK: (func $test (type $0)
;; CHECK-NEXT: (local $0 (ref none))
;; CHECK-NEXT: (local $1 (ref none))
;; CHECK-NEXT: (block $block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (br_on_null $block
;; CHECK-NEXT: (block (result (ref none))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result nullref)
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (ref.as_non_null
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $0
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $test
;; After removing the ref.get_desc, the null descriptor falls through, and
;; we must update the br_on_null's type, or internal validation errors.
(block $block
(drop
(br_on_null $block
(ref.get_desc $A
(struct.new_default $A
(ref.null none)
)
)
)
)
(unreachable)
)
)
)
Loading