summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-06-27 10:25:05 -0700
committerGitHub <noreply@github.com>2024-06-27 10:25:05 -0700
commit53712b6d6e93449a6faf18a55e0fb29022f158df (patch)
tree2e110e33c202f0f7294bef16eb4a77d982fa498e /src
parent636d1b2af6f349a9c7fca908bad05108419835e3 (diff)
downloadbinaryen-53712b6d6e93449a6faf18a55e0fb29022f158df.tar.gz
binaryen-53712b6d6e93449a6faf18a55e0fb29022f158df.tar.bz2
binaryen-53712b6d6e93449a6faf18a55e0fb29022f158df.zip
[NFC] Add HeapType::getFeatures() (#6707)
Diffstat (limited to 'src')
-rw-r--r--src/passes/StringLowering.cpp2
-rw-r--r--src/wasm-type.h3
-rw-r--r--src/wasm/wasm-type.cpp176
-rw-r--r--src/wasm/wasm-validator.cpp3
4 files changed, 95 insertions, 89 deletions
diff --git a/src/passes/StringLowering.cpp b/src/passes/StringLowering.cpp
index ca0ba773c..f735b9ab2 100644
--- a/src/passes/StringLowering.cpp
+++ b/src/passes/StringLowering.cpp
@@ -283,7 +283,7 @@ struct StringLowering : public StringGathering {
// explained we cannot do that - or before it, which is what we do here).
for (auto& func : module->functions) {
if (func->type.getRecGroup().size() != 1 ||
- !Type(func->type, Nullable).getFeatures().hasStrings()) {
+ !func->type.getFeatures().hasStrings()) {
continue;
}
diff --git a/src/wasm-type.h b/src/wasm-type.h
index 51d945b53..69b50c07f 100644
--- a/src/wasm-type.h
+++ b/src/wasm-type.h
@@ -451,6 +451,9 @@ public:
// Return the LUB of two HeapTypes, which may or may not exist.
static std::optional<HeapType> getLeastUpperBound(HeapType a, HeapType b);
+ // Returns the feature set required to use this type.
+ FeatureSet getFeatures() const;
+
// Helper allowing the value of `print(...)` to be sent to an ostream. Stores
// a `TypeID` because `Type` is incomplete at this point and using a reference
// makes it less convenient to use.
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index 92c68d8be..6328180f8 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -900,92 +900,7 @@ Type Type::reinterpret() const {
FeatureSet Type::getFeatures() const {
auto getSingleFeatures = [](Type t) -> FeatureSet {
if (t.isRef()) {
- // A reference type implies we need that feature. Some also require
- // more, such as GC or exceptions, and may require us to look into child
- // types.
- struct ReferenceFeatureCollector
- : HeapTypeChildWalker<ReferenceFeatureCollector> {
- FeatureSet feats = FeatureSet::None;
-
- void noteChild(HeapType* heapType) {
- if (heapType->isBasic()) {
- switch (heapType->getBasic(Unshared)) {
- case HeapType::ext:
- case HeapType::func:
- feats |= FeatureSet::ReferenceTypes;
- return;
- case HeapType::any:
- case HeapType::eq:
- case HeapType::i31:
- case HeapType::struct_:
- case HeapType::array:
- feats |= FeatureSet::ReferenceTypes | FeatureSet::GC;
- return;
- case HeapType::string:
- feats |= FeatureSet::ReferenceTypes | FeatureSet::Strings;
- return;
- case HeapType::none:
- case HeapType::noext:
- case HeapType::nofunc:
- // Technically introduced in GC, but used internally as part of
- // ref.null with just reference types.
- feats |= FeatureSet::ReferenceTypes;
- return;
- case HeapType::exn:
- case HeapType::noexn:
- feats |=
- FeatureSet::ExceptionHandling | FeatureSet::ReferenceTypes;
- return;
- case HeapType::cont:
- case HeapType::nocont:
- feats |= FeatureSet::TypedContinuations;
- return;
- }
- }
-
- if (heapType->getRecGroup().size() > 1 ||
- heapType->getDeclaredSuperType() || heapType->isOpen()) {
- feats |= FeatureSet::ReferenceTypes | FeatureSet::GC;
- }
-
- if (heapType->isShared()) {
- feats |= FeatureSet::SharedEverything;
- }
-
- if (heapType->isStruct() || heapType->isArray()) {
- feats |= FeatureSet::ReferenceTypes | FeatureSet::GC;
- } else if (heapType->isSignature()) {
- // This is a function reference, which requires reference types and
- // possibly also multivalue (if it has multiple returns). Note that
- // technically typed function references also require GC, however,
- // we use these types internally regardless of the presence of GC
- // (in particular, since during load of the wasm we don't know the
- // features yet, so we apply the more refined types), so we don't
- // add that in any case here.
- feats |= FeatureSet::ReferenceTypes;
- auto sig = heapType->getSignature();
- if (sig.results.isTuple()) {
- feats |= FeatureSet::Multivalue;
- }
- } else if (heapType->isContinuation()) {
- feats |= FeatureSet::TypedContinuations;
- }
-
- // In addition, scan their non-ref children, to add dependencies on
- // things like SIMD.
- for (auto child : heapType->getTypeChildren()) {
- if (!child.isRef()) {
- feats |= child.getFeatures();
- }
- }
- }
- };
-
- ReferenceFeatureCollector collector;
- auto heapType = t.getHeapType();
- collector.walkRoot(&heapType);
- collector.noteChild(&heapType);
- return collector.feats;
+ return t.getHeapType().getFeatures();
}
switch (t.getBasic()) {
@@ -1604,6 +1519,95 @@ size_t HeapType::getRecGroupIndex() const {
return getHeapTypeInfo(*this)->recGroupIndex;
}
+FeatureSet HeapType::getFeatures() const {
+ // Collects features from a type + children.
+ struct ReferenceFeatureCollector
+ : HeapTypeChildWalker<ReferenceFeatureCollector> {
+ FeatureSet feats = FeatureSet::None;
+
+ void noteChild(HeapType* heapType) {
+ if (heapType->isBasic()) {
+ switch (heapType->getBasic(Unshared)) {
+ case HeapType::ext:
+ case HeapType::func:
+ feats |= FeatureSet::ReferenceTypes;
+ return;
+ case HeapType::any:
+ case HeapType::eq:
+ case HeapType::i31:
+ case HeapType::struct_:
+ case HeapType::array:
+ feats |= FeatureSet::ReferenceTypes | FeatureSet::GC;
+ return;
+ case HeapType::string:
+ feats |= FeatureSet::ReferenceTypes | FeatureSet::Strings;
+ return;
+ case HeapType::none:
+ case HeapType::noext:
+ case HeapType::nofunc:
+ // Technically introduced in GC, but used internally as part of
+ // ref.null with just reference types.
+ feats |= FeatureSet::ReferenceTypes;
+ return;
+ case HeapType::exn:
+ case HeapType::noexn:
+ feats |= FeatureSet::ExceptionHandling | FeatureSet::ReferenceTypes;
+ return;
+ case HeapType::cont:
+ case HeapType::nocont:
+ feats |= FeatureSet::TypedContinuations;
+ return;
+ }
+ }
+
+ if (heapType->getRecGroup().size() > 1 ||
+ heapType->getDeclaredSuperType() || heapType->isOpen()) {
+ feats |= FeatureSet::ReferenceTypes | FeatureSet::GC;
+ }
+
+ if (heapType->isShared()) {
+ feats |= FeatureSet::SharedEverything;
+ }
+
+ if (heapType->isStruct() || heapType->isArray()) {
+ feats |= FeatureSet::ReferenceTypes | FeatureSet::GC;
+ } else if (heapType->isSignature()) {
+ // This is a function reference, which requires reference types and
+ // possibly also multivalue (if it has multiple returns). Note that
+ // technically typed function references also require GC, however,
+ // we use these types internally regardless of the presence of GC
+ // (in particular, since during load of the wasm we don't know the
+ // features yet, so we apply the more refined types), so we don't
+ // add that in any case here.
+ feats |= FeatureSet::ReferenceTypes;
+ auto sig = heapType->getSignature();
+ if (sig.results.isTuple()) {
+ feats |= FeatureSet::Multivalue;
+ }
+ } else if (heapType->isContinuation()) {
+ feats |= FeatureSet::TypedContinuations;
+ }
+
+ // In addition, scan their non-ref children, to add dependencies on
+ // things like SIMD.
+ for (auto child : heapType->getTypeChildren()) {
+ if (!child.isRef()) {
+ feats |= child.getFeatures();
+ }
+ }
+ }
+ };
+
+ ReferenceFeatureCollector collector;
+ // For internal reasons, the walkRoot/noteChild APIs all require non-const
+ // pointers. We only use them to scan the type, so it is safe for us to
+ // send |this| there from a |const| method.
+ auto* unconst = const_cast<HeapType*>(this);
+ collector.walkRoot(unconst);
+ collector.noteChild(unconst);
+ return collector.feats;
+}
+
HeapType RecGroup::Iterator::operator*() const {
if (parent->id & 1) {
// This is a trivial recursion group. Mask off the low bit to recover the
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 281f3ec45..a491fb951 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -3389,8 +3389,7 @@ void FunctionValidator::visitFunction(Function* curr) {
// Check for things like having a rec group with GC enabled. The type we're
// checking is a reference type even if this an MVP function type, so ignore
// the reference types feature here.
- features |=
- (Type(curr->type, Nullable).getFeatures() & ~FeatureSet::ReferenceTypes);
+ features |= (curr->type.getFeatures() & ~FeatureSet::ReferenceTypes);
for (const auto& param : curr->getParams()) {
features |= param.getFeatures();
shouldBeTrue(param.isConcrete(), curr, "params must be concretely typed");