Skip to content

Commit 2c0fb8c

Browse files
authored
Remove equirecursive typing (#5240)
Equirecursive is no longer standards track and its implementation is extremely complex. Remove it.
1 parent 853b31e commit 2c0fb8c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+194
-1501
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ Current Trunk
1616
-------------
1717

1818
- The isorecursive WasmGC type system (i.e. --hybrid) is now the default to
19-
match the spec.
19+
match the spec and the old default equirecursive (i.e. --structural) system
20+
has been removed.
2021

2122
v111
2223
----

src/binaryen-c.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -408,9 +408,6 @@ BinaryenType BinaryenTypeFromHeapType(BinaryenHeapType heapType,
408408

409409
// TypeSystem
410410

411-
BinaryenTypeSystem BinaryenTypeSystemEquirecursive() {
412-
return static_cast<BinaryenTypeSystem>(TypeSystem::Equirecursive);
413-
}
414411
BinaryenTypeSystem BinaryenTypeSystemNominal() {
415412
return static_cast<BinaryenTypeSystem>(TypeSystem::Nominal);
416413
}

src/binaryen-c.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,6 @@ BINARYEN_API BinaryenType BinaryenTypeFromHeapType(BinaryenHeapType heapType,
192192

193193
typedef uint32_t BinaryenTypeSystem;
194194

195-
BINARYEN_API BinaryenTypeSystem BinaryenTypeSystemEquirecursive(void);
196195
BINARYEN_API BinaryenTypeSystem BinaryenTypeSystemNominal(void);
197196
BINARYEN_API BinaryenTypeSystem BinaryenTypeSystemIsorecursive(void);
198197
BINARYEN_API BinaryenTypeSystem BinaryenGetTypeSystem(void);

src/ir/module-utils.cpp

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -214,24 +214,6 @@ IndexedHeapTypes getOptimizedIndexedHeapTypes(Module& wasm) {
214214
TypeSystem system = getTypeSystem();
215215
Counts counts = getHeapTypeCounts(wasm);
216216

217-
if (system == TypeSystem::Equirecursive) {
218-
// Sort by frequency and then original insertion order.
219-
std::vector<std::pair<HeapType, size_t>> sorted(counts.begin(),
220-
counts.end());
221-
std::stable_sort(sorted.begin(), sorted.end(), [&](auto a, auto b) {
222-
return a.second > b.second;
223-
});
224-
225-
// Collect the results.
226-
IndexedHeapTypes indexedTypes;
227-
for (Index i = 0; i < sorted.size(); ++i) {
228-
indexedTypes.types.push_back(sorted[i].first);
229-
}
230-
231-
setIndices(indexedTypes);
232-
return indexedTypes;
233-
}
234-
235217
// Types have to be arranged into topologically ordered recursion groups.
236218
// Under isorecrsive typing, the topological sort has to take all referenced
237219
// rec groups into account but under nominal typing it only has to take
@@ -285,9 +267,6 @@ IndexedHeapTypes getOptimizedIndexedHeapTypes(Module& wasm) {
285267
info.preds.insert(super->getRecGroup());
286268
}
287269
break;
288-
case TypeSystem::Equirecursive:
289-
WASM_UNREACHABLE(
290-
"Equirecursive types should already have been handled");
291270
}
292271
}
293272

src/ir/possible-contents.cpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -488,12 +488,6 @@ struct InfoCollector
488488
}
489489
}
490490
}
491-
if (type.isRef() && getTypeSystem() != TypeSystem::Nominal &&
492-
getTypeSystem() != TypeSystem::Isorecursive) {
493-
// We need explicit supers in the SubTyping helper class. Without that,
494-
// cannot handle refs, and consider them irrelevant.
495-
return false;
496-
}
497491
return true;
498492
}
499493

