Skip to content

Commit 53712b6

Browse files
authored
[NFC] Add HeapType::getFeatures() (#6707)
1 parent 636d1b2 commit 53712b6

File tree

4 files changed

+95
-89
lines changed

4 files changed

+95
-89
lines changed

src/passes/StringLowering.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ struct StringLowering : public StringGathering {
283283
// explained we cannot do that - or before it, which is what we do here).
284284
for (auto& func : module->functions) {
285285
if (func->type.getRecGroup().size() != 1 ||
286-
!Type(func->type, Nullable).getFeatures().hasStrings()) {
286+
!func->type.getFeatures().hasStrings()) {
287287
continue;
288288
}
289289

src/wasm-type.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,9 @@ class HeapType {
451451
// Return the LUB of two HeapTypes, which may or may not exist.
452452
static std::optional<HeapType> getLeastUpperBound(HeapType a, HeapType b);
453453

454+
// Returns the feature set required to use this type.
455+
FeatureSet getFeatures() const;
456+
454457
// Helper allowing the value of `print(...)` to be sent to an ostream. Stores
455458
// a `TypeID` because `Type` is incomplete at this point and using a reference
456459
// makes it less convenient to use.

src/wasm/wasm-type.cpp

Lines changed: 90 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -900,92 +900,7 @@ Type Type::reinterpret() const {
900900
FeatureSet Type::getFeatures() const {
901901
auto getSingleFeatures = [](Type t) -> FeatureSet {
902902
if (t.isRef()) {
903-
// A reference type implies we need that feature. Some also require
904-
// more, such as GC or exceptions, and may require us to look into child
905-
// types.
906-
struct ReferenceFeatureCollector
907-
: HeapTypeChildWalker<ReferenceFeatureCollector> {
908-
FeatureSet feats = FeatureSet::None;
909-
910-
void noteChild(HeapType* heapType) {
911-
if (heapType->isBasic()) {
912-
switch (heapType->getBasic(Unshared)) {
913-
case HeapType::ext:
914-
case HeapType::func:
915-
feats |= FeatureSet::ReferenceTypes;
916-
return;
917-
case HeapType::any:
918-
case HeapType::eq:
919-
case HeapType::i31:
920-
case HeapType::struct_:
921-
case HeapType::array:
922-
feats |= FeatureSet::ReferenceTypes | FeatureSet::GC;
923-
return;
924-
case HeapType::string:
925-
feats |= FeatureSet::ReferenceTypes | FeatureSet::Strings;
926-
return;
927-
case HeapType::none:
928-
case HeapType::noext:
929-
case HeapType::nofunc:
930-
// Technically introduced in GC, but used internally as part of
931-
// ref.null with just reference types.
932-
feats |= FeatureSet::ReferenceTypes;
933-
return;
934-
case HeapType::exn:
935-
case HeapType::noexn:
936-
feats |=
937-
FeatureSet::ExceptionHandling | FeatureSet::ReferenceTypes;
938-
return;
939-
case HeapType::cont:
940-
case HeapType::nocont:
941-
feats |= FeatureSet::TypedContinuations;
942-
return;
943-
}
944-
}
945-
946-
if (heapType->getRecGroup().size() > 1 ||
947-
heapType->getDeclaredSuperType() || heapType->isOpen()) {
948-
feats |= FeatureSet::ReferenceTypes | FeatureSet::GC;
949-
}
950-
951-
if (heapType->isShared()) {
952-
feats |= FeatureSet::SharedEverything;
953-
}
954-
955-
if (heapType->isStruct() || heapType->isArray()) {
956-
feats |= FeatureSet::ReferenceTypes | FeatureSet::GC;
957-
} else if (heapType->isSignature()) {
958-
// This is a function reference, which requires reference types and
959-
// possibly also multivalue (if it has multiple returns). Note that
960-
// technically typed function references also require GC, however,
961-
// we use these types internally regardless of the presence of GC
962-
// (in particular, since during load of the wasm we don't know the
963-
// features yet, so we apply the more refined types), so we don't
964-
// add that in any case here.
965-
feats |= FeatureSet::ReferenceTypes;
966-
auto sig = heapType->getSignature();
967-
if (sig.results.isTuple()) {
968-
feats |= FeatureSet::Multivalue;
969-
}
970-
} else if (heapType->isContinuation()) {
971-
feats |= FeatureSet::TypedContinuations;
972-
}
973-
974-
// In addition, scan their non-ref children, to add dependencies on
975-
// things like SIMD.
976-
for (auto child : heapType->getTypeChildren()) {
977-
if (!child.isRef()) {
978-
feats |= child.getFeatures();
979-
}
980-
}
981-
}
982-
};
983-
984-
ReferenceFeatureCollector collector;
985-
auto heapType = t.getHeapType();
986-
collector.walkRoot(&heapType);
987-
collector.noteChild(&heapType);
988-
return collector.feats;
903+
return t.getHeapType().getFeatures();
989904
}
990905

991906
switch (t.getBasic()) {
@@ -1604,6 +1519,95 @@ size_t HeapType::getRecGroupIndex() const {
16041519
return getHeapTypeInfo(*this)->recGroupIndex;
16051520
}
16061521

1522+
FeatureSet HeapType::getFeatures() const {
1523+
// Collects features from a type + children.
1524+
struct ReferenceFeatureCollector
1525+
: HeapTypeChildWalker<ReferenceFeatureCollector> {
1526+
FeatureSet feats = FeatureSet::None;
1527+
1528+
void noteChild(HeapType* heapType) {
1529+
if (heapType->isBasic()) {
1530+
switch (heapType->getBasic(Unshared)) {
1531+
case HeapType::ext:
1532+
case HeapType::func:
1533+
feats |= FeatureSet::ReferenceTypes;
1534+
return;
1535+
case HeapType::any:
1536+
case HeapType::eq:
1537+
case HeapType::i31:
1538+
case HeapType::struct_:
1539+
case HeapType::array:
1540+
feats |= FeatureSet::ReferenceTypes | FeatureSet::GC;
1541+
return;
1542+
case HeapType::string:
1543+
feats |= FeatureSet::ReferenceTypes | FeatureSet::Strings;
1544+
return;
1545+
case HeapType::none:
1546+
case HeapType::noext:
1547+
case HeapType::nofunc:
1548+
// Technically introduced in GC, but used internally as part of
1549+
// ref.null with just reference types.
1550+
feats |= FeatureSet::ReferenceTypes;
1551+
return;
1552+
case HeapType::exn:
1553+
case HeapType::noexn:
1554+
feats |= FeatureSet::ExceptionHandling | FeatureSet::ReferenceTypes;
1555+
return;
1556+
case HeapType::cont:
1557+
case HeapType::nocont:
1558+
feats |= FeatureSet::TypedContinuations;
1559+
return;
1560+
}
1561+
}
1562+
1563+
if (heapType->getRecGroup().size() > 1 ||
1564+
heapType->getDeclaredSuperType() || heapType->isOpen()) {
1565+
feats |= FeatureSet::ReferenceTypes | FeatureSet::GC;
1566+
}
1567+
1568+
if (heapType->isShared()) {
1569+
feats |= FeatureSet::SharedEverything;
1570+
}
1571+
1572+
if (heapType->isStruct() || heapType->isArray()) {
1573+
feats |= FeatureSet::ReferenceTypes | FeatureSet::GC;
1574+
} else if (heapType->isSignature()) {
1575+
// This is a function reference, which requires reference types and
1576+
// possibly also multivalue (if it has multiple returns). Note that
1577+
// technically typed function references also require GC, however,
1578+
// we use these types internally regardless of the presence of GC
1579+
// (in particular, since during load of the wasm we don't know the
1580+
// features yet, so we apply the more refined types), so we don't
1581+
// add that in any case here.
1582+
feats |= FeatureSet::ReferenceTypes;
1583+
auto sig = heapType->getSignature();
1584+
if (sig.results.isTuple()) {
1585+
feats |= FeatureSet::Multivalue;
1586+
}
1587+
} else if (heapType->isContinuation()) {
1588+
feats |= FeatureSet::TypedContinuations;
1589+
}
1590+
1591+
// In addition, scan their non-ref children, to add dependencies on
1592+
// things like SIMD.
1593+
for (auto child : heapType->getTypeChildren()) {
1594+
if (!child.isRef()) {
1595+
feats |= child.getFeatures();
1596+
}
1597+
}
1598+
}
1599+
};
1600+
1601+
ReferenceFeatureCollector collector;
1602+
// For internal reasons, the walkRoot/noteChild APIs all require non-const
1603+
// pointers. We only use them to scan the type, so it is safe for us to
1604+
// send |this| there from a |const| method.
1605+
auto* unconst = const_cast<HeapType*>(this);
1606+
collector.walkRoot(unconst);
1607+
collector.noteChild(unconst);
1608+
return collector.feats;
1609+
}
1610+
16071611
HeapType RecGroup::Iterator::operator*() const {
16081612
if (parent->id & 1) {
16091613
// This is a trivial recursion group. Mask off the low bit to recover the

src/wasm/wasm-validator.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3389,8 +3389,7 @@ void FunctionValidator::visitFunction(Function* curr) {
33893389
// Check for things like having a rec group with GC enabled. The type we're
33903390
// checking is a reference type even if this an MVP function type, so ignore
33913391
// the reference types feature here.
3392-
features |=
3393-
(Type(curr->type, Nullable).getFeatures() & ~FeatureSet::ReferenceTypes);
3392+
features |= (curr->type.getFeatures() & ~FeatureSet::ReferenceTypes);
33943393
for (const auto& param : curr->getParams()) {
33953394
features |= param.getFeatures();
33963395
shouldBeTrue(param.isConcrete(), curr, "params must be concretely typed");

0 commit comments

Comments
 (0)