Skip to content

Commit 00aae63

Browse files
authored
[Stack Switching] GUFA: Fix closed world analysis of continuation functions (#7844)
As #7841 but for GUFA.
1 parent 9438ce1 commit 00aae63

File tree

2 files changed

+177
-1
lines changed

2 files changed

+177
-1
lines changed

src/ir/possible-contents.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,31 @@ struct InfoCollector
12751275
void visitContNew(ContNew* curr) {
12761276
// TODO: optimize when possible
12771277
addRoot(curr);
1278+
1279+
// The function reference that is passed in here will be called, just as if
1280+
// we were a call_ref, except at a potentially later time.
1281+
if (!curr->func->type.isRef()) {
1282+
return;
1283+
}
1284+
auto targetType = curr->func->type.getHeapType();
1285+
if (!targetType.isSignature()) {
1286+
assert(targetType.isBottom());
1287+
return;
1288+
}
1289+
// Unlike call_ref, we do not have the call operands here. Assume any
1290+
// value for the signature for now, but we could track them from cont.bind
1291+
// and resume TODO (it is simpler for now to do it here, where we have the
1292+
// original funcref that is called, before cont.bind alters the signature)
1293+
Index i = 0;
1294+
for (auto param : targetType.getSignature().params) {
1295+
if (isRelevant(param)) {
1296+
// Send anything of the proper type to all functions of this signature,
1297+
// since they are all callable.
1298+
info.links.push_back(
1299+
{getTypeLocation(param), SignatureParamLocation{targetType, i}});
1300+
}
1301+
i++;
1302+
}
12781303
}
12791304
void visitContBind(ContBind* curr) {
12801305
// TODO: optimize when possible

test/lit/passes/gufa-cont.wast

Lines changed: 152 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,37 @@
11
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
22

3-
;; RUN: foreach %s %t wasm-opt -all --gufa -S -o - | filecheck %s
3+
;; RUN: foreach %s %t wasm-opt --gufa --closed-world -all -S -o - | filecheck %s
4+
;; RUN: foreach %s %t wasm-opt --gufa -all -S -o - | filecheck %s --check-prefix OPEN_WORLD
45

56
(module
67
;; CHECK: (type $func (func))
8+
;; OPEN_WORLD: (type $func (func))
79
(type $func (func))
810
;; CHECK: (type $cont (cont $func))
11+
;; OPEN_WORLD: (type $cont (cont $func))
912
(type $cont (cont $func))
1013

1114
;; CHECK: (type $func-i32 (func (result i32)))
15+
;; OPEN_WORLD: (type $func-i32 (func (result i32)))
1216
(type $func-i32 (func (result i32)))
1317
;; CHECK: (type $cont-i32 (cont $func-i32))
18+
;; OPEN_WORLD: (type $cont-i32 (cont $func-i32))
1419
(type $cont-i32 (cont $func-i32))
1520

1621
;; CHECK: (type $4 (func (result i32 (ref $cont))))
1722

1823
;; CHECK: (elem declare func $cont $cont-i32)
1924

2025
;; CHECK: (tag $tag (type $func))
26+
;; OPEN_WORLD: (type $4 (func (result i32 (ref $cont))))
27+
28+
;; OPEN_WORLD: (elem declare func $cont $cont-i32)
29+
30+
;; OPEN_WORLD: (tag $tag (type $func))
2131
(tag $tag (type $func))
2232

2333
;; CHECK: (tag $tag-i32 (type $func-i32) (result i32))
34+
;; OPEN_WORLD: (tag $tag-i32 (type $func-i32) (result i32))
2435
(tag $tag-i32 (type $func-i32))
2536

2637
;; CHECK: (export "resume" (func $resume))
@@ -32,6 +43,15 @@
3243
;; CHECK: (func $cont (type $func)
3344
;; CHECK-NEXT: (suspend $tag)
3445
;; CHECK-NEXT: )
46+
;; OPEN_WORLD: (export "resume" (func $resume))
47+
48+
;; OPEN_WORLD: (export "resume_throw" (func $resume_throw))
49+
50+
;; OPEN_WORLD: (export "resume-i32" (func $resume-i32))
51+
52+
;; OPEN_WORLD: (func $cont (type $func)
53+
;; OPEN_WORLD-NEXT: (suspend $tag)
54+
;; OPEN_WORLD-NEXT: )
3555
(func $cont
3656
;; Helper for below.
3757
(suspend $tag)
@@ -49,6 +69,18 @@
4969
;; CHECK-NEXT: )
5070
;; CHECK-NEXT: )
5171
;; CHECK-NEXT: )
72+
;; OPEN_WORLD: (func $resume (type $func)
73+
;; OPEN_WORLD-NEXT: (drop
74+
;; OPEN_WORLD-NEXT: (block $block (result (ref $cont))
75+
;; OPEN_WORLD-NEXT: (resume $cont (on $tag $block)
76+
;; OPEN_WORLD-NEXT: (cont.new $cont
77+
;; OPEN_WORLD-NEXT: (ref.func $cont)
78+
;; OPEN_WORLD-NEXT: )
79+
;; OPEN_WORLD-NEXT: )
80+
;; OPEN_WORLD-NEXT: (return)
81+
;; OPEN_WORLD-NEXT: )
82+
;; OPEN_WORLD-NEXT: )
83+
;; OPEN_WORLD-NEXT: )
5284
(func $resume (export "resume")
5385
;; A continuation is created, it suspends, and we handle that. There is
5486
;; nothing to optimize or change here.
@@ -76,6 +108,18 @@
76108
;; CHECK-NEXT: )
77109
;; CHECK-NEXT: )
78110
;; CHECK-NEXT: )
111+
;; OPEN_WORLD: (func $resume_throw (type $func)
112+
;; OPEN_WORLD-NEXT: (drop
113+
;; OPEN_WORLD-NEXT: (block $block (result (ref $cont))
114+
;; OPEN_WORLD-NEXT: (resume_throw $cont $tag (on $tag $block)
115+
;; OPEN_WORLD-NEXT: (cont.new $cont
116+
;; OPEN_WORLD-NEXT: (ref.func $cont)
117+
;; OPEN_WORLD-NEXT: )
118+
;; OPEN_WORLD-NEXT: )
119+
;; OPEN_WORLD-NEXT: (return)
120+
;; OPEN_WORLD-NEXT: )
121+
;; OPEN_WORLD-NEXT: )
122+
;; OPEN_WORLD-NEXT: )
79123
(func $resume_throw (export "resume_throw")
80124
;; As above, but with resume_throw.
81125
(drop
@@ -95,6 +139,11 @@
95139
;; CHECK-NEXT: (unreachable)
96140
;; CHECK-NEXT: (unreachable)
97141
;; CHECK-NEXT: )
142+
;; OPEN_WORLD: (func $cont-i32 (type $func-i32) (result i32)
143+
;; OPEN_WORLD-NEXT: (suspend $tag)
144+
;; OPEN_WORLD-NEXT: (unreachable)
145+
;; OPEN_WORLD-NEXT: (unreachable)
146+
;; OPEN_WORLD-NEXT: )
98147
(func $cont-i32 (result i32)
99148
;; Helper for below.
100149
(suspend $tag)
@@ -115,6 +164,20 @@
115164
;; CHECK-NEXT: )
116165
;; CHECK-NEXT: )
117166
;; CHECK-NEXT: )
167+
;; OPEN_WORLD: (func $resume-i32 (type $func)
168+
;; OPEN_WORLD-NEXT: (tuple.drop 2
169+
;; OPEN_WORLD-NEXT: (block $block (type $4) (result i32 (ref $cont))
170+
;; OPEN_WORLD-NEXT: (drop
171+
;; OPEN_WORLD-NEXT: (resume $cont-i32 (on $tag-i32 $block)
172+
;; OPEN_WORLD-NEXT: (cont.new $cont-i32
173+
;; OPEN_WORLD-NEXT: (ref.func $cont-i32)
174+
;; OPEN_WORLD-NEXT: )
175+
;; OPEN_WORLD-NEXT: )
176+
;; OPEN_WORLD-NEXT: )
177+
;; OPEN_WORLD-NEXT: (return)
178+
;; OPEN_WORLD-NEXT: )
179+
;; OPEN_WORLD-NEXT: )
180+
;; OPEN_WORLD-NEXT: )
118181
(func $resume-i32 (export "resume-i32")
119182
;; As above, but with more values sent than just the continuation.
120183
(tuple.drop 2
@@ -130,3 +193,91 @@
130193
)
131194
)
132195

