Skip to content

Commit c3de795

Browse files
authored
[EH][Stack Switching] Fix GUFA's analysis of resume_throw (#8174)
resume_throw does both a resume (which we handled) and a throw - that is, it sends values to a Tag.
1 parent ed7bf9e commit c3de795

2 files changed

Lines changed: 66 additions & 2 deletions

File tree

src/ir/possible-contents.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,7 +1277,7 @@ struct InfoCollector
12771277
}
12781278
}
12791279
}
1280-
void visitThrow(Throw* curr) {
1280+
template<typename T> void handleThrow(T* curr) {
12811281
auto& operands = curr->operands;
12821282
if (!isRelevant(operands)) {
12831283
return;
@@ -1289,6 +1289,7 @@ struct InfoCollector
12891289
{ExpressionLocation{operands[i], 0}, TagLocation{tag, i}});
12901290
}
12911291
}
1292+
void visitThrow(Throw* curr) { handleThrow(curr); }
12921293
void visitRethrow(Rethrow* curr) {}
12931294
void visitThrowRef(ThrowRef* curr) {}
12941295

@@ -1390,7 +1391,10 @@ struct InfoCollector
13901391
}
13911392

13921393
void visitResume(Resume* curr) { handleResume(curr); }
1393-
void visitResumeThrow(ResumeThrow* curr) { handleResume(curr); }
1394+
void visitResumeThrow(ResumeThrow* curr) {
1395+
handleResume(curr);
1396+
handleThrow(curr);
1397+
}
13941398
void visitStackSwitch(StackSwitch* curr) {
13951399
// TODO: optimize when possible
13961400
addRoot(curr);

test/lit/passes/gufa-eh.wast

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,63 @@
5858
)
5959
)
6060
)
61+
62+
(module
63+
;; CHECK: (type $func (func))
64+
(type $func (func))
65+
;; CHECK: (type $cont (cont $func))
66+
(type $cont (cont $func))
67+
68+
;; CHECK: (type $2 (func (param i32)))
69+
70+
;; CHECK: (type $3 (func (result i32)))
71+
72+
;; CHECK: (elem declare func $func)
73+
74+
;; CHECK: (tag $tag (type $2) (param i32))
75+
(tag $tag (param i32))
76+
77+
;; CHECK: (export "handle" (func $handle))
78+
79+
;; CHECK: (func $func (type $func)
80+
;; CHECK-NEXT: (nop)
81+
;; CHECK-NEXT: )
82+
(func $func (type $func)
83+
(nop)
84+
)
85+
86+
;; CHECK: (func $handle (type $3) (result i32)
87+
;; CHECK-NEXT: (drop
88+
;; CHECK-NEXT: (block $block (result i32)
89+
;; CHECK-NEXT: (try_table (catch $tag $block)
90+
;; CHECK-NEXT: (resume_throw $cont $tag
91+
;; CHECK-NEXT: (i32.const 42)
92+
;; CHECK-NEXT: (cont.new $cont
93+
;; CHECK-NEXT: (ref.func $func)
94+
;; CHECK-NEXT: )
95+
;; CHECK-NEXT: )
96+
;; CHECK-NEXT: (unreachable)
97+
;; CHECK-NEXT: )
98+
;; CHECK-NEXT: )
99+
;; CHECK-NEXT: )
100+
;; CHECK-NEXT: (i32.const 42)
101+
;; CHECK-NEXT: )
102+
(func $handle (export "handle") (result i32)
103+
;; Resume a new continuation and throw inside it immediately. We handle the
104+
;; exception in the try_table, returning 42. GUFA should not think we do not
105+
;; handle it (if it did, it would add an unreachable and trap). This tests
106+
;; that we see that resume_throw sends values to the tag, like a throw.
107+
(block $block (result i32)
108+
(try_table (catch $tag $block)
109+
(resume_throw $cont $tag
110+
(i32.const 42)
111+
(cont.new $cont
112+
(ref.func $func)
113+
)
114+
)
115+
(unreachable)
116+
)
117+
)
118+
)
119+
)
120+

0 commit comments

Comments
 (0)