diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/literal.cpp | 51 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 32 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 12 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 16 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 68 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 7 | ||||
-rw-r--r-- | src/wasm/wat-parser.cpp | 8 |
7 files changed, 184 insertions, 10 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 8d60a4829..7890c7a42 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -235,6 +235,57 @@ Literal Literal::makeNegOne(Type type) { return makeFromInt32(-1, type); } +Literal Literal::makeFromMemory(void* p, Type type) { + assert(type.isNumber()); + switch (type.getBasic()) { + case Type::i32: { + int32_t i; + memcpy(&i, p, sizeof(i)); + return Literal(i); + } + case Type::i64: { + int64_t i; + memcpy(&i, p, sizeof(i)); + return Literal(i); + } + case Type::f32: { + int32_t i; + memcpy(&i, p, sizeof(i)); + return Literal(bit_cast<float>(i)); + } + case Type::f64: { + int64_t i; + memcpy(&i, p, sizeof(i)); + return Literal(bit_cast<double>(i)); + } + case Type::v128: { + uint8_t bytes[16]; + memcpy(bytes, p, sizeof(bytes)); + return Literal(bytes); + } + default: + WASM_UNREACHABLE("unexpected type"); + } +} + +Literal Literal::makeFromMemory(void* p, const Field& field) { + switch (field.packedType) { + case Field::not_packed: + return makeFromMemory(p, field.type); + case Field::i8: { + int8_t i; + memcpy(&i, p, sizeof(i)); + return Literal(int32_t(i)); + } + case Field::i16: { + int16_t i; + memcpy(&i, p, sizeof(i)); + return Literal(int32_t(i)); + } + } + WASM_UNREACHABLE("unexpected type"); +} + Literal Literal::standardizeNaN(const Literal& input) { if (!std::isnan(input.getFloat())) { return input; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index d023a56c6..e2bb0075b 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -3122,12 +3122,15 @@ void WasmBinaryBuilder::readDataSegments() { } curr->setName(Name::fromInt(i), false); curr->isPassive = flags & BinaryConsts::IsPassive; - Index memIdx = 0; - if (flags & BinaryConsts::HasIndex) { - memIdx = getU32LEB(); - } - memoryRefs[memIdx].push_back(&curr->memory); - if (!curr->isPassive) { + if (curr->isPassive) { + curr->memory = Name(); + curr->offset = nullptr; + } else { + Index memIdx = 0; + if (flags & BinaryConsts::HasIndex) { + memIdx = getU32LEB(); + } + memoryRefs[memIdx].push_back(&curr->memory); curr->offset = readExpression(); } auto size = getU32LEB(); @@ -3973,6 +3976,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (maybeVisitArrayNew(curr, opcode)) { break; } + if (maybeVisitArrayNewSeg(curr, opcode)) { + break; + } if (maybeVisitArrayInit(curr, opcode)) { break; } @@ -7058,6 +7064,20 @@ bool WasmBinaryBuilder::maybeVisitArrayNew(Expression*& out, uint32_t code) { return false; } +bool WasmBinaryBuilder::maybeVisitArrayNewSeg(Expression*& out, uint32_t code) { + if (code == BinaryConsts::ArrayNewData || + code == BinaryConsts::ArrayNewElem) { + auto op = code == BinaryConsts::ArrayNewData ? NewData : NewElem; + auto heapType = getIndexedHeapType(); + auto seg = getU32LEB(); + auto* size = popNonVoidExpression(); + auto* offset = popNonVoidExpression(); + out = Builder(wasm).makeArrayNewSeg(op, heapType, seg, offset, size); + return true; + } + return false; +} + bool WasmBinaryBuilder::maybeVisitArrayInit(Expression*& out, uint32_t code) { if (code == BinaryConsts::ArrayInitStatic) { auto heapType = getIndexedHeapType(); diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index a54226194..a9fd2de77 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -2892,6 +2892,15 @@ Expression* SExpressionWasmBuilder::makeArrayNewStatic(Element& s, return Builder(wasm).makeArrayNew(heapType, size, init); } +Expression* SExpressionWasmBuilder::makeArrayNewSeg(Element& s, + ArrayNewSegOp op) { + auto heapType = parseHeapType(*s[1]); + Index seg = parseIndex(*s[2]); + Expression* offset = parseExpression(*s[3]); + Expression* size = parseExpression(*s[4]); + return Builder(wasm).makeArrayNewSeg(op, heapType, seg, offset, size); +} + Expression* SExpressionWasmBuilder::makeArrayInitStatic(Element& s) { auto heapType = parseHeapType(*s[1]); size_t i = 2; @@ -3292,9 +3301,6 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) { } void SExpressionWasmBuilder::parseData(Element& s) { - if (wasm.memories.empty()) { - throw ParseException("data but no memory", s.line, s.col); - } Index i = 1; Name name = Name::fromInt(dataCounter++); bool hasExplicitName = false; diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index f30e4be82..daeac60d6 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2132,6 +2132,22 @@ void BinaryInstWriter::visitArrayNew(ArrayNew* curr) { parent.writeIndexedHeapType(curr->type.getHeapType()); } +void BinaryInstWriter::visitArrayNewSeg(ArrayNewSeg* curr) { + o << int8_t(BinaryConsts::GCPrefix); + switch (curr->op) { + case NewData: + o << U32LEB(BinaryConsts::ArrayNewData); + break; + case NewElem: + o << U32LEB(BinaryConsts::ArrayNewElem); + break; + default: + WASM_UNREACHABLE("unexpected op"); + } + parent.writeIndexedHeapType(curr->type.getHeapType()); + o << U32LEB(curr->segment); +} + void BinaryInstWriter::visitArrayInit(ArrayInit* curr) { o << int8_t(BinaryConsts::GCPrefix); o << U32LEB(BinaryConsts::ArrayInitStatic); diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index cb3841197..c1316f283 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -451,6 +451,7 @@ public: void visitStructGet(StructGet* curr); void visitStructSet(StructSet* curr); void visitArrayNew(ArrayNew* curr); + void visitArrayNewSeg(ArrayNewSeg* curr); void visitArrayInit(ArrayInit* curr); void visitArrayGet(ArrayGet* curr); void visitArraySet(ArraySet* curr); @@ -2683,6 +2684,73 @@ void FunctionValidator::visitArrayNew(ArrayNew* curr) { } } +void FunctionValidator::visitArrayNewSeg(ArrayNewSeg* curr) { + shouldBeTrue(getModule()->features.hasGC(), + curr, + "array.new_{data, elem} requires gc [--enable-gc]"); + shouldBeEqualOrFirstIsUnreachable( + curr->offset->type, + Type(Type::i32), + curr, + "array.new_{data, elem} offset must be an i32"); + shouldBeEqualOrFirstIsUnreachable( + curr->size->type, + Type(Type::i32), + curr, + "array.new_{data, elem} size must be an i32"); + switch (curr->op) { + case NewData: + if (!shouldBeTrue(curr->segment < getModule()->dataSegments.size(), + curr, + "array.new_data segment index out of bounds")) { + return; + } + break; + case NewElem: + if (!shouldBeTrue(curr->segment < getModule()->elementSegments.size(), + curr, + "array.new_elem segment index out of bounds")) { + return; + } + break; + default: + WASM_UNREACHABLE("unexpected op"); + } + if (curr->type == Type::unreachable) { + return; + } + if (!shouldBeTrue( + curr->type.isRef(), + curr, + "array.new_{data, elem} type should be an array reference")) { + return; + } + auto heapType = curr->type.getHeapType(); + if (!shouldBeTrue( + heapType.isArray(), + curr, + "array.new_{data, elem} type shoudl be an array reference")) { + return; + } + auto elemType = heapType.getArray().element.type; + switch (curr->op) { + case NewData: + shouldBeTrue(elemType.isNumber(), + curr, + "array.new_data result element type should be numeric"); + break; + case NewElem: + shouldBeSubType(getModule()->elementSegments[curr->segment]->type, + elemType, + curr, + "array.new_elem segment type should be a subtype of the " + "result element type"); + break; + default: + WASM_UNREACHABLE("unexpected op"); + } +} + void FunctionValidator::visitArrayInit(ArrayInit* curr) { shouldBeTrue(getModule()->features.hasGC(), curr, diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 6347d83e5..a92b62343 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -1053,7 +1053,12 @@ void ArrayNew::finalize() { if (size->type == Type::unreachable || (init && init->type == Type::unreachable)) { type = Type::unreachable; - return; + } +} + +void ArrayNewSeg::finalize() { + if (offset->type == Type::unreachable || size->type == Type::unreachable) { + type = Type::unreachable; } } diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp index 1c1349e47..7705c9e5c 100644 --- a/src/wasm/wat-parser.cpp +++ b/src/wasm/wat-parser.cpp @@ -1907,6 +1907,8 @@ template<typename Ctx> Result<typename Ctx::InstrT> makeStructSet(Ctx&, Index); template<typename Ctx> Result<typename Ctx::InstrT> makeArrayNewStatic(Ctx&, Index, bool default_); template<typename Ctx> +Result<typename Ctx::InstrT> makeArrayNewSeg(Ctx&, Index, ArrayNewSegOp op); +template<typename Ctx> Result<typename Ctx::InstrT> makeArrayInitStatic(Ctx&, Index); template<typename Ctx> Result<typename Ctx::InstrT> makeArrayGet(Ctx&, Index, bool signed_ = false); @@ -2892,6 +2894,12 @@ makeArrayNewStatic(Ctx& ctx, Index pos, bool default_) { } template<typename Ctx> +Result<typename Ctx::InstrT> +makeArrayNewSeg(Ctx& ctx, Index pos, ArrayNewSegOp op) { + return ctx.in.err("unimplemented instruction"); +} + +template<typename Ctx> Result<typename Ctx::InstrT> makeArrayInitStatic(Ctx& ctx, Index pos) { return ctx.in.err("unimplemented instruction"); } |