diff options
author | Alon Zakai <azakai@google.com> | 2020-12-07 15:23:24 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-07 15:23:24 -0800 |
commit | 72a7881b42ebed6b2ef36e912a8f5937106e5824 (patch) | |
tree | 5a79bfdbac295b47163e20cf76d25af9d8475b56 /src/wasm/wasm-binary.cpp | |
parent | 295780928d576613ea47bcc55dafc54619086bc8 (diff) | |
download | binaryen-72a7881b42ebed6b2ef36e912a8f5937106e5824.tar.gz binaryen-72a7881b42ebed6b2ef36e912a8f5937106e5824.tar.bz2 binaryen-72a7881b42ebed6b2ef36e912a8f5937106e5824.zip |
[GC] Add struct.get instruction parsing and execution (#3429)
This is the first instruction that uses a GC Struct or Array, so it's where
we start to actually need support in the interpreter for those values, which
is added here.
GC data is modeled as a gcData field on a Literal, which is just a
Literals. That is, both a struct and an array are represented as an
array of values. The type which is alongside would indicate if it's a
struct or an array. Note that the data is referred to using a shared_ptr
so it should "just work", but we'll only be able to really test that once we
add struct.new and so can verify that references are by reference and
not value, etc.
As the first instruction to care about i8/16 types (which are only possible
in a Struct or Array) this adds support for parsing and emitting them.
This PR includes fuzz fixes for some minor things the fuzzer found, including
some bad printing of not having ResultTypeName in necessary places
(found by the text format roundtripping fuzzer).
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 60 |
1 files changed, 39 insertions, 21 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 3aace6721..361faf631 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1030,7 +1030,7 @@ void WasmBinaryWriter::writeType(Type type) { void WasmBinaryWriter::writeHeapType(HeapType type) { if (type.isSignature() || type.isStruct() || type.isArray()) { - o << S32LEB(getTypeIndex(type)); + o << S64LEB(getTypeIndex(type)); // TODO: Actually s33 return; } int ret = 0; @@ -1058,11 +1058,21 @@ void WasmBinaryWriter::writeHeapType(HeapType type) { case HeapType::ArrayKind: WASM_UNREACHABLE("TODO: compound GC types"); } - o << S32LEB(ret); // TODO: Actually encoded as s33 + o << S64LEB(ret); // TODO: Actually s33 } void WasmBinaryWriter::writeField(const Field& field) { - writeType(field.type); + if (field.type == Type::i32 && field.packedType != Field::not_packed) { + if (field.packedType == Field::i8) { + o << S32LEB(BinaryConsts::EncodedType::i8); + } else if (field.packedType == Field::i16) { + o << S32LEB(BinaryConsts::EncodedType::i16); + } else { + WASM_UNREACHABLE("invalid packed type"); + } + } else { + writeType(field.type); + } o << U32LEB(field.mutable_); } @@ -1335,14 +1345,13 @@ uint64_t WasmBinaryBuilder::getUPtrLEB() { return wasm.memory.is64() ? getU64LEB() : getU32LEB(); } -Type WasmBinaryBuilder::getType() { - int type = getS32LEB(); +Type WasmBinaryBuilder::getType(int initial) { // Single value types are negative; signature indices are non-negative - if (type >= 0) { + if (initial >= 0) { // TODO: Handle block input types properly. - return getSignatureByTypeIndex(type).results; + return getSignatureByTypeIndex(initial).results; } - switch (type) { + switch (initial) { // None only used for block signatures. TODO: Separate out? case BinaryConsts::EncodedType::Empty: return Type::none; @@ -1374,13 +1383,15 @@ Type WasmBinaryBuilder::getType() { case BinaryConsts::EncodedType::i31ref: return Type::i31ref; default: - throwError("invalid wasm type: " + std::to_string(type)); + throwError("invalid wasm type: " + std::to_string(initial)); } WASM_UNREACHABLE("unexpected type"); } +Type WasmBinaryBuilder::getType() { return getType(getS32LEB()); } + HeapType WasmBinaryBuilder::getHeapType() { - int type = getS32LEB(); // TODO: Actually encoded as s33 + auto type = getS64LEB(); // TODO: Actually s33 // Single heap types are negative; heap type indices are non-negative if (type >= 0) { if (size_t(type) >= types.size()) { @@ -1408,7 +1419,19 @@ HeapType WasmBinaryBuilder::getHeapType() { } Field WasmBinaryBuilder::getField() { - auto type = getConcreteType(); + // The value may be a general wasm type, or one of the types only possible in + // a field. + auto initial = getS32LEB(); + if (initial == BinaryConsts::EncodedType::i8) { + auto mutable_ = getU32LEB(); + return Field(Field::i8, mutable_); + } + if (initial == BinaryConsts::EncodedType::i16) { + auto mutable_ = getU32LEB(); + return Field(Field::i16, mutable_); + } + // It's a regular wasm value. + auto type = getType(initial); auto mutable_ = getU32LEB(); return Field(type, mutable_); } @@ -1466,12 +1489,6 @@ void WasmBinaryBuilder::verifyInt64(int64_t x) { } } -void WasmBinaryBuilder::ungetInt8() { - assert(pos > 0); - BYN_TRACE("ungetInt8 (at " << pos << ")\n"); - pos--; -} - void WasmBinaryBuilder::readHeader() { BYN_TRACE("== readHeader\n"); verifyInt32(BinaryConsts::Magic); @@ -5601,20 +5618,21 @@ bool WasmBinaryBuilder::maybeVisitStructGet(Expression*& out, uint32_t code) { switch (code) { case BinaryConsts::StructGet: curr = allocator.alloc<StructGet>(); - // ... break; case BinaryConsts::StructGetS: curr = allocator.alloc<StructGet>(); - // ... + curr->signed_ = true; break; case BinaryConsts::StructGetU: curr = allocator.alloc<StructGet>(); - // ... + curr->signed_ = false; break; default: return false; } - WASM_UNREACHABLE("TODO (gc): struct.get"); + auto type = getHeapType(); + curr->index = getU32LEB(); + curr->value = popNonVoidExpression(); curr->finalize(); out = curr; return true; |