@@ -1582,11 +1576,8 @@ Flower::Flower(Module& wasm) : wasm(wasm) {
15821576
std::cout << "struct phase\n";
15831577
#endif
15841578

1585-
if (getTypeSystem() == TypeSystem::Nominal ||
1586-
getTypeSystem() == TypeSystem::Isorecursive) {
1587-
subTypes = std::make_unique<SubTypes>(wasm);
1588-
maxDepths = subTypes->getMaxDepths();
1589-
}
1579+
subTypes = std::make_unique<SubTypes>(wasm);
1580+
maxDepths = subTypes->getMaxDepths();
15901581

15911582
#ifdef POSSIBLE_CONTENTS_DEBUG
15921583
std::cout << "Link-targets phase\n";

src/ir/subtypes.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ namespace wasm {
2929
// This only scans user types, and not basic types like HeapType::eq.
3030
struct SubTypes {
3131
SubTypes(const std::vector<HeapType>& types) : types(types) {
32-
if (getTypeSystem() != TypeSystem::Nominal &&
33-
getTypeSystem() != TypeSystem::Isorecursive) {
34-
Fatal() << "SubTypes requires explicit supers";
35-
}
3632
for (auto type : types) {
3733
note(type);
3834
}

src/passes/ConstantFieldPropagation.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,6 @@ struct ConstantFieldPropagation : public Pass {
187187
if (!module->features.hasGC()) {
188188
return;
189189
}
190-
if (getTypeSystem() != TypeSystem::Nominal &&
191-
getTypeSystem() != TypeSystem::Isorecursive) {
192-
Fatal() << "CFP requires nominal/isorecursive typing";
193-
}
194190

195191
// Find and analyze all writes inside each function.
196192
PCVFunctionStructValuesMap functionNewInfos(*module),

src/passes/GUFA.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,6 @@ struct GUFAOptimizer
110110
return;
111111
}
112112

113-
if (type.isRef() && (getTypeSystem() != TypeSystem::Nominal &&
114-
getTypeSystem() != TypeSystem::Isorecursive)) {
115-
// Without type info we can't analyze subtypes, so we cannot infer
116-
// anything about refs.
117-
return;
118-
}
119-
120113
// Ok, this is an interesting location that we might optimize. See what the
121114
// oracle says is possible there.
122115
auto contents = getContents(curr);

src/passes/GlobalRefining.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ struct GlobalRefining : public Pass {
3838
if (!module->features.hasGC()) {
3939
return;
4040
}
41-
if (getTypeSystem() != TypeSystem::Nominal &&
42-
getTypeSystem() != TypeSystem::Isorecursive) {
43-
Fatal() << "GlobalRefining requires nominal/isorecursive typing";
44-
}
4541

4642
// First, find all the global.sets.
4743

src/passes/GlobalStructInference.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,6 @@ struct GlobalStructInference : public Pass {
7171
if (!module->features.hasGC()) {
7272
return;
7373
}
74-
if (getTypeSystem() != TypeSystem::Nominal &&
75-
getTypeSystem() != TypeSystem::Isorecursive) {
76-
Fatal() << "GlobalStructInference requires nominal/isorecursive typing";
77-
}
7874

7975
// First, find all the information we need. We need to know which struct
8076
// types are created in functions, because we will not be able to optimize

src/passes/GlobalTypeOptimization.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,6 @@ struct GlobalTypeOptimization : public Pass {
117117
if (!module->features.hasGC()) {
118118
return;
119119
}
120-
if (getTypeSystem() != TypeSystem::Nominal &&
121-
getTypeSystem() != TypeSystem::Isorecursive) {
122-
Fatal() << "GlobalTypeOptimization requires nominal/isorecursive typing";
123-
}
124120

125121
// Find and analyze struct operations inside each function.
126122
StructUtils::FunctionStructValuesMap<FieldInfo> functionNewInfos(*module),

src/passes/Print.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3034,9 +3034,7 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
30343034
o << '(';
30353035
printMajor(o, "func ");
30363036
printName(curr->name, o);
3037-
if (currModule && currModule->features.hasGC() &&
3038-
(getTypeSystem() == TypeSystem::Nominal ||
3039-
getTypeSystem() == TypeSystem::Isorecursive)) {
3037+
if (currModule && currModule->features.hasGC()) {
30403038
o << " (type ";
30413039
printHeapType(o, curr->type, currModule) << ')';
30423040
}

src/passes/SignaturePruning.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,6 @@ struct SignaturePruning : public Pass {
5252
if (!module->features.hasGC()) {
5353
return;
5454
}
55-
if (getTypeSystem() != TypeSystem::Nominal &&
56-
getTypeSystem() != TypeSystem::Isorecursive) {
57-
Fatal() << "SignaturePruning requires nominal/isorecursive typing";
58-
}
5955

6056
if (!module->tables.empty()) {
6157
// When there are tables we must also take their types into account, which

src/passes/SignatureRefining.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,6 @@ struct SignatureRefining : public Pass {
5454
if (!module->features.hasGC()) {
5555
return;
5656
}
57-
if (getTypeSystem() != TypeSystem::Nominal &&
58-
getTypeSystem() != TypeSystem::Isorecursive) {
59-
Fatal() << "SignatureRefining requires nominal/hybrid typing";
60-
}
6157

6258
if (!module->tables.empty()) {
6359
// When there are tables we must also take their types into account, which

src/passes/pass.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -593,10 +593,7 @@ void PassRunner::addDefaultGlobalOptimizationPrePasses() {
593593
if (options.optimizeLevel >= 2) {
594594
addIfNoDWARFIssues("once-reduction");
595595
}
596-
if (wasm->features.hasGC() &&
597-
(getTypeSystem() == TypeSystem::Nominal ||
598-
getTypeSystem() == TypeSystem::Isorecursive) &&
599-
options.optimizeLevel >= 2) {
596+
if (wasm->features.hasGC() && options.optimizeLevel >= 2) {
600597
addIfNoDWARFIssues("type-refining");
601598
addIfNoDWARFIssues("signature-pruning");
602599
addIfNoDWARFIssues("signature-refining");

src/tools/tool-options.h

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,6 @@ struct ToolOptions : public Options {
148148
[](Options* o, const std::string& argument) {
149149
setTypeSystem(TypeSystem::Nominal);
150150
})
151-
.add("--structural",
152-
"",
153-
"Force all GC type definitions to be parsed as structural "
154-
"(i.e. equirecursive). This is the default.",
155-
ToolOptionsCategory,
156-
Options::Arguments::Zero,
157-
[](Options* o, const std::string& argument) {
158-
setTypeSystem(TypeSystem::Equirecursive);
159-
})
160151
.add("--hybrid",
161152
"",
162153
"Force all GC type definitions to be parsed using the isorecursive "
@@ -196,9 +187,7 @@ struct ToolOptions : public Options {
196187
void applyFeatures(Module& module) const {
197188
module.features.enable(enabledFeatures);
198189
module.features.disable(disabledFeatures);
199-
// Non-default type systems only make sense with GC enabled. TODO: Error on
200-
// non-GC equirecursive types as well once we make isorecursive the default
201-
// if we don't remove equirecursive types entirely.
190+
// Non-default type systems only make sense with GC enabled.
202191
if (!module.features.hasGC() && getTypeSystem() == TypeSystem::Nominal) {
203192
Fatal() << "Nominal typing is only allowed when GC is enabled";
204193
}

src/tools/wasm-fuzz-types.cpp

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -517,25 +517,17 @@ int main(int argc, const char* argv[]) {
517517
Options::Arguments::Zero,
518518
[&](Options*, const std::string& arg) { verbose = true; });
519519

520-
TypeSystem system = TypeSystem::Nominal;
520+
TypeSystem system = TypeSystem::Isorecursive;
521521
options.add(
522522
"--nominal",
523523
"",
524-
"Use the nominal type system (default)",
524+
"Use the nominal type system",
525525
WasmFuzzTypesOption,
526526
Options::Arguments::Zero,
527527
[&](Options*, const std::string& arg) { system = TypeSystem::Nominal; });
528-
options.add("--structural",
529-
"",
530-
"Use the equirecursive type system",
531-
WasmFuzzTypesOption,
532-
Options::Arguments::Zero,
533-
[&](Options*, const std::string& arg) {
534-
system = TypeSystem::Equirecursive;
535-
});
536528
options.add("--hybrid",
537529
"",
538-
"Use the isorecursive hybrid type system",
530+
"Use the isorecursive hybrid type system (default)",
539531
WasmFuzzTypesOption,
540532
Options::Arguments::Zero,
541533
[&](Options*, const std::string& arg) {

src/tools/wasm-reduce.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,9 +1293,10 @@ int main(int argc, const char* argv[]) {
12931293
}
12941294
if (getTypeSystem() == TypeSystem::Nominal) {
12951295
extraFlags += " --nominal";
1296-
}
1297-
if (getTypeSystem() == TypeSystem::Isorecursive) {
1296+
} else if (getTypeSystem() == TypeSystem::Isorecursive) {
12981297
extraFlags += " --hybrid";
1298+
} else {
1299+
WASM_UNREACHABLE("unexpected type system");
12991300
}
13001301

13011302
if (test.size() == 0) {

src/wasm-type.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,8 @@
4141
namespace wasm {
4242

4343
enum class TypeSystem {
44-
Equirecursive,
45-
Nominal,
4644
Isorecursive,
45+
Nominal,
4746
};
4847

4948
// This should only ever be called before any Types or HeapTypes have been

src/wasm/wasm-binary.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,9 @@ void WasmBinaryWriter::writeTypes() {
232232
// MVP types are structural and do not use recursion groups.
233233
TypeSystem typeSystem = getTypeSystem();
234234
if (!wasm->features.hasGC()) {
235-
typeSystem = TypeSystem::Equirecursive;
235+
typeSystem = TypeSystem::Isorecursive;
236236
}
237237
switch (typeSystem) {
238-
case TypeSystem::Equirecursive:
239-
numGroups = indexedTypes.types.size();
240-
break;
241238
case TypeSystem::Nominal:
242239
numGroups = 1;
243240
break;
@@ -2191,9 +2188,6 @@ void WasmBinaryBuilder::readTypes() {
21912188
auto form = getS32LEB();
21922189
if (form == BinaryConsts::EncodedType::Rec) {
21932190
uint32_t groupSize = getU32LEB();
2194-
if (getTypeSystem() == TypeSystem::Equirecursive) {
2195-
throwError("Recursion groups not allowed with equirecursive typing");
2196-
}
21972191
if (groupSize == 0u) {
21982192
// TODO: Support groups of size zero by shrinking the builder.
21992193
throwError("Recursion groups of size zero not supported");

0 commit comments

Comments
 (0)