summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp18
-rw-r--r--src/wasm/wasm-s-parser.cpp11
-rw-r--r--src/wasm/wasm-stack.cpp5
-rw-r--r--src/wasm/wasm-validator.cpp17
-rw-r--r--src/wasm/wasm.cpp8
5 files changed, 59 insertions, 0 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 04dad3c9c..7e72b056f 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -2791,6 +2791,8 @@ void WasmBinaryBuilder::processNames() {
callIndirect->table = getTableName(index);
} else if (auto* get = ref->dynCast<TableGet>()) {
get->table = getTableName(index);
+ } else if (auto* set = ref->dynCast<TableSet>()) {
+ set->table = getTableName(index);
} else {
WASM_UNREACHABLE("Invalid type in table references");
}
@@ -3524,6 +3526,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
case BinaryConsts::TableGet:
visitTableGet((curr = allocator.alloc<TableGet>())->cast<TableGet>());
break;
+ case BinaryConsts::TableSet:
+ visitTableSet((curr = allocator.alloc<TableSet>())->cast<TableSet>());
+ break;
case BinaryConsts::Try:
visitTryOrTryInBlock(curr);
break;
@@ -6217,6 +6222,19 @@ void WasmBinaryBuilder::visitTableGet(TableGet* curr) {
tableRefs[tableIdx].push_back(curr);
}
+void WasmBinaryBuilder::visitTableSet(TableSet* curr) {
+ BYN_TRACE("zz node: TableSet\n");
+ Index tableIdx = getU32LEB();
+ if (tableIdx >= tables.size()) {
+ throwError("bad table index");
+ }
+ curr->value = popNonVoidExpression();
+ curr->index = popNonVoidExpression();
+ curr->finalize();
+ // Defer setting the table name for later, when we know it.
+ tableRefs[tableIdx].push_back(curr);
+}
+
void WasmBinaryBuilder::visitTryOrTryInBlock(Expression*& out) {
BYN_TRACE("zz node: Try\n");
auto* curr = allocator.alloc<Try>();
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 573699eae..417a0ac0e 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -2427,6 +2427,17 @@ Expression* SExpressionWasmBuilder::makeTableGet(Element& s) {
return Builder(wasm).makeTableGet(tableName, index, table->type);
}
+Expression* SExpressionWasmBuilder::makeTableSet(Element& s) {
+ auto tableName = s[1]->str();
+ auto* index = parseExpression(s[2]);
+ auto* value = parseExpression(s[3]);
+ auto* table = wasm.getTableOrNull(tableName);
+ if (!table) {
+ throw ParseException("invalid table name in table.set", s.line, s.col);
+ }
+ return Builder(wasm).makeTableSet(tableName, index, value);
+}
+
// 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 58bd29f6e..b74b73ba1 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -1852,6 +1852,11 @@ void BinaryInstWriter::visitTableGet(TableGet* curr) {
o << U32LEB(parent.getTableIndex(curr->table));
}
+void BinaryInstWriter::visitTableSet(TableSet* curr) {
+ o << int8_t(BinaryConsts::TableSet);
+ 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 fae95980f..0e362df9c 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -365,6 +365,7 @@ public:
void visitRefFunc(RefFunc* curr);
void visitRefEq(RefEq* curr);
void visitTableGet(TableGet* curr);
+ void visitTableSet(TableSet* curr);
void noteDelegate(Name name, Expression* curr);
void noteRethrow(Name name, Expression* curr);
void visitTry(Try* curr);
@@ -2046,6 +2047,22 @@ void FunctionValidator::visitTableGet(TableGet* curr) {
}
}
+void FunctionValidator::visitTableSet(TableSet* curr) {
+ shouldBeTrue(getModule()->features.hasReferenceTypes(),
+ curr,
+ "table.set requires reference types to be enabled");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->index->type, Type(Type::i32), curr, "table.set index must be an i32");
+ auto* table = getModule()->getTableOrNull(curr->table);
+ if (shouldBeTrue(!!table, curr, "table.set table must exist") &&
+ curr->type != Type::unreachable) {
+ shouldBeSubType(curr->value->type,
+ table->type,
+ curr,
+ "table.set value must have right type");
+ }
+}
+
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 19ba5f265..26e6b369b 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -825,6 +825,14 @@ void TableGet::finalize() {
// Otherwise, the type should have been set already.
}
+void TableSet::finalize() {
+ if (index->type == Type::unreachable || value->type == Type::unreachable) {
+ type = Type::unreachable;
+ } else {
+ type = Type::none;
+ }
+}
+
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.