@@ -190,7 +190,10 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
190
190
void visitRefNull (RefNull* curr) {}
191
191
void visitRefIsNull (RefIsNull* curr) {}
192
192
void visitRefFunc (RefFunc* curr) {}
193
- void visitRefEq (RefEq* curr) {}
193
+ void visitRefEq (RefEq* curr) {
194
+ self ()->noteSubtype (curr->left , Type (HeapType::eq, Nullable));
195
+ self ()->noteSubtype (curr->right , Type (HeapType::eq, Nullable));
196
+ }
194
197
void visitTableGet (TableGet* curr) {}
195
198
void visitTableSet (TableSet* curr) {
196
199
self ()->noteSubtype (curr->value ,
@@ -225,12 +228,27 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
225
228
void visitTupleMake (TupleMake* curr) {}
226
229
void visitTupleExtract (TupleExtract* curr) {}
227
230
void visitRefI31 (RefI31* curr) {}
228
- void visitI31Get (I31Get* curr) {}
231
+ void visitI31Get (I31Get* curr) {
232
+ self ()->noteSubtype (curr->i31 , Type (HeapType::i31, Nullable));
233
+ }
229
234
void visitCallRef (CallRef* curr) {
230
- if (!curr->target ->type .isSignature ()) {
231
- return ;
235
+ // Even if we are unreachable, the target must be valid, and in particular
236
+ // it cannot be funcref - it must be a proper signature type. We could
237
+ // perhaps have |addStrictSubtype| to handle that, but for now just require
238
+ // that the target keep its type.
239
+ //
240
+ // Note that even if we are reachable, there is an interaction between the
241
+ // target and the the types of the parameters and results (the target's type
242
+ // must support the parameter and result types properly), and so it is not
243
+ // obvious how users would want to optimize here (if they are trying to
244
+ // generalize, should they generalize the target more or the parameters
245
+ // more? etc.), so we do the simple thing here for now of requiring the
246
+ // target type not generalize.
247
+ self ()->noteSubtype (curr->target , curr->target ->type );
248
+
249
+ if (curr->target ->type .isSignature ()) {
250
+ handleCall (curr, curr->target ->type .getHeapType ().getSignature ());
232
251
}
233
- handleCall (curr, curr->target ->type .getHeapType ().getSignature ());
234
252
}
235
253
void visitRefTest (RefTest* curr) {
236
254
self ()->noteCast (curr->ref , curr->castType );
@@ -286,13 +304,14 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
286
304
self ()->noteSubtype (value, array.element .type );
287
305
}
288
306
}
307
+
289
308
void visitArrayGet (ArrayGet* curr) {}
290
309
void visitArraySet (ArraySet* curr) {
291
310
if (!curr->ref ->type .isArray ()) {
292
311
return ;
293
312
}
294
313
auto array = curr->ref ->type .getHeapType ().getArray ();
295
- self ()->noteSubtype (curr->value -> type , array.element .type );
314
+ self ()->noteSubtype (curr->value , array.element .type );
296
315
}
297
316
void visitArrayLen (ArrayLen* curr) {}
298
317
void visitArrayCopy (ArrayCopy* curr) {
@@ -308,7 +327,7 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
308
327
return ;
309
328
}
310
329
auto array = curr->ref ->type .getHeapType ().getArray ();
311
- self ()->noteSubtype (curr->value -> type , array.element .type );
330
+ self ()->noteSubtype (curr->value , array.element .type );
312
331
}
313
332
void visitArrayInitData (ArrayInitData* curr) {}
314
333
void visitArrayInitElem (ArrayInitElem* curr) {
@@ -319,7 +338,11 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
319
338
auto * seg = self ()->getModule ()->getElementSegment (curr->segment );
320
339
self ()->noteSubtype (seg->type , array.element .type );
321
340
}
322
- void visitRefAs (RefAs* curr) {}
341
+ void visitRefAs (RefAs* curr) {
342
+ if (curr->op == RefAsNonNull) {
343
+ self ()->noteCast (curr->value , curr);
344
+ }
345
+ }
323
346
void visitStringNew (StringNew* curr) {}
324
347
void visitStringConst (StringConst* curr) {}
325
348
void visitStringMeasure (StringMeasure* curr) {}
0 commit comments