diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 20 | ||||
-rw-r--r-- | src/wasm/wasm-ir-builder.cpp | 8 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 6 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 36 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 8 |
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_; |