summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2022-05-04 17:50:29 -0700
committerGitHub <noreply@github.com>2022-05-04 17:50:29 -0700
commit996cbd861c0cae4c942cc57b1915af5ea7b4d5f5 (patch)
treee0318d1a61c31a8498b8a68e3e175758800deb5b
parentef4011c665f225f895861ce555c9347eb505c89f (diff)
downloadbinaryen-996cbd861c0cae4c942cc57b1915af5ea7b4d5f5.tar.gz
binaryen-996cbd861c0cae4c942cc57b1915af5ea7b4d5f5.tar.bz2
binaryen-996cbd861c0cae4c942cc57b1915af5ea7b4d5f5.zip
Parse the prototype nominal binary format (#4644)
In f124a11ca3 we removed support for the prototype nominal binary format entirely, but that means that we can no longer parse older binary modules that used that format. Fix this regression by restoring the ability to parse the prototype binary format.
-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