@@ -502,9 +502,8 @@ struct Unsubtyping : Pass {
502502 }
503503
504504 void noteDescriptor (HeapType described, HeapType descriptor) {
505- DBG (std::cerr << " noting " << ModuleHeapType (*wasm, described)
506- << " described by " << ModuleHeapType (*wasm, descriptor)
507- << ' \n ' );
505+ DBG (std::cerr << " noting " << ModuleHeapType (*wasm, described) << " -> "
506+ << ModuleHeapType (*wasm, descriptor) << ' \n ' );
508507 work.push_back ({Kind::Descriptor, described, descriptor});
509508 }
510509
@@ -722,33 +721,16 @@ struct Unsubtyping : Pass {
722721
723722 types.setSupertype (sub, super);
724723
725- // If the supertype has a descriptor type, then the subtype must be
726- // described by a corresponding subtype of the supertype's descriptor. (On
727- // the other hand, no further requirements are placed on the supertype if
728- // the subtype has a descriptor.)
729- if (auto desc = types.getDescriptor (super)) {
730- auto subDesc = sub.getDescriptorType ();
731- assert (subDesc);
732- noteDescriptor (sub, *subDesc);
733- noteSubtype (*subDesc, *desc);
734- }
735- // If the supertype describes a type, then the subtype must describe a
736- // corresponding subtype of the supertype's described type.
737- if (auto desc = types.getDescribed (super)) {
738- auto subDesc = sub.getDescribedType ();
739- assert (subDesc);
740- noteDescriptor (*subDesc, sub);
741- noteSubtype (*subDesc, *desc);
742- }
743- // If the subtype describes a type, then the supertype must describe the
744- // supertype of the subtype's described type.
745- if (!super.isBasic ()) {
746- if (auto desc = types.getDescribed (sub)) {
747- auto superDesc = super.getDescribedType ();
748- assert (superDesc);
749- noteDescriptor (*superDesc, super);
750- noteSubtype (*desc, *superDesc);
751- }
724+ // Complete the descriptor squares to the left and right of the new
725+ // subtyping edge if those squares can possibly exist based on the original
726+ // types.
727+ if (super.getDescribedType ()) {
728+ completeDescriptorSquare (
729+ types.getDescribed (super), super, types.getDescribed (sub), sub);
730+ }
731+ if (super.getDescriptorType ()) {
732+ completeDescriptorSquare (
733+ super, types.getDescriptor (super), sub, types.getDescriptor (sub));
752734 }
753735
754736 // Find the implied subtypings from the type definitions and casts.
@@ -757,6 +739,8 @@ struct Unsubtyping : Pass {
757739 }
758740
759741 void processDescriptor (HeapType described, HeapType descriptor) {
742+ DBG (std::cerr << " processing " << ModuleHeapType (*wasm, described) << " -> "
743+ << ModuleHeapType (*wasm, descriptor) << ' \n ' );
760744 assert (described.getDescriptorType () &&
761745 *described.getDescriptorType () == descriptor);
762746 if (auto oldDesc = types.getDescriptor (described)) {
@@ -767,32 +751,16 @@ struct Unsubtyping : Pass {
767751
768752 types.setDescriptor (described, descriptor);
769753
770- // Every immediate subtype of the described type must also be described by a
771- // corresponding immediate subtype of the descriptor. (On the other hand,
772- // no further requirements are placed on the supertype of the described
773- // type.)
754+ // Complete the descriptor squares above and below the new descriptor edge.
755+ completeDescriptorSquare (
756+ std::nullopt , types.getSupertype (descriptor), described, descriptor);
774757 for (auto sub : types.immediateSubtypes (described)) {
775- auto subDesc = sub.getDescriptorType ();
776- assert (subDesc);
777- noteDescriptor (sub, *subDesc);
778- noteSubtype (*subDesc, descriptor);
779- }
780- // Every immediate subtype of the descriptor type must also describe a
781- // corresponding immediate subtype of the described typed.
782- for (auto sub : types.immediateSubtypes (descriptor)) {
783- auto subDesc = sub.getDescribedType ();
784- assert (subDesc);
785- noteDescriptor (*subDesc, sub);
786- noteSubtype (*subDesc, described);
787- }
788- // The immediate superytpe of the descriptor, if it exists, must describe
789- // the immediate supertype of the described type.
790- if (auto superDescriptor = types.getSupertype (descriptor);
791- superDescriptor && !superDescriptor->isBasic ()) {
792- auto superDescribed = superDescriptor->getDescribedType ();
793- assert (superDescribed);
794- noteDescriptor (*superDescribed, *superDescriptor);
795- noteSubtype (described, *superDescribed);
758+ completeDescriptorSquare (
759+ described, descriptor, sub, types.getDescriptor (sub));
760+ }
761+ for (auto subDesc : types.immediateSubtypes (descriptor)) {
762+ completeDescriptorSquare (
763+ described, descriptor, types.getDescribed (subDesc), subDesc);
796764 }
797765 }
798766
@@ -852,6 +820,41 @@ struct Unsubtyping : Pass {
852820 }
853821 }
854822
823+ void completeDescriptorSquare (std::optional<HeapType> super,
824+ std::optional<HeapType> superDesc,
825+ std::optional<HeapType> sub,
826+ std::optional<HeapType> subDesc) {
827+ if ((super && super->isBasic ()) || (superDesc && superDesc->isBasic ())) {
828+ // Basic types do not have descriptors or described types, so do not form
829+ // descriptor squares.
830+ return ;
831+ }
832+ if (bool (super) + bool (superDesc) + bool (sub) + bool (subDesc) < 3 ) {
833+ // We must have two adjacent edges (involving at least 3 types) for there
834+ // to be any further requirements.
835+ return ;
836+ }
837+ // There may be up to one missing type. Look it up using its original
838+ // descriptor relation with the present types and add the missing edges.
839+ if (!super) {
840+ super = superDesc->getDescribedType ();
841+ } else if (!sub) {
842+ sub = subDesc->getDescribedType ();
843+ } else if (!subDesc) {
844+ subDesc = sub->getDescriptorType ();
845+ } else if (!superDesc) {
846+ // This is the only type that is allowed to be missing.
847+ return ;
848+ }
849+ // Add all the edges. Don't worry about duplicating existing edges because
850+ // checking whether they're necessary now would be about as expensive as
851+ // discarding them later.
852+ noteSubtype (*sub, *super);
853+ noteSubtype (*subDesc, *superDesc);
854+ noteDescriptor (*super, *superDesc);
855+ noteDescriptor (*sub, *subDesc);
856+ }
857+
855858 void rewriteTypes (Module& wasm) {
856859 struct Rewriter : GlobalTypeRewriter {
857860 Unsubtyping& parent;
0 commit comments