diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2021-10-08 14:21:21 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-08 14:21:21 -0700 |
commit | 53c5e3e62db25fe3522a1fa615a1f53c4cefdf06 (patch) | |
tree | 6e4e054e8ac1ccc95d2c177ecf37ba687905fcaf /src | |
parent | 562250e14af4f74911b5f8510ca3c5774c9b1e1c (diff) | |
download | binaryen-53c5e3e62db25fe3522a1fa615a1f53c4cefdf06.tar.gz binaryen-53c5e3e62db25fe3522a1fa615a1f53c4cefdf06.tar.bz2 binaryen-53c5e3e62db25fe3522a1fa615a1f53c4cefdf06.zip |
Parse milestone 4 nominal types (#4222)
Implement parsing the new {func,struct,array}_subtype format for nominal types.
For now, the new format is parsed the same way the old-style (extends X) format
is parsed, i.e. in --nominal mode types are parsed as nominal but otherwise they
are parsed as equirecursive. Intentionally do not parse the new types
unconditionally as nominal for now to allow frontends to update their nominal
text format while continuing to use the workflow of running wasm-opt without
--nominal to lower nominal types to structural types.
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 417a0ac0e..854228e9f 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -52,8 +52,9 @@ int unhex(char c) { namespace wasm { static Name STRUCT("struct"), FIELD("field"), ARRAY("array"), - EXTENDS("extends"), I8("i8"), I16("i16"), RTT("rtt"), DECLARE("declare"), - ITEM("item"), OFFSET("offset"); + FUNC_SUBTYPE("func_subtype"), STRUCT_SUBTYPE("struct_subtype"), + ARRAY_SUBTYPE("array_subtype"), EXTENDS("extends"), I8("i8"), I16("i16"), + RTT("rtt"), DECLARE("declare"), ITEM("item"), OFFSET("offset"); static Address getAddress(const Element* s) { return atoll(s->c_str()); } @@ -786,12 +787,13 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { return results; }; - auto parseSignatureDef = [&](Element& elem) { + auto parseSignatureDef = [&](Element& elem, bool nominal) { // '(' 'func' vec(param) vec(result) ')' // param ::= '(' 'param' id? valtype ')' // result ::= '(' 'result' valtype ')' std::vector<Type> params, results; - for (auto it = ++elem.begin(), end = elem.end(); it != end; ++it) { + auto end = elem.end() - (nominal ? 1 : 0); + for (auto it = ++elem.begin(); it != end; ++it) { Element& curr = **it; if (elementStartsWith(curr, PARAM)) { auto newParams = parseParams(curr); @@ -838,9 +840,10 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { return Field(parseValType(*elem), mutable_); }; - auto parseStructDef = [&](Element& elem, size_t typeIndex) { + auto parseStructDef = [&](Element& elem, size_t typeIndex, bool nominal) { FieldList fields; - for (Index i = 1; i < elem.size(); i++) { + Index end = elem.size() - (nominal ? 1 : 0); + for (Index i = 1; i < end; i++) { Name name; fields.emplace_back(parseField(elem[i], name)); if (name.is()) { @@ -860,22 +863,43 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { forEachType([&](Element& elem) { Element& def = elem[1]->dollared() ? *elem[2] : *elem[1]; Element& kind = *def[0]; - if (kind == FUNC) { - builder[index] = parseSignatureDef(def); - } else if (kind == STRUCT) { - builder[index] = parseStructDef(def, index); - } else if (kind == ARRAY) { + bool nominal = + kind == FUNC_SUBTYPE || kind == STRUCT_SUBTYPE || kind == ARRAY_SUBTYPE; + if (kind == FUNC || kind == FUNC_SUBTYPE) { + builder[index] = parseSignatureDef(def, nominal); + } else if (kind == STRUCT || kind == STRUCT_SUBTYPE) { + builder[index] = parseStructDef(def, index, nominal); + } else if (kind == ARRAY || kind == ARRAY_SUBTYPE) { builder[index] = parseArrayDef(def); } else { throw ParseException("unknown heaptype kind", kind.line, kind.col); } - if (elementStartsWith(elem[elem.size() - 1], EXTENDS)) { + Element* super = nullptr; + if (nominal) { + // TODO: Let the new nominal types coexist with equirecursive types + // builder[index].setNominal(); + super = def[def.size() - 1]; + if (super->dollared()) { + // OK + } else if (kind == FUNC_SUBTYPE && super->str() == FUNC) { + // OK; no supertype + super = nullptr; + } else if ((kind == STRUCT_SUBTYPE || kind == ARRAY_SUBTYPE) && + super->str() == DATA) { + // OK; no supertype + super = nullptr; + } else { + throw ParseException("unknown supertype", super->line, super->col); + } + } else if (elementStartsWith(elem[elem.size() - 1], EXTENDS)) { // '(' 'extends' $supertype ')' Element& extends = *elem[elem.size() - 1]; - auto it = typeIndices.find(extends[1]->c_str()); + super = extends[1]; + } + if (super) { + auto it = typeIndices.find(super->c_str()); if (it == typeIndices.end()) { - throw ParseException( - "unknown dollared function type", elem.line, elem.col); + throw ParseException("unknown supertype", super->line, super->col); } builder[index].subTypeOf(builder[it->second]); } |