summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2023-04-03 16:59:15 +0100
committerGitHub <noreply@github.com>2023-04-03 08:59:15 -0700
commit382671ba0f673dd5da6bcaf6756fc43a518a41f6 (patch)
tree9035b2d9681803c6530bbd67286ff1631e51bf02
parent47056c9a00e368969a503209b6b9f5c0bc287058 (diff)
downloadbinaryen-382671ba0f673dd5da6bcaf6756fc43a518a41f6.tar.gz
binaryen-382671ba0f673dd5da6bcaf6756fc43a518a41f6.tar.bz2
binaryen-382671ba0f673dd5da6bcaf6756fc43a518a41f6.zip
[Wasm GC] Parse (sub $super _) for array, func, and struct (#5515)
The pretty-printer will still serialize these using the old func_subtype, array_subtype, and struct_subtype syntax, though.
-rw-r--r--src/wasm/wasm-s-parser.cpp78
-rw-r--r--test/lit/isorecursive-good.wast6
2 files changed, 58 insertions, 26 deletions
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index b7f88f4c1..1afdefe87 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -52,7 +52,7 @@ namespace wasm {
static Name STRUCT("struct"), FIELD("field"), ARRAY("array"),
FUNC_SUBTYPE("func_subtype"), STRUCT_SUBTYPE("struct_subtype"),
ARRAY_SUBTYPE("array_subtype"), EXTENDS("extends"), REC("rec"), I8("i8"),
- I16("i16"), DECLARE("declare"), ITEM("item"), OFFSET("offset");
+ I16("i16"), DECLARE("declare"), ITEM("item"), OFFSET("offset"), SUB("sub");
static Address getAddress(const Element* s) {
return std::stoll(s->toString());
@@ -898,30 +898,62 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) {
forEachType([&](Element& elem, size_t) {
Element& def = elem[1]->dollared() ? *elem[2] : *elem[1];
Element& kind = *def[0];
- bool hasSupertype =
- kind == FUNC_SUBTYPE || kind == STRUCT_SUBTYPE || kind == ARRAY_SUBTYPE;
- if (kind == FUNC || kind == FUNC_SUBTYPE) {
- builder[index] = parseSignatureDef(def, hasSupertype);
- } else if (kind == STRUCT || kind == STRUCT_SUBTYPE) {
- builder[index] = parseStructDef(def, index, hasSupertype);
- } else if (kind == ARRAY || kind == ARRAY_SUBTYPE) {
- builder[index] = parseArrayDef(def);
- } else {
- throw ParseException("unknown heaptype kind", kind.line, kind.col);
- }
Element* super = nullptr;
- if (hasSupertype) {
- 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;
+ if (kind == SUB) {
+ if (def.size() != 3) {
+ throw ParseException("invalid 'sub' form", kind.line, kind.col);
+ }
+ super = def[1];
+ Element& subtype = *def[2];
+ if (!subtype.isList() || subtype.size() < 1) {
+ throw ParseException(
+ "invalid subtype definition", subtype.line, subtype.col);
+ }
+ Element& subtypeKind = *subtype[0];
+ if (subtypeKind == FUNC) {
+ builder[index] = parseSignatureDef(subtype, 0);
+ } else if (subtypeKind == STRUCT) {
+ builder[index] = parseStructDef(subtype, index, 0);
+ } else if (subtypeKind == ARRAY) {
+ builder[index] = parseArrayDef(subtype);
+ } else {
+ throw ParseException(
+ "unknown subtype kind", subtypeKind.line, subtypeKind.col);
+ }
+ } else {
+ if (kind == FUNC) {
+ builder[index] = parseSignatureDef(def, 0);
+ } else if (kind == FUNC_SUBTYPE) {
+ builder[index] = parseSignatureDef(def, 1);
+ super = def[def.size() - 1];
+ if (!super->dollared() && super->str() == FUNC) {
+ // OK; no supertype
+ super = nullptr;
+ }
+ } else if (kind == STRUCT) {
+ builder[index] = parseStructDef(def, index, 0);
+ } else if (kind == STRUCT_SUBTYPE) {
+ builder[index] = parseStructDef(def, index, 1);
+ super = def[def.size() - 1];
+ if (!super->dollared() && super->str() == DATA) {
+ // OK; no supertype
+ super = nullptr;
+ }
+ } else if (kind == ARRAY) {
+ builder[index] = parseArrayDef(def);
+ } else if (kind == ARRAY_SUBTYPE) {
+ builder[index] = parseArrayDef(def);
+ super = def[def.size() - 1];
+ if (!super->dollared() && super->str() == DATA) {
+ // OK; no supertype
+ super = nullptr;
+ }
} else {
+ throw ParseException("unknown heaptype kind", kind.line, kind.col);
+ }
+ }
+ if (super) {
+ if (!super->dollared()) {
throw ParseException("unknown supertype", super->line, super->col);
}
} else if (elementStartsWith(elem[elem.size() - 1], EXTENDS)) {
diff --git a/test/lit/isorecursive-good.wast b/test/lit/isorecursive-good.wast
index c7c9569eb..0f5cbddf0 100644
--- a/test/lit/isorecursive-good.wast
+++ b/test/lit/isorecursive-good.wast
@@ -16,7 +16,7 @@
(type $super-struct (struct i32))
;; HYBRID: (type $sub-struct (struct_subtype (field i32) (field i64) $super-struct))
;; NOMINAL: (type $sub-struct (struct_subtype (field i32) (field i64) $super-struct))
- (type $sub-struct (struct_subtype i32 i64 $super-struct))
+ (type $sub-struct (sub $super-struct (struct i32 i64)))
)
(rec
@@ -24,7 +24,7 @@
;; HYBRID-NEXT: (type $super-array (array (ref $super-struct)))
(type $super-array (array (ref $super-struct)))
;; HYBRID: (type $sub-array (array_subtype (ref $sub-struct) $super-array))
- (type $sub-array (array_subtype (ref $sub-struct) $super-array))
+ (type $sub-array (sub $super-array (array (ref $sub-struct))))
)
(rec
@@ -34,7 +34,7 @@
(type $super-func (func (param (ref $sub-array)) (result (ref $super-array))))
;; HYBRID: (type $sub-func (func_subtype (param (ref $super-array)) (result (ref $sub-array)) $super-func))
;; NOMINAL: (type $sub-func (func_subtype (param (ref $super-array)) (result (ref $sub-array)) $super-func))
- (type $sub-func (func_subtype (param (ref $super-array)) (result (ref $sub-array)) $super-func))
+ (type $sub-func (sub $super-func (func (param (ref $super-array)) (result (ref $sub-array)))))
)
;; HYBRID: (func $make-super-struct (type $none_=>_ref|$super-struct|) (result (ref $super-struct))