summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2023-09-08 20:08:33 -0500
committerGitHub <noreply@github.com>2023-09-09 01:08:33 +0000
commit4e58466b40b65cda399b4749105f0ce10f48f62b (patch)
tree9e34ae5ed464d87d75683603171e7b2645015568 /src/wasm
parent90571051b3d6f89eab184df3d4dd716472a6cd7c (diff)
downloadbinaryen-4e58466b40b65cda399b4749105f0ce10f48f62b.tar.gz
binaryen-4e58466b40b65cda399b4749105f0ce10f48f62b.tar.bz2
binaryen-4e58466b40b65cda399b4749105f0ce10f48f62b.zip
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.
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp15
-rw-r--r--src/wasm/wasm-s-parser.cpp7
-rw-r--r--src/wasm/wasm-type.cpp21
-rw-r--r--src/wasm/wat-parser.cpp6
4 files changed, 28 insertions, 21 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 51325e7dd..d43640e26 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -265,13 +265,11 @@ void WasmBinaryWriter::writeTypes() {
// Emit the type definition.
BYN_TRACE("write " << type << std::endl);
auto super = type.getSuperType();
- // TODO: Use the binary shorthand for final types once we parse MVP
- // signatures as final.
- if (type.isFinal() || super || hasSubtypes[i]) {
- if (type.isFinal()) {
- o << S32LEB(BinaryConsts::EncodedType::SubFinal);
- } else {
+ if (super || type.isOpen()) {
+ if (type.isOpen()) {
o << S32LEB(BinaryConsts::EncodedType::Sub);
+ } else {
+ o << S32LEB(BinaryConsts::EncodedType::SubFinal);
}
if (super) {
o << U32LEB(1);
@@ -2268,9 +2266,8 @@ void WasmBinaryReader::readTypes() {
std::optional<uint32_t> superIndex;
if (form == BinaryConsts::EncodedType::Sub ||
form == BinaryConsts::EncodedType::SubFinal) {
- if (form == BinaryConsts::EncodedType::SubFinal) {
- // TODO: Interpret type definitions without any `sub` as final as well.
- builder[i].setFinal();
+ if (form == BinaryConsts::EncodedType::Sub) {
+ builder[i].setOpen();
}
uint32_t supers = getU32LEB();
if (supers > 0) {
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index b6b9a40fb..e30901c5b 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -929,8 +929,9 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) {
if (kind == SUB) {
Index i = 1;
if (*def[i] == FINAL) {
- builder[index].setFinal();
++i;
+ } else {
+ builder[index].setOpen();
}
if (def[i]->dollared()) {
super = def[i];
@@ -959,6 +960,7 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) {
if (kind == FUNC) {
builder[index] = parseSignatureDef(def, 0);
} else if (kind == FUNC_SUBTYPE) {
+ builder[index].setOpen();
builder[index] = parseSignatureDef(def, 1);
super = def[def.size() - 1];
if (!super->dollared() && super->str() == FUNC) {
@@ -968,6 +970,7 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) {
} else if (kind == STRUCT) {
builder[index] = parseStructDef(def, index, 0);
} else if (kind == STRUCT_SUBTYPE) {
+ builder[index].setOpen();
builder[index] = parseStructDef(def, index, 1);
super = def[def.size() - 1];
if (!super->dollared() && super->str() == DATA) {
@@ -977,6 +980,7 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) {
} else if (kind == ARRAY) {
builder[index] = parseArrayDef(def);
} else if (kind == ARRAY_SUBTYPE) {
+ builder[index].setOpen();
builder[index] = parseArrayDef(def);
super = def[def.size() - 1];
if (!super->dollared() && super->str() == DATA) {
@@ -993,6 +997,7 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) {
}
} else if (elementStartsWith(elem[elem.size() - 1], EXTENDS)) {
// '(' 'extends' $supertype ')'
+ builder[index].setOpen();
Element& extends = *elem[elem.size() - 1];
super = extends[1];
}
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index 0c4e7b049..ba38231b6 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -85,7 +85,7 @@ struct HeapTypeInfo {
// Used in assertions to ensure that temporary types don't leak into the
// global store.
bool isTemp = false;
- bool isFinal = false;
+ bool isOpen = false;
// The supertype of this HeapType, if it exists.
HeapTypeInfo* supertype = nullptr;
// The recursion group of this type or null if the recursion group is trivial
@@ -1180,11 +1180,11 @@ bool HeapType::isBottom() const {
return false;
}
-bool HeapType::isFinal() const {
+bool HeapType::isOpen() const {
if (isBasic()) {
return false;
} else {
- return getHeapTypeInfo(*this)->isFinal;
+ return getHeapTypeInfo(*this)->isOpen;
}
}
@@ -1771,13 +1771,12 @@ std::ostream& TypePrinter::print(HeapType type) {
os << "(; temp ;) ";
}
- // TODO: Use shorthand for final types once we parse MVP signatures as final.
bool useSub = false;
auto super = type.getSuperType();
- if (super || type.isFinal()) {
+ if (super || type.isOpen()) {
useSub = true;
os << "(sub ";
- if (type.isFinal()) {
+ if (!type.isOpen()) {
os << "final ";
}
if (super) {
@@ -1946,7 +1945,7 @@ size_t RecGroupHasher::hash(const HeapTypeInfo& info) const {
if (info.supertype) {
hash_combine(digest, hash(HeapType(uintptr_t(info.supertype))));
}
- wasm::rehash(digest, info.isFinal);
+ wasm::rehash(digest, info.isOpen);
wasm::rehash(digest, info.kind);
switch (info.kind) {
case HeapTypeInfo::SignatureKind:
@@ -2069,7 +2068,7 @@ bool RecGroupEquator::eq(const HeapTypeInfo& a, const HeapTypeInfo& b) const {
return false;
}
}
- if (a.isFinal != b.isFinal) {
+ if (a.isOpen != b.isOpen) {
return false;
}
if (a.kind != b.kind) {
@@ -2325,15 +2324,15 @@ void TypeBuilder::createRecGroup(size_t index, size_t length) {
{RecGroup(uintptr_t(groupInfo.get())), std::move(groupInfo)});
}
-void TypeBuilder::setFinal(size_t i, bool final) {
+void TypeBuilder::setOpen(size_t i, bool open) {
assert(i < size() && "index out of bounds");
- impl->entries[i].info->isFinal = final;
+ impl->entries[i].info->isOpen = open;
}
namespace {
bool isValidSupertype(const HeapTypeInfo& sub, const HeapTypeInfo& super) {
- if (super.isFinal) {
+ if (!super.isOpen) {
return false;
}
if (sub.kind != super.kind) {
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp
index 3961cbb7f..bdd1af0d8 100644
--- a/src/wasm/wat-parser.cpp
+++ b/src/wasm/wat-parser.cpp
@@ -849,6 +849,7 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx {
void addFuncType(SignatureT) {}
void addStructType(StructT) {}
void addArrayType(ArrayT) {}
+ void setOpen() {}
Result<> addSubtype(Index) { return Ok{}; }
void finishSubtype(Name name, Index pos) {
subtypeDefs.push_back({name, pos, Index(subtypeDefs.size())});
@@ -1078,6 +1079,8 @@ struct ParseTypeDefsCtx : TypeParserCtx<ParseTypeDefsCtx> {
void addArrayType(ArrayT& type) { builder[index] = type; }
+ void setOpen() { builder[index].setOpen(); }
+
Result<> addSubtype(Index super) {
if (super >= builder.size()) {
return in.err("supertype index out of bounds");
@@ -3463,6 +3466,9 @@ template<typename Ctx> MaybeResult<> subtype(Ctx& ctx) {
}
if (ctx.in.takeSExprStart("sub"sv)) {
+ if (ctx.in.takeKeyword("open"sv)) {
+ ctx.setOpen();
+ }
if (auto super = maybeTypeidx(ctx)) {
CHECK_ERR(super);
CHECK_ERR(ctx.addSubtype(*super));