summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp25
-rw-r--r--src/wasm/wasm-s-parser.cpp18
-rw-r--r--src/wasm/wasm-stack.cpp6
-rw-r--r--src/wasm/wasm-validator.cpp22
-rw-r--r--src/wasm/wasm.cpp8
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.