summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-02-28 12:30:40 -0800
committerGitHub <noreply@github.com>2024-02-28 12:30:40 -0800
commitbaefd93d0a00cd33efecfd85e1a4d325457287f1 (patch)
tree720155a58943f6508e67e4fff075e33b0b242555 /src
parent1ef95ae7b9e2c765abbbc6af6dff6c29c1fa4d13 (diff)
downloadbinaryen-baefd93d0a00cd33efecfd85e1a4d325457287f1.tar.gz
binaryen-baefd93d0a00cd33efecfd85e1a4d325457287f1.tar.bz2
binaryen-baefd93d0a00cd33efecfd85e1a4d325457287f1.zip
[NFC] Add some comments about flow in SubtypingDiscoverer and Unsubtyping (#6359)
I audited all of SubtypingDiscoverer for flow/non-flow constraints and added some comments to clarify things for our future selves if we ever need to generalize it.
Diffstat (limited to 'src')
-rw-r--r--src/ir/subtype-exprs.h7
-rw-r--r--src/passes/Unsubtyping.cpp11
2 files changed, 18 insertions, 0 deletions
diff --git a/src/ir/subtype-exprs.h b/src/ir/subtype-exprs.h
index 1c922521f..ab0ace53d 100644
--- a/src/ir/subtype-exprs.h
+++ b/src/ir/subtype-exprs.h
@@ -161,6 +161,8 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
// sources, call_indirect target types may be supertypes of their source
// table types. In this case, the cast will always succeed, but only if we
// keep the types related.
+ // TODO: No value flows here, so we could use |noteNonFlowSubtype|, but
+ // this is a trivial situation that is not worth optimizing.
self()->noteSubtype(tableType, curr->heapType);
} else if (HeapType::isSubType(curr->heapType, tableType)) {
self()->noteCast(tableType, curr->heapType);
@@ -256,6 +258,8 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
void visitTupleExtract(TupleExtract* curr) {}
void visitRefI31(RefI31* curr) {}
void visitI31Get(I31Get* curr) {
+ // This could be |noteNonFlowSubtype| but as there are no subtypes of i31
+ // it does not matter.
self()->noteSubtype(curr->i31, Type(HeapType::i31, Nullable));
}
void visitCallRef(CallRef* curr) {
@@ -271,6 +275,9 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
// generalize, should they generalize the target more or the parameters
// more? etc.), so we do the simple thing here for now of requiring the
// target type not generalize.
+ //
+ // Note that this could be |noteNonFlowSubtype| but since we are comparing
+ // a type to itself here, that does not matter.
self()->noteSubtype(curr->target, curr->target->type);
if (curr->target->type.isSignature()) {
diff --git a/src/passes/Unsubtyping.cpp b/src/passes/Unsubtyping.cpp
index 897511c35..ccad4ed3d 100644
--- a/src/passes/Unsubtyping.cpp
+++ b/src/passes/Unsubtyping.cpp
@@ -201,6 +201,17 @@ struct Unsubtyping
// basic type then we can simply ignore this: we only remove subtyping
// between user types, so subtyping wrt basic types is unchanged, and so
// this constraint will never be a problem.
+ //
+ // This is sort of a hack because in general to be precise we should not
+ // just consider basic types here - in general, we should note for each
+ // constraint whether it is a flow-based one or not, and only take the
+ // flow-based ones into account when looking at the impact of casts.
+ // However, in practice this is enough as the only non-trivial case of
+ // |noteNonFlowSubtype| is for RefEq, which uses a basic type (eqref). Other
+ // cases of non-flow subtyping end up trivial, e.g., the target of a
+ // CallRef is compared to itself (and we ignore constraints of A :> A).
+ // However, if we change how |noteNonFlowSubtype| is used in
+ // SubtypingDiscoverer then we may need to generalize this.
if (super.isRef() && super.getHeapType().isBasic()) {
return;
}