Skip to content

Commit ca59e79

Browse files
authored
[Custom Descriptors] Effects for br_on_cast_desc (#7739)
We previously handled trapping effects for null descriptors for struct.new and ref.cast_desc, but we were missing the effects for br_on_cast_desc. Unify the handling of the effects for all these instructions and add more tests for the new and existing functionality.
1 parent 8fd7cef commit ca59e79

File tree

5 files changed

+277
-42
lines changed

5 files changed

+277
-42
lines changed

scripts/test/fuzzing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,12 @@
125125
'minimize-rec-groups-desc.wast',
126126
'precompute-desc.wast',
127127
'gc-desc.wast',
128-
'simplify-locals-desc.wast',
129128
'optimize-instructions-desc.wast',
130129
'gto-desc.wast',
131130
'type-ssa-desc.wast',
132131
'abstract-type-refining-desc.wast',
133132
'remove-unused-brs-desc.wast',
133+
'vacuum-desc.wast',
134134
# TODO: fix split_wast() on tricky escaping situations like a string ending
135135
# in \\" (the " is not escaped - there is an escaped \ before it)
136136
'string-lifting-section.wast',

src/ir/effects.h

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -849,25 +849,30 @@ class EffectAnalyzer {
849849
}
850850
}
851851
void visitRefTest(RefTest* curr) {}
852+
void maybeHandleDescriptor(Expression* desc) {
853+
if (desc) {
854+
// Traps when the descriptor is null.
855+
if (desc->type.isNull()) {
856+
parent.trap = true;
857+
} else if (desc->type.isNullable()) {
858+
parent.implicitTrap = true;
859+
}
860+
}
861+
}
852862
void visitRefCast(RefCast* curr) {
853863
// Traps if the cast fails.
854864
parent.implicitTrap = true;
865+
maybeHandleDescriptor(curr->desc);
855866
}
856867
void visitRefGetDesc(RefGetDesc* curr) {
857868
// Traps if the ref is null.
858869
parent.implicitTrap = true;
859870
}
860-
void visitBrOn(BrOn* curr) { parent.breakTargets.insert(curr->name); }
861-
void visitStructNew(StructNew* curr) {
862-
if (curr->desc) {
863-
// Traps when the descriptor is null.
864-
if (curr->desc->type.isNull()) {
865-
parent.trap = true;
866-
} else if (curr->desc->type.isNullable()) {
867-
parent.implicitTrap = true;
868-
}
869-
}
871+
void visitBrOn(BrOn* curr) {
872+
parent.breakTargets.insert(curr->name);
873+
maybeHandleDescriptor(curr->desc);
870874
}
875+
void visitStructNew(StructNew* curr) { maybeHandleDescriptor(curr->desc); }
871876
void visitStructGet(StructGet* curr) {
872877
if (curr->ref->type == Type::unreachable) {
873878
return;

src/passes/OptimizeCasts.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ struct EarlyCastFinder
167167

168168
// TODO: generalize this when we handle more than RefAsNonNull.
169169
RefCast dummyRefCast(module->allocator);
170+
dummyRefCast.desc = nullptr;
170171
RefAs dummyRefAs(module->allocator);
171172
dummyRefAs.op = RefAsNonNull;
172173

test/lit/passes/simplify-locals-desc.wast

Lines changed: 0 additions & 31 deletions
This file was deleted.

test/lit/passes/vacuum-desc.wast

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
2+
3+
;; RUN: wasm-opt -all %s --vacuum -S -o - | filecheck %s
4+
;; RUN: wasm-opt -all %s --vacuum --ignore-implicit-traps -S -o - | filecheck %s --check-prefix=CKIIT
5+
;; RUN: wasm-opt -all %s --vacuum --traps-never-happen -S -o - | filecheck %s --check-prefix=CKTNH
6+
7+
(module
8+
(rec
9+
;; CHECK: (rec
10+
;; CHECK-NEXT: (type $struct (descriptor $desc (struct)))
11+
;; CKIIT: (rec
12+
;; CKIIT-NEXT: (type $struct (descriptor $desc (struct)))
13+
;; CKTNH: (rec
14+
;; CKTNH-NEXT: (type $struct (descriptor $desc (struct)))
15+
(type $struct (descriptor $desc (struct)))
16+
;; CHECK: (type $desc (describes $struct (struct)))
17+
;; CKIIT: (type $desc (describes $struct (struct)))
18+
;; CKTNH: (type $desc (describes $struct (struct)))
19+
(type $desc (describes $struct (struct)))
20+
)
21+
22+
;; CHECK: (func $new-null-desc (type $5) (param $desc nullref)
23+
;; CHECK-NEXT: (drop
24+
;; CHECK-NEXT: (struct.new_default $struct
25+
;; CHECK-NEXT: (local.get $desc)
26+
;; CHECK-NEXT: )
27+
;; CHECK-NEXT: )
28+
;; CHECK-NEXT: )
29+
;; CKIIT: (func $new-null-desc (type $5) (param $desc nullref)
30+
;; CKIIT-NEXT: (drop
31+
;; CKIIT-NEXT: (struct.new_default $struct
32+
;; CKIIT-NEXT: (local.get $desc)
33+
;; CKIIT-NEXT: )
34+
;; CKIIT-NEXT: )
35+
;; CKIIT-NEXT: )
36+
;; CKTNH: (func $new-null-desc (type $5) (param $desc nullref)
37+
;; CKTNH-NEXT: (nop)
38+
;; CKTNH-NEXT: )
39+
(func $new-null-desc (param $desc nullref)
40+
(drop
41+
(struct.new $struct
42+
(local.get $desc)
43+
)
44+
)
45+
)
46+
47+
;; CHECK: (func $new-nullable-desc (type $6) (param $desc (ref null (exact $desc)))
48+
;; CHECK-NEXT: (drop
49+
;; CHECK-NEXT: (struct.new_default $struct
50+
;; CHECK-NEXT: (local.get $desc)
51+
;; CHECK-NEXT: )
52+
;; CHECK-NEXT: )
53+
;; CHECK-NEXT: )
54+
;; CKIIT: (func $new-nullable-desc (type $6) (param $desc (ref null (exact $desc)))
55+
;; CKIIT-NEXT: (nop)
56+
;; CKIIT-NEXT: )
57+
;; CKTNH: (func $new-nullable-desc (type $6) (param $desc (ref null (exact $desc)))
58+
;; CKTNH-NEXT: (nop)
59+
;; CKTNH-NEXT: )
60+
(func $new-nullable-desc (param $desc (ref null (exact $desc)))
61+
(drop
62+
(struct.new $struct
63+
(local.get $desc)
64+
)
65+
)
66+
)
67+
68+
;; CHECK: (func $new-non-nullable-desc (type $7) (param $desc (ref (exact $desc)))
69+
;; CHECK-NEXT: (nop)
70+
;; CHECK-NEXT: )
71+
;; CKIIT: (func $new-non-nullable-desc (type $7) (param $desc (ref (exact $desc)))
72+
;; CKIIT-NEXT: (nop)
73+
;; CKIIT-NEXT: )
74+
;; CKTNH: (func $new-non-nullable-desc (type $7) (param $desc (ref (exact $desc)))
75+
;; CKTNH-NEXT: (nop)
76+
;; CKTNH-NEXT: )
77+
(func $new-non-nullable-desc (param $desc (ref (exact $desc)))
78+
(drop
79+
(struct.new $struct
80+
(local.get $desc)
81+
)
82+
)
83+
)
84+
85+
;; CHECK: (func $cast-null-desc (type $2) (param $ref anyref) (param $desc nullref)
86+
;; CHECK-NEXT: (drop
87+
;; CHECK-NEXT: (block ;; (replaces unreachable RefCast we can't emit)
88+
;; CHECK-NEXT: (drop
89+
;; CHECK-NEXT: (local.get $ref)
90+
;; CHECK-NEXT: )
91+
;; CHECK-NEXT: (drop
92+
;; CHECK-NEXT: (local.get $desc)
93+
;; CHECK-NEXT: )
94+
;; CHECK-NEXT: (unreachable)
95+
;; CHECK-NEXT: )
96+
;; CHECK-NEXT: )
97+
;; CHECK-NEXT: )
98+
;; CKIIT: (func $cast-null-desc (type $2) (param $ref anyref) (param $desc nullref)
99+
;; CKIIT-NEXT: (drop
100+
;; CKIIT-NEXT: (block ;; (replaces unreachable RefCast we can't emit)
101+
;; CKIIT-NEXT: (drop
102+
;; CKIIT-NEXT: (local.get $ref)
103+
;; CKIIT-NEXT: )
104+
;; CKIIT-NEXT: (drop
105+
;; CKIIT-NEXT: (local.get $desc)
106+
;; CKIIT-NEXT: )
107+
;; CKIIT-NEXT: (unreachable)
108+
;; CKIIT-NEXT: )
109+
;; CKIIT-NEXT: )
110+
;; CKIIT-NEXT: )
111+
;; CKTNH: (func $cast-null-desc (type $2) (param $ref anyref) (param $desc nullref)
112+
;; CKTNH-NEXT: (nop)
113+
;; CKTNH-NEXT: )
114+
(func $cast-null-desc (param $ref anyref) (param $desc nullref)
115+
(drop
116+
(ref.cast_desc (ref null $struct)
117+
(local.get $ref)
118+
(local.get $desc)
119+
)
120+
)
121+
)
122+
123+
;; CHECK: (func $cast-nullable-desc (type $3) (param $ref anyref) (param $desc (ref null $desc))
124+
;; CHECK-NEXT: (drop
125+
;; CHECK-NEXT: (ref.cast_desc (ref null $struct)
126+
;; CHECK-NEXT: (local.get $ref)
127+
;; CHECK-NEXT: (local.get $desc)
128+
;; CHECK-NEXT: )
129+
;; CHECK-NEXT: )
130+
;; CHECK-NEXT: )
131+
;; CKIIT: (func $cast-nullable-desc (type $3) (param $ref anyref) (param $desc (ref null $desc))
132+
;; CKIIT-NEXT: (nop)
133+
;; CKIIT-NEXT: )
134+
;; CKTNH: (func $cast-nullable-desc (type $3) (param $ref anyref) (param $desc (ref null $desc))
135+
;; CKTNH-NEXT: (nop)
136+
;; CKTNH-NEXT: )
137+
(func $cast-nullable-desc (param $ref anyref) (param $desc (ref null $desc))
138+
(drop
139+
(ref.cast_desc (ref null $struct)
140+
(local.get $ref)
141+
(local.get $desc)
142+
)
143+
)
144+
)
145+
146+
;; CHECK: (func $cast-non-nullable-desc (type $4) (param $ref anyref) (param $desc (ref $desc))
147+
;; CHECK-NEXT: (drop
148+
;; CHECK-NEXT: (ref.cast_desc (ref null $struct)
149+
;; CHECK-NEXT: (local.get $ref)
150+
;; CHECK-NEXT: (local.get $desc)
151+
;; CHECK-NEXT: )
152+
;; CHECK-NEXT: )
153+
;; CHECK-NEXT: )
154+
;; CKIIT: (func $cast-non-nullable-desc (type $4) (param $ref anyref) (param $desc (ref $desc))
155+
;; CKIIT-NEXT: (nop)
156+
;; CKIIT-NEXT: )
157+
;; CKTNH: (func $cast-non-nullable-desc (type $4) (param $ref anyref) (param $desc (ref $desc))
158+
;; CKTNH-NEXT: (nop)
159+
;; CKTNH-NEXT: )
160+
(func $cast-non-nullable-desc (param $ref anyref) (param $desc (ref $desc))
161+
(drop
162+
;; The cast can still trap on failure, so by default we cannot remove it.
163+
(ref.cast_desc (ref null $struct)
164+
(local.get $ref)
165+
(local.get $desc)
166+
)
167+
)
168+
)
169+
170+
;; CHECK: (func $br-on-cast-null-desc (type $2) (param $ref anyref) (param $desc nullref)
171+
;; CHECK-NEXT: (drop
172+
;; CHECK-NEXT: (block $l (result anyref)
173+
;; CHECK-NEXT: (block ;; (replaces unreachable BrOn we can't emit)
174+
;; CHECK-NEXT: (drop
175+
;; CHECK-NEXT: (local.get $ref)
176+
;; CHECK-NEXT: )
177+
;; CHECK-NEXT: (drop
178+
;; CHECK-NEXT: (local.get $desc)
179+
;; CHECK-NEXT: )
180+
;; CHECK-NEXT: (unreachable)
181+
;; CHECK-NEXT: )
182+
;; CHECK-NEXT: )
183+
;; CHECK-NEXT: )
184+
;; CHECK-NEXT: )
185+
;; CKIIT: (func $br-on-cast-null-desc (type $2) (param $ref anyref) (param $desc nullref)
186+
;; CKIIT-NEXT: (drop
187+
;; CKIIT-NEXT: (block $l (result anyref)
188+
;; CKIIT-NEXT: (block ;; (replaces unreachable BrOn we can't emit)
189+
;; CKIIT-NEXT: (drop
190+
;; CKIIT-NEXT: (local.get $ref)
191+
;; CKIIT-NEXT: )
192+
;; CKIIT-NEXT: (drop
193+
;; CKIIT-NEXT: (local.get $desc)
194+
;; CKIIT-NEXT: )
195+
;; CKIIT-NEXT: (unreachable)
196+
;; CKIIT-NEXT: )
197+
;; CKIIT-NEXT: )
198+
;; CKIIT-NEXT: )
199+
;; CKIIT-NEXT: )
200+
;; CKTNH: (func $br-on-cast-null-desc (type $2) (param $ref anyref) (param $desc nullref)
201+
;; CKTNH-NEXT: (nop)
202+
;; CKTNH-NEXT: )
203+
(func $br-on-cast-null-desc (param $ref anyref) (param $desc nullref)
204+
(drop
205+
(block $l (result anyref)
206+
(br_on_cast_desc $l anyref (ref null $struct)
207+
(local.get $ref)
208+
(local.get $desc)
209+
)
210+
)
211+
)
212+
)
213+
214+
;; CHECK: (func $br-on-cast-nullable-desc (type $3) (param $ref anyref) (param $desc (ref null $desc))
215+
;; CHECK-NEXT: (drop
216+
;; CHECK-NEXT: (block $l (result anyref)
217+
;; CHECK-NEXT: (br_on_cast_desc $l anyref (ref null $struct)
218+
;; CHECK-NEXT: (local.get $ref)
219+
;; CHECK-NEXT: (local.get $desc)
220+
;; CHECK-NEXT: )
221+
;; CHECK-NEXT: )
222+
;; CHECK-NEXT: )
223+
;; CHECK-NEXT: )
224+
;; CKIIT: (func $br-on-cast-nullable-desc (type $3) (param $ref anyref) (param $desc (ref null $desc))
225+
;; CKIIT-NEXT: (nop)
226+
;; CKIIT-NEXT: )
227+
;; CKTNH: (func $br-on-cast-nullable-desc (type $3) (param $ref anyref) (param $desc (ref null $desc))
228+
;; CKTNH-NEXT: (nop)
229+
;; CKTNH-NEXT: )
230+
(func $br-on-cast-nullable-desc (param $ref anyref) (param $desc (ref null $desc))
231+
(drop
232+
(block $l (result anyref)
233+
(br_on_cast_desc $l anyref (ref null $struct)
234+
(local.get $ref)
235+
(local.get $desc)
236+
)
237+
)
238+
)
239+
)
240+
241+
;; CHECK: (func $br-on-cast-non-nullable-desc (type $4) (param $ref anyref) (param $desc (ref $desc))
242+
;; CHECK-NEXT: (nop)
243+
;; CHECK-NEXT: )
244+
;; CKIIT: (func $br-on-cast-non-nullable-desc (type $4) (param $ref anyref) (param $desc (ref $desc))
245+
;; CKIIT-NEXT: (nop)
246+
;; CKIIT-NEXT: )
247+
;; CKTNH: (func $br-on-cast-non-nullable-desc (type $4) (param $ref anyref) (param $desc (ref $desc))
248+
;; CKTNH-NEXT: (nop)
249+
;; CKTNH-NEXT: )
250+
(func $br-on-cast-non-nullable-desc (param $ref anyref) (param $desc (ref $desc))
251+
(drop
252+
(block $l (result anyref)
253+
(br_on_cast_desc $l anyref (ref null $struct)
254+
(local.get $ref)
255+
(local.get $desc)
256+
)
257+
)
258+
)
259+
)
260+
)

0 commit comments

Comments
 (0)