summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp20
-rw-r--r--src/wasm/wasm-ir-builder.cpp8
-rw-r--r--src/wasm/wasm-stack.cpp6
-rw-r--r--src/wasm/wasm-validator.cpp36
-rw-r--r--src/wasm/wasm.cpp8
5 files changed, 75 insertions, 3 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 4082fbf5f..2abb32837 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -4223,6 +4223,9 @@ BinaryConsts::ASTNodes WasmBinaryReader::readExpression(Expression*& curr) {
if (maybeVisitTableCopy(curr, opcode)) {
break;
}
+ if (maybeVisitTableInit(curr, opcode)) {
+ break;
+ }
if (maybeVisitLoad(curr, opcode, BinaryConsts::MiscPrefix)) {
break;
}
@@ -5646,6 +5649,23 @@ bool WasmBinaryReader::maybeVisitTableCopy(Expression*& out, uint32_t code) {
return true;
}
+bool WasmBinaryReader::maybeVisitTableInit(Expression*& out, uint32_t code) {
+ if (code != BinaryConsts::TableInit) {
+ return false;
+ }
+ auto* curr = allocator.alloc<TableInit>();
+ curr->size = popNonVoidExpression();
+ curr->offset = popNonVoidExpression();
+ curr->dest = popNonVoidExpression();
+ Index segIdx = getU32LEB();
+ elemRefs[segIdx].push_back(&curr->segment);
+ Index memIdx = getU32LEB();
+ tableRefs[memIdx].push_back(&curr->table);
+ curr->finalize();
+ out = curr;
+ return true;
+}
+
bool WasmBinaryReader::maybeVisitBinary(Expression*& out, uint8_t code) {
Binary* curr;
#define INT_TYPED_CODE(code) \
diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp
index 3db6238c4..2f2f3b595 100644
--- a/src/wasm/wasm-ir-builder.cpp
+++ b/src/wasm/wasm-ir-builder.cpp
@@ -1523,6 +1523,14 @@ Result<> IRBuilder::makeTableCopy(Name destTable, Name srcTable) {
return Ok{};
}
+Result<> IRBuilder::makeTableInit(Name elem, Name table) {
+ TableInit curr;
+ curr.table = table;
+ CHECK_ERR(visitTableInit(&curr));
+ push(builder.makeTableInit(elem, curr.dest, curr.offset, curr.size, table));
+ return Ok{};
+}
+
Result<> IRBuilder::makeTry(Name label, Type type) {
auto* tryy = wasm.allocator.alloc<Try>();
tryy->type = type;
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index a9b582f43..1c2c2c42b 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -2053,6 +2053,12 @@ void BinaryInstWriter::visitTableCopy(TableCopy* curr) {
o << U32LEB(parent.getTableIndex(curr->sourceTable));
}
+void BinaryInstWriter::visitTableInit(TableInit* curr) {
+ o << int8_t(BinaryConsts::MiscPrefix) << U32LEB(BinaryConsts::TableInit);
+ o << U32LEB(parent.getElementSegmentIndex(curr->segment));
+ o << U32LEB(parent.getTableIndex(curr->table));
+}
+
void BinaryInstWriter::visitTry(Try* curr) {
breakStack.push_back(curr->name);
o << int8_t(BinaryConsts::Try);
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index b032e6bad..758ae158e 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -469,6 +469,7 @@ public:
void visitTableGrow(TableGrow* curr);
void visitTableFill(TableFill* curr);
void visitTableCopy(TableCopy* curr);
+ void visitTableInit(TableInit* curr);
void noteDelegate(Name name, Expression* curr);
void noteRethrow(Name name, Expression* curr);
void visitTry(Try* curr);
@@ -2443,12 +2444,41 @@ void FunctionValidator::visitTableCopy(TableCopy* curr) {
curr,
"table.copy source must have right type for dest");
}
+ shouldBeEqualOrFirstIsUnreachable(curr->dest->type,
+ destTable->indexType,
+ curr,
+ "table.copy dest must be valid");
+ shouldBeEqualOrFirstIsUnreachable(curr->source->type,
+ sourceTable->indexType,
+ curr,
+ "table.copy source must be valid");
+ Type sizeType =
+ sourceTable->is64() && destTable->is64() ? Type::i64 : Type::i32;
shouldBeEqualOrFirstIsUnreachable(
- curr->dest->type, Type(Type::i32), curr, "table.copy dest must be i32");
+ curr->size->type, sizeType, curr, "table.copy size must be valid");
+}
+
+void FunctionValidator::visitTableInit(TableInit* curr) {
+ shouldBeTrue(getModule()->features.hasBulkMemory(),
+ curr,
+ "table.init requires bulk-memory [--enable-bulk-memory]");
+ auto* segment = getModule()->getElementSegment(curr->segment);
+ auto* table = getModule()->getTableOrNull(curr->table);
+ if (shouldBeTrue(!!segment, curr, "table.init segment must exist") &&
+ shouldBeTrue(!!table, curr, "table.init table must exist")) {
+ shouldBeSubType(segment->type,
+ table->type,
+ curr,
+ "table.init source must have right type for dest");
+ }
shouldBeEqualOrFirstIsUnreachable(
- curr->source->type, Type(Type::i32), curr, "table.copy source must be i32");
+ curr->dest->type, table->indexType, curr, "table.init dest must be valid");
+ shouldBeEqualOrFirstIsUnreachable(curr->offset->type,
+ Type(Type::i32),
+ curr,
+ "table.init offset must be valid");
shouldBeEqualOrFirstIsUnreachable(
- curr->size->type, Type(Type::i32), curr, "table.copy size must be i32");
+ curr->size->type, Type(Type::i32), curr, "table.init size must be valid");
}
void FunctionValidator::noteDelegate(Name name, Expression* curr) {
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index d138e4226..ff641c7eb 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -875,6 +875,14 @@ void TableCopy::finalize() {
}
}
+void TableInit::finalize() {
+ type = Type::none;
+ if (dest->type == Type::unreachable || offset->type == Type::unreachable ||
+ size->type == Type::unreachable) {
+ type = Type::unreachable;
+ }
+}
+
void Try::finalize(std::optional<Type> type_) {
if (type_) {
type = *type_;