diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 25 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 18 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 6 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 22 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 8 |
5 files changed, 79 insertions, 0 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 6b74f2597..3c01e5df5 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -4062,6 +4062,9 @@ BinaryConsts::ASTNodes WasmBinaryReader::readExpression(Expression*& curr) { if (maybeVisitTableFill(curr, opcode)) { break; } + if (maybeVisitTableCopy(curr, opcode)) { + break; + } throwError("invalid code after misc prefix: " + std::to_string(opcode)); break; } @@ -5436,6 +5439,28 @@ bool WasmBinaryReader::maybeVisitTableFill(Expression*& out, uint32_t code) { return true; } +bool WasmBinaryReader::maybeVisitTableCopy(Expression*& out, uint32_t code) { + if (code != BinaryConsts::TableCopy) { + return false; + } + Index destTableIdx = getU32LEB(); + if (destTableIdx >= wasm.tables.size()) { + throwError("bad table index"); + } + Index sourceTableIdx = getU32LEB(); + if (sourceTableIdx >= wasm.tables.size()) { + throwError("bad table index"); + } + auto* size = popNonVoidExpression(); + auto* source = popNonVoidExpression(); + auto* dest = popNonVoidExpression(); + auto* ret = Builder(wasm).makeTableCopy(dest, source, size, Name(), Name()); + tableRefs[destTableIdx].push_back(&ret->destTable); + tableRefs[sourceTableIdx].push_back(&ret->sourceTable); + out = ret; + return true; +} + bool WasmBinaryReader::maybeVisitBinary(Expression*& out, uint8_t code) { Binary* curr; #define INT_TYPED_CODE(code) \ diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 6f3fbe76b..7b415813e 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -2706,6 +2706,24 @@ Expression* SExpressionWasmBuilder::makeTableFill(Element& s) { return Builder(wasm).makeTableFill(tableName, dest, value, size); } +Expression* SExpressionWasmBuilder::makeTableCopy(Element& s) { + auto destTableName = s[1]->str(); + auto* destTable = wasm.getTableOrNull(destTableName); + if (!destTable) { + throw SParseException("invalid dest table name in table.copy", s); + } + auto sourceTableName = s[2]->str(); + auto* sourceTable = wasm.getTableOrNull(sourceTableName); + if (!sourceTable) { + throw SParseException("invalid source table name in table.copy", s); + } + auto* dest = parseExpression(s[3]); + auto* source = parseExpression(s[4]); + auto* size = parseExpression(s[5]); + return Builder(wasm).makeTableCopy( + dest, source, size, destTableName, sourceTableName); +} + // try can be either in the form of try-catch or try-delegate. // try-catch is written in the folded wast format as // (try diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 1d2363be3..0f8facfd5 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -1941,6 +1941,12 @@ void BinaryInstWriter::visitTableFill(TableFill* curr) { o << U32LEB(parent.getTableIndex(curr->table)); } +void BinaryInstWriter::visitTableCopy(TableCopy* curr) { + o << int8_t(BinaryConsts::MiscPrefix) << U32LEB(BinaryConsts::TableCopy); + o << U32LEB(parent.getTableIndex(curr->destTable)); + o << U32LEB(parent.getTableIndex(curr->sourceTable)); +} + 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 cd90e767e..68d1f786d 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -441,6 +441,7 @@ public: void visitTableSize(TableSize* curr); void visitTableGrow(TableGrow* curr); void visitTableFill(TableFill* curr); + void visitTableCopy(TableCopy* curr); void noteDelegate(Name name, Expression* curr); void noteRethrow(Name name, Expression* curr); void visitTry(Try* curr); @@ -2315,6 +2316,27 @@ void FunctionValidator::visitTableFill(TableFill* curr) { curr->size->type, Type(Type::i32), curr, "table.fill size must be i32"); } +void FunctionValidator::visitTableCopy(TableCopy* curr) { + shouldBeTrue(getModule()->features.hasBulkMemory(), + curr, + "table.copy requires bulk-memory [--enable-bulk-memory]"); + auto* sourceTable = getModule()->getTableOrNull(curr->sourceTable); + auto* destTable = getModule()->getTableOrNull(curr->destTable); + if (shouldBeTrue(!!sourceTable, curr, "table.copy source table must exist") && + shouldBeTrue(!!destTable, curr, "table.copy dest table must exist")) { + shouldBeSubType(sourceTable->type, + destTable->type, + curr, + "table.copy source must have right type for dest"); + } + shouldBeEqualOrFirstIsUnreachable( + curr->dest->type, Type(Type::i32), curr, "table.copy dest must be i32"); + shouldBeEqualOrFirstIsUnreachable( + curr->source->type, Type(Type::i32), curr, "table.copy source must be i32"); + shouldBeEqualOrFirstIsUnreachable( + curr->size->type, Type(Type::i32), curr, "table.copy size must be i32"); +} + void FunctionValidator::noteDelegate(Name name, Expression* curr) { if (name != DELEGATE_CALLER_TARGET) { shouldBeTrue(delegateTargetNames.count(name) != 0, diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index fef613cd2..24479c1cf 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -866,6 +866,14 @@ void TableFill::finalize() { } } +void TableCopy::finalize() { + type = Type::none; + if (dest->type == Type::unreachable || source->type == Type::unreachable || + size->type == Type::unreachable) { + type = Type::unreachable; + } +} + void Try::finalize() { // If none of the component bodies' type is a supertype of the others, assume // the current type is already correct. TODO: Calculate a proper LUB. |