summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm-binary.h4
-rw-r--r--src/wasm/wasm-binary.cpp49
-rw-r--r--test/lit/binary/prototype-nominal-format.test27
-rw-r--r--test/lit/binary/prototype-nominal-format.test.wasmbin0 -> 211 bytes
4 files changed, 71 insertions, 9 deletions
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 62c2f7af2..12deeacab 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -382,6 +382,10 @@ enum EncodedType {
Struct = -0x21, // 0x5f
Array = -0x22, // 0x5e
Sub = -0x30, // 0x50
+ // prototype nominal forms we still parse
+ FuncSubtype = -0x23, // 0x5d
+ StructSubtype = -0x24, // 0x5c
+ ArraySubtype = -0x25, // 0x5b
// isorecursive recursion groups
Rec = -0x31, // 0x4f
// block_type
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 9dcdbb73d..60a4bad77 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -1985,6 +1985,7 @@ void WasmBinaryBuilder::readTypes() {
builder.createRecGroup(i, groupSize);
form = getS32LEB();
}
+ std::optional<uint32_t> superIndex;
if (form == BinaryConsts::EncodedType::Sub) {
uint32_t supers = getU32LEB();
if (supers > 0) {
@@ -1992,24 +1993,54 @@ void WasmBinaryBuilder::readTypes() {
throwError("Invalid type definition with " + std::to_string(supers) +
" supertypes");
}
- uint32_t superIndex = getU32LEB();
- if (superIndex > builder.size()) {
- throwError("Out of bounds supertype index " +
- std::to_string(superIndex));
- }
- builder[i].subTypeOf(builder[superIndex]);
+ superIndex = getU32LEB();
}
form = getS32LEB();
}
- if (form == BinaryConsts::EncodedType::Func) {
+ if (form == BinaryConsts::EncodedType::Func ||
+ form == BinaryConsts::EncodedType::FuncSubtype) {
builder[i] = readSignatureDef();
- } else if (form == BinaryConsts::EncodedType::Struct) {
+ } else if (form == BinaryConsts::EncodedType::Struct ||
+ form == BinaryConsts::EncodedType::StructSubtype) {
builder[i] = readStructDef();
- } else if (form == BinaryConsts::EncodedType::Array) {
+ } else if (form == BinaryConsts::EncodedType::Array ||
+ form == BinaryConsts::EncodedType::ArraySubtype) {
builder[i] = Array(readFieldDef());
} else {
throwError("Bad type form " + std::to_string(form));
}
+ if (form == BinaryConsts::EncodedType::FuncSubtype ||
+ form == BinaryConsts::EncodedType::StructSubtype ||
+ form == BinaryConsts::EncodedType::ArraySubtype) {
+ int64_t super = getS64LEB(); // TODO: Actually s33
+ if (super >= 0) {
+ superIndex = (uint32_t)super;
+ } else {
+ // Validate but otherwise ignore trivial supertypes.
+ HeapType basicSuper;
+ if (!getBasicHeapType(super, basicSuper)) {
+ throwError("Unrecognized supertype " + std::to_string(super));
+ }
+ if (form == BinaryConsts::EncodedType::FuncSubtype) {
+ if (basicSuper != HeapType::func) {
+ throwError(
+ "The only allowed trivial supertype for functions is func");
+ }
+ } else {
+ if (basicSuper != HeapType::data) {
+ throwError("The only allowed trivial supertype for structs and "
+ "arrays is data");
+ }
+ }
+ }
+ }
+ if (superIndex) {
+ if (*superIndex > builder.size()) {
+ throwError("Out of bounds supertype index " +
+ std::to_string(*superIndex));
+ }
+ builder[i].subTypeOf(builder[*superIndex]);
+ }
}
auto result = builder.build();
diff --git a/test/lit/binary/prototype-nominal-format.test b/test/lit/binary/prototype-nominal-format.test
new file mode 100644
index 000000000..def3e1473
--- /dev/null
+++ b/test/lit/binary/prototype-nominal-format.test
@@ -0,0 +1,27 @@
+;; Test the we can properly parse the prototype nominal binary format that we no
+;; longer emit.
+
+;; RUN: wasm-dis %s.wasm -all | filecheck %s
+
+;; CHECK: (module
+;; CHECK-NEXT: (type $super-struct (struct (field i32)))
+;; CHECK-NEXT: (type $sub-struct (struct (field i32) (field i64)))
+;; CHECK-NEXT: (type $none_=>_ref|$super-struct| (func (result (ref $super-struct))))
+;; CHECK-NEXT: (type $none_=>_ref|$sub-struct| (func (result (ref $sub-struct))))
+;; CHECK-NEXT: (type $none_=>_ref|$super-array| (func (result (ref $super-array))))
+;; CHECK-NEXT: (type $none_=>_ref|$sub-array| (func (result (ref $sub-array))))
+;; CHECK-NEXT: (type $super-array (array (ref $super-struct)))
+;; CHECK-NEXT: (type $sub-array (array (ref $sub-struct)))
+;; CHECK-NEXT: (func $make-super-struct (result (ref $super-struct))
+;; CHECK-NEXT: (call $make-sub-struct)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (func $make-sub-struct (result (ref $sub-struct))
+;; CHECK-NEXT: (unreachable)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (func $make-super-array (result (ref $super-array))
+;; CHECK-NEXT: (call $make-sub-array)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: (func $make-sub-array (result (ref $sub-array))
+;; CHECK-NEXT: (unreachable)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
diff --git a/test/lit/binary/prototype-nominal-format.test.wasm b/test/lit/binary/prototype-nominal-format.test.wasm
new file mode 100644
index 000000000..97485ae4f
--- /dev/null
+++ b/test/lit/binary/prototype-nominal-format.test.wasm
Binary files differ