@@ -1503,49 +1503,64 @@ std::ostream& operator<<(std::ostream& os, Struct struct_) {
15031503std::ostream& operator <<(std::ostream& os, Array array) {
15041504 return TypePrinter (os).print (array);
15051505}
1506- std::ostream& operator <<(std::ostream& os, TypeBuilder::ErrorReason reason) {
1506+ std::ostream& operator <<(std::ostream& os,
1507+ TypeBuilder::ErrorReasonKind reason) {
15071508 switch (reason) {
1508- case TypeBuilder::ErrorReason ::SelfSupertype:
1509+ case TypeBuilder::ErrorReasonKind ::SelfSupertype:
15091510 return os << " Heap type is a supertype of itself" ;
1510- case TypeBuilder::ErrorReason ::InvalidSupertype:
1511+ case TypeBuilder::ErrorReasonKind ::InvalidSupertype:
15111512 return os << " Heap type has an invalid supertype" ;
1512- case TypeBuilder::ErrorReason ::ForwardSupertypeReference:
1513+ case TypeBuilder::ErrorReasonKind ::ForwardSupertypeReference:
15131514 return os << " Heap type has an undeclared supertype" ;
1514- case TypeBuilder::ErrorReason ::ForwardChildReference:
1515+ case TypeBuilder::ErrorReasonKind ::ForwardChildReference:
15151516 return os << " Heap type has an undeclared child" ;
1516- case TypeBuilder::ErrorReason ::InvalidFuncType:
1517+ case TypeBuilder::ErrorReasonKind ::InvalidFuncType:
15171518 return os << " Continuation has invalid function type" ;
1518- case TypeBuilder::ErrorReason ::InvalidSharedType:
1519+ case TypeBuilder::ErrorReasonKind ::InvalidSharedType:
15191520 return os << " Shared types require shared-everything" ;
1520- case TypeBuilder::ErrorReason ::InvalidWaitQueue:
1521+ case TypeBuilder::ErrorReasonKind ::InvalidWaitQueue:
15211522 return os << " Waitqueues require shared-everything" ;
1522- case TypeBuilder::ErrorReason ::InvalidStringType:
1523+ case TypeBuilder::ErrorReasonKind ::InvalidStringType:
15231524 return os << " String types require strings feature" ;
1524- case TypeBuilder::ErrorReason ::InvalidUnsharedField:
1525+ case TypeBuilder::ErrorReasonKind ::InvalidUnsharedField:
15251526 return os << " Heap type has an invalid unshared field" ;
1526- case TypeBuilder::ErrorReason ::NonStructDescribes:
1527+ case TypeBuilder::ErrorReasonKind ::NonStructDescribes:
15271528 return os << " Describes clause on a non-struct type" ;
1528- case TypeBuilder::ErrorReason ::ForwardDescribesReference:
1529+ case TypeBuilder::ErrorReasonKind ::ForwardDescribesReference:
15291530 return os << " Describes clause is a forward reference" ;
1530- case TypeBuilder::ErrorReason ::MismatchedDescribes:
1531+ case TypeBuilder::ErrorReasonKind ::MismatchedDescribes:
15311532 return os << " Described type is not a matching descriptor" ;
1532- case TypeBuilder::ErrorReason ::NonStructDescriptor:
1533+ case TypeBuilder::ErrorReasonKind ::NonStructDescriptor:
15331534 return os << " Descriptor clause on a non-struct type" ;
1534- case TypeBuilder::ErrorReason ::MismatchedDescriptor:
1535+ case TypeBuilder::ErrorReasonKind ::MismatchedDescriptor:
15351536 return os << " Descriptor type does not describe heap type" ;
1536- case TypeBuilder::ErrorReason ::InvalidUnsharedDescriptor:
1537+ case TypeBuilder::ErrorReasonKind ::InvalidUnsharedDescriptor:
15371538 return os << " Heap type has an invalid unshared descriptor" ;
1538- case TypeBuilder::ErrorReason ::InvalidUnsharedDescribes:
1539+ case TypeBuilder::ErrorReasonKind ::InvalidUnsharedDescribes:
15391540 return os << " Heap type describes an invalid unshared type" ;
1540- case TypeBuilder::ErrorReason ::RequiresCustomDescriptors:
1541+ case TypeBuilder::ErrorReasonKind ::RequiresCustomDescriptors:
15411542 return os << " custom descriptors required but not enabled" ;
1542- case TypeBuilder::ErrorReason ::RecGroupCollision:
1543+ case TypeBuilder::ErrorReasonKind ::RecGroupCollision:
15431544 return os
15441545 << " distinct rec groups would be identical after binary writing" ;
15451546 }
15461547 WASM_UNREACHABLE (" Unexpected error reason" );
15471548}
15481549
1550+ std::ostream& operator <<(std::ostream& os,
1551+ const TypeBuilder::ErrorReason& reason) {
1552+ os << reason.getKind ();
1553+ if (auto * collision = std::get_if<TypeBuilder::RecGroupCollision>(&reason)) {
1554+ if (collision->missingFeatures != FeatureSet (FeatureSet::None)) {
1555+ os << " (to resolve this, use" ;
1556+ collision->missingFeatures .iterFeatures (
1557+ [&](auto feat) { os << " --enable-" << FeatureSet::toString (feat); });
1558+ os << " )" ;
1559+ }
1560+ }
1561+ return os;
1562+ }
1563+
15491564unsigned Field::getByteSize () const {
15501565 if (type != Type::i32 ) {
15511566 return type.getByteSize ();
@@ -2413,13 +2428,13 @@ validateType(Type type, FeatureSet feats, bool isShared) {
24132428 if (type.isRef ()) {
24142429 auto heapType = type.getHeapType ();
24152430 if (isShared && !heapType.isShared ()) {
2416- return TypeBuilder::ErrorReason ::InvalidUnsharedField;
2431+ return TypeBuilder::ErrorReasonKind ::InvalidUnsharedField;
24172432 }
24182433 if (heapType.isShared () && !feats.hasSharedEverything ()) {
2419- return TypeBuilder::ErrorReason ::InvalidSharedType;
2434+ return TypeBuilder::ErrorReasonKind ::InvalidSharedType;
24202435 }
24212436 if (heapType.isString () && !feats.hasStrings ()) {
2422- return TypeBuilder::ErrorReason ::InvalidStringType;
2437+ return TypeBuilder::ErrorReasonKind ::InvalidStringType;
24232438 }
24242439 }
24252440 return std::nullopt ;
@@ -2433,7 +2448,7 @@ validateStruct(const Struct& struct_, FeatureSet feats, bool isShared) {
24332448 }
24342449 if (field.packedType == Field::PackedType::WaitQueue &&
24352450 !feats.hasSharedEverything ()) {
2436- return TypeBuilder::ErrorReason ::InvalidWaitQueue;
2451+ return TypeBuilder::ErrorReasonKind ::InvalidWaitQueue;
24372452 }
24382453 }
24392454 return std::nullopt ;
@@ -2464,10 +2479,10 @@ validateSignature(Signature sig, FeatureSet feats, bool isShared) {
24642479std::optional<TypeBuilder::ErrorReason>
24652480validateContinuation (Continuation cont, FeatureSet feats, bool isShared) {
24662481 if (!cont.type .isSignature ()) {
2467- return TypeBuilder::ErrorReason ::InvalidFuncType;
2482+ return TypeBuilder::ErrorReasonKind ::InvalidFuncType;
24682483 }
24692484 if (isShared != cont.type .isShared ()) {
2470- return TypeBuilder::ErrorReason ::InvalidFuncType;
2485+ return TypeBuilder::ErrorReasonKind ::InvalidFuncType;
24712486 }
24722487 return std::nullopt ;
24732488}
@@ -2480,48 +2495,48 @@ validateTypeInfo(HeapTypeInfo& info,
24802495 // The supertype must be canonical (i.e. defined in a previous rec group)
24812496 // or have already been defined in this rec group.
24822497 if (super->isTemp && !seenTypes.count (HeapType (uintptr_t (super)))) {
2483- return TypeBuilder::ErrorReason ::ForwardSupertypeReference;
2498+ return TypeBuilder::ErrorReasonKind ::ForwardSupertypeReference;
24842499 }
24852500 // The supertype must have a valid structure.
24862501 if (!isValidSupertype (info, *super)) {
2487- return TypeBuilder::ErrorReason ::InvalidSupertype;
2502+ return TypeBuilder::ErrorReasonKind ::InvalidSupertype;
24882503 }
24892504 }
24902505 if (auto * desc = info.described ) {
24912506 if (!features.hasCustomDescriptors ()) {
2492- return TypeBuilder::ErrorReason ::RequiresCustomDescriptors;
2507+ return TypeBuilder::ErrorReasonKind ::RequiresCustomDescriptors;
24932508 }
24942509 if (info.kind != HeapTypeKind::Struct) {
2495- return TypeBuilder::ErrorReason ::NonStructDescribes;
2510+ return TypeBuilder::ErrorReasonKind ::NonStructDescribes;
24962511 }
24972512 assert (desc->isTemp && " unexpected canonical described type" );
24982513 if (!seenTypes.count (HeapType (uintptr_t (desc)))) {
2499- return TypeBuilder::ErrorReason ::ForwardDescribesReference;
2514+ return TypeBuilder::ErrorReasonKind ::ForwardDescribesReference;
25002515 }
25012516 if (desc->descriptor != &info) {
2502- return TypeBuilder::ErrorReason ::MismatchedDescribes;
2517+ return TypeBuilder::ErrorReasonKind ::MismatchedDescribes;
25032518 }
25042519 }
25052520 if (auto * desc = info.descriptor ) {
25062521 if (!features.hasCustomDescriptors ()) {
2507- return TypeBuilder::ErrorReason ::RequiresCustomDescriptors;
2522+ return TypeBuilder::ErrorReasonKind ::RequiresCustomDescriptors;
25082523 }
25092524 if (info.kind != HeapTypeKind::Struct) {
2510- return TypeBuilder::ErrorReason ::NonStructDescriptor;
2525+ return TypeBuilder::ErrorReasonKind ::NonStructDescriptor;
25112526 }
25122527 if (desc->described != &info) {
2513- return TypeBuilder::ErrorReason ::MismatchedDescriptor;
2528+ return TypeBuilder::ErrorReasonKind ::MismatchedDescriptor;
25142529 }
25152530 }
25162531 if (info.share == Shared) {
25172532 if (!features.hasSharedEverything ()) {
2518- return TypeBuilder::ErrorReason ::InvalidSharedType;
2533+ return TypeBuilder::ErrorReasonKind ::InvalidSharedType;
25192534 }
25202535 if (info.described && info.described ->share != Shared) {
2521- return TypeBuilder::ErrorReason ::InvalidUnsharedDescribes;
2536+ return TypeBuilder::ErrorReasonKind ::InvalidUnsharedDescribes;
25222537 }
25232538 if (info.descriptor && info.descriptor ->share != Shared) {
2524- return TypeBuilder::ErrorReason ::InvalidUnsharedDescriptor;
2539+ return TypeBuilder::ErrorReasonKind ::InvalidUnsharedDescriptor;
25252540 }
25262541 }
25272542 bool isShared = info.share == Shared;
@@ -2636,7 +2651,7 @@ buildRecGroup(std::unique_ptr<RecGroupInfo>&& groupInfo,
26362651 for (auto child : type.getHeapTypeChildren ()) {
26372652 if (isTemp (child) && !seenTypes.count (child)) {
26382653 return {TypeBuilder::Error{
2639- i, TypeBuilder::ErrorReason ::ForwardChildReference}};
2654+ i, TypeBuilder::ErrorReasonKind ::ForwardChildReference}};
26402655 }
26412656 }
26422657 }
@@ -2746,8 +2761,26 @@ TypeBuilder::BuildResult TypeBuilder::build() {
27462761 auto group = (*built)[0 ].getRecGroup ();
27472762 auto uniqueGroup = impl->unique .insertOrGet (group);
27482763 if (group != uniqueGroup) {
2764+ // There is a conflict. Find the set of missing featuers that would
2765+ // resolve the conflict if enabled.
2766+ FeatureSet missingFeatures = FeatureSet::None;
2767+ FeatureSet potential = FeatureSet::GC | FeatureSet::CustomDescriptors;
2768+ std::vector<HeapType> builtTypes = *built;
2769+ std::vector<HeapType> otherTypes (uniqueGroup.begin (),
2770+ uniqueGroup.end ());
2771+ for (uint32_t x = 1 ; x & FeatureSet::All; x <<= 1 ) {
2772+ FeatureSet f (x);
2773+ if ((f & potential) && !impl->features .has (f)) {
2774+ // We have a potential missing feature. Check whether enabling it
2775+ // allows us to differentiate the rec groups.
2776+ if (RecGroupShape (builtTypes, impl->features | f) !=
2777+ RecGroupShape (otherTypes, impl->features | f)) {
2778+ missingFeatures |= f;
2779+ }
2780+ }
2781+ }
27492782 return {TypeBuilder::Error{
2750- groupStart, TypeBuilder::ErrorReason:: RecGroupCollision}};
2783+ groupStart, TypeBuilder::RecGroupCollision{missingFeatures} }};
27512784 }
27522785 }
27532786
0 commit comments