summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/wasm/wasm-s-parser.cpp54
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]);
}