@@ -167,12 +167,10 @@ struct FunctionStructValuesMap
167167//
168168// void noteRMW(Expression* expr, HeapType type, Index index, T& info);
169169//
170- // * Note a copied value (read from this field and written to the same, possibly
171- // in another object). Note that we require that the two types (the one read
172- // from, and written to) are identical; allowing subtyping is possible, but
173- // would add complexity amid diminishing returns.
170+ // * Note a copied value (read from a struct field and written to another struct
171+ // field).
174172//
175- // void noteCopy(HeapType type , Index index, T& info);
173+ // void noteCopy(StructGet* src, Type dstType , Index index, T& info);
176174//
177175// * Note a read.
178176//
@@ -214,7 +212,7 @@ struct StructScanner
214212 if (curr->isWithDefault ()) {
215213 self ().noteDefault (fields[i].type , heapType, i, infos[i]);
216214 } else {
217- noteExpressionOrCopy (curr->operands [i], heapType , i, infos[i]);
215+ noteExpressionOrCopy (curr->operands [i], type , i, infos[i]);
218216 }
219217 }
220218
@@ -233,7 +231,7 @@ struct StructScanner
233231 auto ht = std::make_pair (type.getHeapType (), type.getExactness ());
234232 noteExpressionOrCopy (
235233 curr->value ,
236- type. getHeapType () ,
234+ type,
237235 curr->index ,
238236 functionSetGetInfos[this ->getFunction ()][ht][curr->index ]);
239237 }
@@ -265,7 +263,7 @@ struct StructScanner
265263 if (curr->op == RMWXchg) {
266264 // An xchg is really like a read and write combined.
267265 self ().noteRead (heapType, index, info);
268- noteExpressionOrCopy (curr->value , heapType , index, info);
266+ noteExpressionOrCopy (curr->value , type , index, info);
269267 return ;
270268 }
271269
@@ -287,7 +285,7 @@ struct StructScanner
287285
288286 // A cmpxchg is like a read and conditional write.
289287 self ().noteRead (heapType, index, info);
290- noteExpressionOrCopy (curr->replacement , heapType , index, info);
288+ noteExpressionOrCopy (curr->replacement , type , index, info);
291289 }
292290
293291 void visitRefCast (RefCast* curr) {
@@ -327,27 +325,22 @@ struct StructScanner
327325 }
328326 }
329327
330- void
331- noteExpressionOrCopy (Expression* expr, HeapType type, Index index, T& info) {
332- // Look at the value falling through, if it has the exact same type
333- // (otherwise, we'd need to consider both the type actually written and the
334- // type of the fallthrough, somehow).
335- auto * fallthrough = Properties::getFallthrough (
336- expr,
337- this ->getPassOptions (),
338- *this ->getModule (),
339- static_cast <SubType*>(this )->getFallthroughBehavior ());
328+ void noteExpressionOrCopy (Expression* expr, Type type, Index index, T& info) {
329+ auto * fallthrough =
330+ Properties::getFallthrough (expr,
331+ this ->getPassOptions (),
332+ *this ->getModule (),
333+ self ().getFallthroughBehavior ());
334+ // TODO: Consider lifting this restriction on the use of fallthrough values.
340335 if (fallthrough->type == expr->type ) {
341336 expr = fallthrough;
342337 }
343- if (auto * get = expr->dynCast <StructGet>()) {
344- if (get->index == index && get->ref ->type != Type::unreachable &&
345- get->ref ->type .getHeapType () == type) {
346- static_cast <SubType*>(this )->noteCopy (type, index, info);
347- return ;
348- }
338+ if (auto * get = expr->dynCast <StructGet>();
339+ get && get->ref ->type .isStruct ()) {
340+ self ().noteCopy (get, type, index, info);
341+ return ;
349342 }
350- static_cast <SubType*>( this )-> noteExpression (expr, type, index, info);
343+ self (). noteExpression (expr, type. getHeapType () , index, info);
351344 }
352345
353346 Properties::FallthroughBehavior getFallthroughBehavior () {
0 commit comments