summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/literal.cpp51
-rw-r--r--src/wasm/wasm-binary.cpp32
-rw-r--r--src/wasm/wasm-s-parser.cpp12
-rw-r--r--src/wasm/wasm-stack.cpp16
-rw-r--r--src/wasm/wasm-validator.cpp68
-rw-r--r--src/wasm/wasm.cpp7
-rw-r--r--src/wasm/wat-parser.cpp8
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");
}