Skip to content

Commit 15c1d2d

Browse files
authored
[EH] Fix pops in newly-added blocks in ReFinalize (#8114)
1 parent 2a05afe commit 15c1d2d

File tree

3 files changed

+81
-1
lines changed

3 files changed

+81
-1
lines changed

src/ir/ReFinalize.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
#include "ir/eh-utils.h"
1718
#include "ir/utils.h"
1819

1920
namespace wasm {
@@ -137,7 +138,10 @@ void ReFinalize::visitRethrow(Rethrow* curr) { curr->finalize(); }
137138
void ReFinalize::visitThrowRef(ThrowRef* curr) { curr->finalize(); }
138139
void ReFinalize::visitNop(Nop* curr) { curr->finalize(); }
139140
void ReFinalize::visitUnreachable(Unreachable* curr) { curr->finalize(); }
140-
void ReFinalize::visitPop(Pop* curr) { curr->finalize(); }
141+
void ReFinalize::visitPop(Pop* curr) {
142+
curr->finalize();
143+
seenPop = true;
144+
}
141145
void ReFinalize::visitTupleMake(TupleMake* curr) { curr->finalize(); }
142146
void ReFinalize::visitTupleExtract(TupleExtract* curr) { curr->finalize(); }
143147
void ReFinalize::visitRefI31(RefI31* curr) { curr->finalize(); }
@@ -210,6 +214,11 @@ void ReFinalize::visitDataSegment(DataSegment* curr) {
210214
WASM_UNREACHABLE("unimp");
211215
}
212216
void ReFinalize::visitTag(Tag* curr) { WASM_UNREACHABLE("unimp"); }
217+
void ReFinalize::visitFunction(Function* curr) {
218+
if (seenPop && addedBlock) {
219+
EHUtils::handleBlockNestedPops(curr, *getModule());
220+
}
221+
}
213222
void ReFinalize::visitModule(Module* curr) { WASM_UNREACHABLE("unimp"); }
214223

215224
void ReFinalize::updateBreakValueType(Name name, Type type) {
@@ -232,6 +241,7 @@ void ReFinalize::replaceUntaken(Expression* value, Expression* otherChild) {
232241
otherChild = builder.makeDrop(otherChild);
233242
}
234243
replaceCurrent(builder.makeBlock({value, otherChild}, Type::unreachable));
244+
addedBlock = true;
235245
} else if (value) {
236246
replaceCurrent(value);
237247
} else {

src/ir/utils.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ struct ReFinalize
145145
void visitMemory(Memory* curr);
146146
void visitDataSegment(DataSegment* curr);
147147
void visitTag(Tag* curr);
148+
void visitFunction(Function* curr);
148149
void visitModule(Module* curr);
149150

150151
private:
@@ -153,6 +154,10 @@ struct ReFinalize
153154
// Replace an untaken branch/switch with an unreachable value.
154155
// A condition may also exist and may or may not be unreachable.
155156
void replaceUntaken(Expression* value, Expression* condition);
157+
158+
// If we see a pop and also add a block, we need to do EH fixups.
159+
bool seenPop = false;
160+
bool addedBlock = false;
156161
};
157162

158163
// Re-finalize a single node. This is slow, if you want to refinalize

test/lit/passes/vacuum-eh-pop.wast

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
2+
;; RUN: wasm-opt %s --vacuum -all -S -o - | filecheck %s
3+
4+
(module
5+
;; CHECK: (type $func (func (param i32)))
6+
(type $func (func (param i32)))
7+
8+
;; CHECK: (import "fuzzing-support" "log-i32" (func $import (type $func) (param i32)))
9+
(import "fuzzing-support" "log-i32" (func $import (param i32)))
10+
11+
;; CHECK: (tag $tag (type $func) (param i32))
12+
(tag $tag (type $func) (param i32))
13+
14+
;; CHECK: (func $test (type $1) (result i32)
15+
;; CHECK-NEXT: (local $0 i32)
16+
;; CHECK-NEXT: (block $block (result i32)
17+
;; CHECK-NEXT: (try
18+
;; CHECK-NEXT: (do
19+
;; CHECK-NEXT: (call $import
20+
;; CHECK-NEXT: (i32.const 0)
21+
;; CHECK-NEXT: )
22+
;; CHECK-NEXT: )
23+
;; CHECK-NEXT: (catch $tag
24+
;; CHECK-NEXT: (local.set $0
25+
;; CHECK-NEXT: (pop i32)
26+
;; CHECK-NEXT: )
27+
;; CHECK-NEXT: (drop
28+
;; CHECK-NEXT: (block
29+
;; CHECK-NEXT: (drop
30+
;; CHECK-NEXT: (local.get $0)
31+
;; CHECK-NEXT: )
32+
;; CHECK-NEXT: (unreachable)
33+
;; CHECK-NEXT: )
34+
;; CHECK-NEXT: )
35+
;; CHECK-NEXT: )
36+
;; CHECK-NEXT: )
37+
;; CHECK-NEXT: (i32.const 1)
38+
;; CHECK-NEXT: )
39+
;; CHECK-NEXT: )
40+
(func $test (result i32)
41+
(block $block (result i32)
42+
;; Vacuum cannot simplify the body here, but it will make a change to the
43+
;; unreachable br_if, replacing it with its dropped children (as the branch
44+
;; is untaken, and we want to remove that reference to $block). While doing
45+
;; so we must update the IR to handle the pop.
46+
(try
47+
(do
48+
(call $import
49+
(i32.const 0)
50+
)
51+
)
52+
(catch $tag
53+
(drop
54+
(br_if $block
55+
(pop i32)
56+
(unreachable)
57+
)
58+
)
59+
)
60+
)
61+
(i32.const 1)
62+
)
63+
)
64+
)
65+

0 commit comments

Comments
 (0)