196+
(module
197+
;; CHECK: (type $func (func (param i32)))
198+
199+
;; CHECK: (type $cont (cont $func))
200+
201+
;; CHECK: (type $none (func))
202+
;; OPEN_WORLD: (type $func (func (param i32)))
203+
204+
;; OPEN_WORLD: (type $cont (cont $func))
205+
206+
;; OPEN_WORLD: (type $none (func))
207+
(type $none (func))
208+
(type $func (func (param i32)))
209+
(type $cont (cont $func))
210+
211+
;; CHECK: (elem declare func $func)
212+
213+
;; CHECK: (tag $tag (type $none))
214+
;; OPEN_WORLD: (elem declare func $func)
215+
216+
;; OPEN_WORLD: (tag $tag (type $none))
217+
(tag $tag (type $none))
218+
219+
;; CHECK: (export "run" (func $run))
220+
221+
;; CHECK: (func $func (type $func) (param $x i32)
222+
;; CHECK-NEXT: (drop
223+
;; CHECK-NEXT: (local.get $x)
224+
;; CHECK-NEXT: )
225+
;; CHECK-NEXT: )
226+
;; OPEN_WORLD: (export "run" (func $run))
227+
228+
;; OPEN_WORLD: (func $func (type $func) (param $x i32)
229+
;; OPEN_WORLD-NEXT: (drop
230+
;; OPEN_WORLD-NEXT: (local.get $x)
231+
;; OPEN_WORLD-NEXT: )
232+
;; OPEN_WORLD-NEXT: )
233+
(func $func (param $x i32)
234+
;; This function is only ever referred to by a ref.func that is passed into
235+
;; a cont.new, and that is the only source of values for this local. We should
236+
;; not modify this to unreachable, which we would do if we didn't realize it
237+
;; can be reached. (The only possible value is 42, from the caller below, but
238+
;; we do not infer that yet TODO)
239+
(drop
240+
(local.get $x)
241+
)
242+
)
243+
244+
;; CHECK: (func $run (type $none)
245+
;; CHECK-NEXT: (drop
246+
;; CHECK-NEXT: (block $block (result (ref $cont))
247+
;; CHECK-NEXT: (resume $cont (on $tag $block)
248+
;; CHECK-NEXT: (i32.const 42)
249+
;; CHECK-NEXT: (cont.new $cont
250+
;; CHECK-NEXT: (ref.func $func)
251+
;; CHECK-NEXT: )
252+
;; CHECK-NEXT: )
253+
;; CHECK-NEXT: (return)
254+
;; CHECK-NEXT: )
255+
;; CHECK-NEXT: )
256+
;; CHECK-NEXT: )
257+
;; OPEN_WORLD: (func $run (type $none)
258+
;; OPEN_WORLD-NEXT: (drop
259+
;; OPEN_WORLD-NEXT: (block $block (result (ref $cont))
260+
;; OPEN_WORLD-NEXT: (resume $cont (on $tag $block)
261+
;; OPEN_WORLD-NEXT: (i32.const 42)
262+
;; OPEN_WORLD-NEXT: (cont.new $cont
263+
;; OPEN_WORLD-NEXT: (ref.func $func)
264+
;; OPEN_WORLD-NEXT: )
265+
;; OPEN_WORLD-NEXT: )
266+
;; OPEN_WORLD-NEXT: (return)
267+
;; OPEN_WORLD-NEXT: )
268+
;; OPEN_WORLD-NEXT: )
269+
;; OPEN_WORLD-NEXT: )
270+
(func $run (export "run")
271+
(drop
272+
(block $block (result (ref $cont))
273+
(resume $cont (on $tag $block)
274+
(cont.new $cont
275+
(i32.const 42)
276+
(ref.func $func)
277+
)
278+
)
279+
(return)
280+
)
281+
)
282+
)
283+
)

0 commit comments

Comments
 (0)