Skip to content

Commit 4e58466

Browse files
authored
Make final types the default (#5918)
Match the spec and parse the shorthand binary and text formats as final and emit final types without supertypes using the shorthands as well. This is a potentially-breaking change, since the text and binary shorthands can no longer be used to define types that have subtypes. Also make TypeBuilder entries final by default to better match the spec and update the internal APIs to use the "open" terminology rather than "final" terminology. Future changes will update the text format to use the standard "sub open" rather than the current "sub final" keywords. The exception is the new wat parser, which supporst "sub open" as of this change, since it didn't support final types at all previously.
1 parent 9057105 commit 4e58466

File tree

79 files changed

+729
-730
lines changed

Some content is hidden

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

79 files changed

+729
-730
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Current Trunk
2222
and as a convenience.
2323
- The nonstandard, experimental gc-nn-locals feature has been removed now that
2424
standard non-nullable locals are supported.
25+
- Heap types are now final by default and openness must be opted into both in
26+
the text and binary formats as well as in the TypeBuilder API.
2527

2628
v114
2729
----

src/binaryen-c.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6413,6 +6413,9 @@ void TypeBuilderSetSubType(TypeBuilderRef builder,
64136413
BinaryenHeapType superType) {
64146414
((TypeBuilder*)builder)->setSubType(index, HeapType(superType));
64156415
}
6416+
void TypeBuilderSetOpen(TypeBuilderRef builder, BinaryenIndex index) {
6417+
((TypeBuilder*)builder)->setOpen(index);
6418+
}
64166419
void TypeBuilderCreateRecGroup(TypeBuilderRef builder,
64176420
BinaryenIndex index,
64186421
BinaryenIndex length) {

src/binaryen-c.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3572,6 +3572,9 @@ BINARYEN_API BinaryenType TypeBuilderGetTempRefType(TypeBuilderRef builder,
35723572
BINARYEN_API void TypeBuilderSetSubType(TypeBuilderRef builder,
35733573
BinaryenIndex index,
35743574
BinaryenHeapType superType);
3575+
// Sets the type at `index` to be open (i.e. non-final).
3576+
BINARYEN_API void TypeBuilderSetOpen(TypeBuilderRef builder,
3577+
BinaryenIndex index);
35753578
// Creates a new recursion group in the range `index` inclusive to `index +
35763579
// length` exclusive. Recursion groups must not overlap.
35773580
BINARYEN_API void TypeBuilderCreateRecGroup(TypeBuilderRef builder,

src/ir/type-updating.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ GlobalTypeRewriter::TypeMap GlobalTypeRewriter::rebuildTypes() {
7272
// Create the temporary heap types.
7373
i = 0;
7474
for (auto [type, _] : typeIndices) {
75-
typeBuilder[i].setFinal(type.isFinal());
75+
typeBuilder[i].setOpen(type.isOpen());
7676
if (type.isSignature()) {
7777
auto sig = type.getSignature();
7878
TypeList newParams, newResults;

src/passes/TypeMerging.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ bool shapeEq(HeapType a, HeapType b) {
538538
// Check whether `a` and `b` have the same top-level structure, including the
539539
// position and identity of any children that are not included as transitions
540540
// in the DFA, i.e. any children that are not nontrivial references.
541-
if (a.isFinal() != b.isFinal()) {
541+
if (a.isOpen() != b.isOpen()) {
542542
return false;
543543
}
544544
if (a.isStruct() && b.isStruct()) {
@@ -554,7 +554,7 @@ bool shapeEq(HeapType a, HeapType b) {
554554
}
555555

556556
size_t shapeHash(HeapType a) {
557-
size_t digest = hash(a.isFinal());
557+
size_t digest = hash(a.isOpen());
558558
if (a.isStruct()) {
559559
rehash(digest, 0);
560560
hash_combine(digest, shapeHash(a.getStruct()));

src/passes/TypeSSA.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ std::vector<HeapType> ensureTypesAreInNewRecGroup(RecGroup recGroup,
110110
if (auto super = type.getSuperType()) {
111111
builder[i].subTypeOf(*super);
112112
}
113-
builder[i].setFinal(type.isFinal());
113+
builder[i].setOpen(type.isOpen());
114114
}
115115

116116
// Implement the hash as a struct with "random" fields, and add it.
@@ -255,6 +255,7 @@ struct TypeSSA : public Pass {
255255
builder[i] = oldType.getArray();
256256
}
257257
builder[i].subTypeOf(oldType);
258+
builder[i].setOpen();
258259
}
259260
builder.createRecGroup(0, num);
260261
auto result = builder.build();
@@ -311,7 +312,7 @@ struct TypeSSA : public Pass {
311312
return false;
312313
}
313314

314-
if (curr->type.getHeapType().isFinal()) {
315+
if (!curr->type.getHeapType().isOpen()) {
315316
// We can't create new subtypes of a final type anyway.
316317
return false;
317318
}

src/tools/fuzzing/heap-types.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,7 @@ struct HeapTypeGeneratorImpl {
8787

8888
// Types without nontrivial subtypes may be marked final.
8989
for (Index i = 0; i < builder.size(); ++i) {
90-
if (subtypeIndices[i].size() == 1 && rand.oneIn(2)) {
91-
builder[i].setFinal();
92-
}
90+
builder[i].setOpen(subtypeIndices[i].size() > 1 || rand.oneIn(2));
9391
}
9492

9593
// Initialize the recursion groups.
@@ -894,7 +892,7 @@ std::vector<HeapType> Inhabitator::build() {
894892
builder[i].subTypeOf(*super);
895893
}
896894
}
897-
builder[i].setFinal(types[i].isFinal());
895+
builder[i].setOpen(types[i].isOpen());
898896
}
899897

900898
auto built = builder.build();

src/tools/wasm-fuzz-types.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ void Fuzzer::checkCanonicalization() {
264264

265265
// Set finality
266266
for (size_t i = 0; i < types.size(); ++i) {
267-
builder[i].setFinal(types[i].isFinal());
267+
builder[i].setOpen(types[i].isOpen());
268268
}
269269

270270
// Set up recursion groups and record group ends to ensure we only select

src/wasm-type.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ class HeapType {
361361
bool isArray() const;
362362
bool isString() const;
363363
bool isBottom() const;
364-
bool isFinal() const;
364+
bool isOpen() const;
365365

366366
Signature getSignature() const;
367367
const Struct& getStruct() const;
@@ -587,7 +587,7 @@ struct TypeBuilder {
587587
// not overlap or go out of bounds.
588588
void createRecGroup(size_t i, size_t length);
589589

590-
void setFinal(size_t i, bool final = true);
590+
void setOpen(size_t i, bool open = true);
591591

592592
enum class ErrorReason {
593593
// There is a cycle in the supertype relation.
@@ -650,8 +650,8 @@ struct TypeBuilder {
650650
builder.setSubType(index, other);
651651
return *this;
652652
}
653-
Entry& setFinal(bool final = true) {
654-
builder.setFinal(index, final);
653+
Entry& setOpen(bool open = true) {
654+
builder.setOpen(index, open);
655655
return *this;
656656
}
657657
};

src/wasm/wasm-binary.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -265,13 +265,11 @@ void WasmBinaryWriter::writeTypes() {
265265
// Emit the type definition.
266266
BYN_TRACE("write " << type << std::endl);
267267
auto super = type.getSuperType();
268-
// TODO: Use the binary shorthand for final types once we parse MVP
269-
// signatures as final.
270-
if (type.isFinal() || super || hasSubtypes[i]) {
271-
if (type.isFinal()) {
272-
o << S32LEB(BinaryConsts::EncodedType::SubFinal);
273-
} else {
268+
if (super || type.isOpen()) {
269+
if (type.isOpen()) {
274270
o << S32LEB(BinaryConsts::EncodedType::Sub);
271+
} else {
272+
o << S32LEB(BinaryConsts::EncodedType::SubFinal);
275273
}
276274
if (super) {
277275
o << U32LEB(1);
@@ -2268,9 +2266,8 @@ void WasmBinaryReader::readTypes() {
22682266
std::optional<uint32_t> superIndex;
22692267
if (form == BinaryConsts::EncodedType::Sub ||
22702268
form == BinaryConsts::EncodedType::SubFinal) {
2271-
if (form == BinaryConsts::EncodedType::SubFinal) {
2272-
// TODO: Interpret type definitions without any `sub` as final as well.
2273-
builder[i].setFinal();
2269+
if (form == BinaryConsts::EncodedType::Sub) {
2270+
builder[i].setOpen();
22742271
}
22752272
uint32_t supers = getU32LEB();
22762273
if (supers > 0) {

0 commit comments

Comments
 (0)