diff options
-rw-r--r-- | src/wasm-binary.h | 4 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 49 | ||||
-rw-r--r-- | test/lit/binary/prototype-nominal-format.test | 27 | ||||
-rw-r--r-- | test/lit/binary/prototype-nominal-format.test.wasm | bin | 0 -> 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 Binary files differnew file mode 100644 index 000000000..97485ae4f --- /dev/null +++ b/test/lit/binary/prototype-nominal-format.test.wasm |