Skip to content

Commit 752061c

Browse files
committed
generalize
1 parent 06f8b60 commit 752061c

1 file changed

Lines changed: 58 additions & 55 deletions

File tree

src/passes/Unsubtyping.cpp

Lines changed: 58 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)