Skip to content

Commit d555a06

Browse files
authored
[EH] Fix nested pops when GTO removes a GC operation (WebAssembly#7242)
1 parent bb876a5 commit d555a06

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

src/passes/GlobalTypeOptimization.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
// * Fields that are never read from can be removed entirely.
2323
//
2424

25+
#include "ir/eh-utils.h"
2526
#include "ir/localize.h"
2627
#include "ir/module-utils.h"
2728
#include "ir/ordering.h"
@@ -453,6 +454,8 @@ struct GlobalTypeOptimization : public Pass {
453454
return std::make_unique<FieldRemover>(parent);
454455
}
455456

457+
bool needEHFixups = false;
458+
456459
void visitStructNew(StructNew* curr) {
457460
if (curr->type == Type::unreachable) {
458461
return;
@@ -476,6 +479,8 @@ struct GlobalTypeOptimization : public Pass {
476479
ChildLocalizer localizer(
477480
curr, getFunction(), *getModule(), getPassOptions());
478481
replaceCurrent(localizer.getReplacement());
482+
// Adding a block here requires EH fixups.
483+
needEHFixups = true;
479484

480485
// Remove and reorder operands.
481486
Index removed = 0;
@@ -519,6 +524,7 @@ struct GlobalTypeOptimization : public Pass {
519524
getFunction(),
520525
getModule(),
521526
getPassOptions());
527+
needEHFixups = true;
522528
Expression* replacement =
523529
builder.makeDrop(builder.makeRefAs(RefAsNonNull, flipped));
524530
if (curr->order == MemoryOrder::SeqCst) {
@@ -545,6 +551,12 @@ struct GlobalTypeOptimization : public Pass {
545551
curr->index = newIndex;
546552
}
547553

554+
void visitFunction(Function* curr) {
555+
if (needEHFixups) {
556+
EHUtils::handleBlockNestedPops(curr, *getModule());
557+
}
558+
}
559+
548560
private:
549561
Index getNewIndex(HeapType type, Index index) {
550562
auto iter = parent.indexesAfterRemovals.find(type);

test/lit/passes/gto-removals.wast

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,3 +1627,55 @@
16271627
)
16281628
)
16291629
)
1630+
1631+
;; A struct with a pop, which requires EH fixups to avoid popping in a nested
1632+
;; block.
1633+
(module
1634+
(type $i32 (func (param i32)))
1635+
1636+
;; CHECK: (rec
1637+
;; CHECK-NEXT: (type $struct (struct))
1638+
(type $struct (struct (field (mut i32))))
1639+
1640+
;; CHECK: (type $1 (func))
1641+
1642+
;; CHECK: (type $i32 (func (param i32)))
1643+
1644+
;; CHECK: (tag $tag (type $i32) (param i32))
1645+
(tag $tag (type $i32) (param i32))
1646+
1647+
;; CHECK: (func $func (type $1)
1648+
;; CHECK-NEXT: (local $0 i32)
1649+
;; CHECK-NEXT: (local $1 i32)
1650+
;; CHECK-NEXT: (try
1651+
;; CHECK-NEXT: (do
1652+
;; CHECK-NEXT: )
1653+
;; CHECK-NEXT: (catch $tag
1654+
;; CHECK-NEXT: (local.set $1
1655+
;; CHECK-NEXT: (pop i32)
1656+
;; CHECK-NEXT: )
1657+
;; CHECK-NEXT: (drop
1658+
;; CHECK-NEXT: (block (result (ref $struct))
1659+
;; CHECK-NEXT: (local.set $0
1660+
;; CHECK-NEXT: (local.get $1)
1661+
;; CHECK-NEXT: )
1662+
;; CHECK-NEXT: (struct.new_default $struct)
1663+
;; CHECK-NEXT: )
1664+
;; CHECK-NEXT: )
1665+
;; CHECK-NEXT: )
1666+
;; CHECK-NEXT: )
1667+
;; CHECK-NEXT: )
1668+
(func $func
1669+
(try
1670+
(do
1671+
)
1672+
(catch $tag
1673+
(drop
1674+
(struct.new $struct
1675+
(pop i32)
1676+
)
1677+
)
1678+
)
1679+
)
1680+
)
1681+
)

0 commit comments

Comments
 (0)