summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp23
-rw-r--r--src/wasm/wasm-s-parser.cpp18
-rw-r--r--src/wasm/wasm-stack.cpp5
-rw-r--r--src/wasm/wasm-validator.cpp19
-rw-r--r--src/wasm/wasm.cpp12
5 files changed, 73 insertions, 4 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index e2dacdf70..9c8b83325 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -2798,6 +2798,8 @@ void WasmBinaryBuilder::processNames() {
set->table = getTableName(index);
} else if (auto* size = ref->dynCast<TableSize>()) {
size->table = getTableName(index);
+ } else if (auto* grow = ref->dynCast<TableGrow>()) {
+ grow->table = getTableName(index);
} else {
WASM_UNREACHABLE("Invalid type in table references");
}
@@ -3621,6 +3623,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
if (maybeVisitTableSize(curr, opcode)) {
break;
}
+ if (maybeVisitTableGrow(curr, opcode)) {
+ break;
+ }
throwError("invalid code after misc prefix: " + std::to_string(opcode));
break;
}
@@ -4941,6 +4946,24 @@ bool WasmBinaryBuilder::maybeVisitTableSize(Expression*& out, uint32_t code) {
return true;
}
+bool WasmBinaryBuilder::maybeVisitTableGrow(Expression*& out, uint32_t code) {
+ if (code != BinaryConsts::TableGrow) {
+ return false;
+ }
+ Index tableIdx = getU32LEB();
+ if (tableIdx >= tables.size()) {
+ throwError("bad table index");
+ }
+ auto* curr = allocator.alloc<TableGrow>();
+ curr->delta = popNonVoidExpression();
+ curr->value = popNonVoidExpression();
+ curr->finalize();
+ // Defer setting the table name for later, when we know it.
+ tableRefs[tableIdx].push_back(curr);
+ out = curr;
+ return true;
+}
+
bool WasmBinaryBuilder::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 cea666f29..1e15c1faa 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -2453,12 +2453,12 @@ Expression* SExpressionWasmBuilder::makeTableGet(Element& s) {
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);
}
+ auto* index = parseExpression(s[2]);
+ auto* value = parseExpression(s[3]);
return Builder(wasm).makeTableSet(tableName, index, value);
}
@@ -2471,6 +2471,20 @@ Expression* SExpressionWasmBuilder::makeTableSize(Element& s) {
return Builder(wasm).makeTableSize(tableName);
}
+Expression* SExpressionWasmBuilder::makeTableGrow(Element& s) {
+ auto tableName = s[1]->str();
+ auto* table = wasm.getTableOrNull(tableName);
+ if (!table) {
+ throw ParseException("invalid table name in table.grow", s.line, s.col);
+ }
+ auto* value = parseExpression(s[2]);
+ if (!value->type.isRef()) {
+ throw ParseException("only reference types are valid for tables");
+ }
+ auto* delta = parseExpression(s[3]);
+ return Builder(wasm).makeTableGrow(tableName, value, delta);
+}
+
// 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 f81a0b7a0..f5be5d2c5 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -1862,6 +1862,11 @@ void BinaryInstWriter::visitTableSize(TableSize* curr) {
o << U32LEB(parent.getTableIndex(curr->table));
}
+void BinaryInstWriter::visitTableGrow(TableGrow* curr) {
+ o << int8_t(BinaryConsts::MiscPrefix) << U32LEB(BinaryConsts::TableGrow);
+ 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 0271884a4..f8669961c 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -367,6 +367,7 @@ public:
void visitTableGet(TableGet* curr);
void visitTableSet(TableSet* curr);
void visitTableSize(TableSize* curr);
+ void visitTableGrow(TableGrow* curr);
void noteDelegate(Name name, Expression* curr);
void noteRethrow(Name name, Expression* curr);
void visitTry(Try* curr);
@@ -2072,6 +2073,24 @@ void FunctionValidator::visitTableSize(TableSize* curr) {
shouldBeTrue(!!table, curr, "table.size table must exist");
}
+void FunctionValidator::visitTableGrow(TableGrow* curr) {
+ shouldBeTrue(getModule()->features.hasReferenceTypes(),
+ curr,
+ "table.grow requires reference types to be enabled");
+ auto* table = getModule()->getTableOrNull(curr->table);
+ if (shouldBeTrue(!!table, curr, "table.grow table must exist") &&
+ curr->type != Type::unreachable) {
+ shouldBeSubType(curr->value->type,
+ table->type,
+ curr,
+ "table.grow value must have right type");
+ shouldBeEqual(curr->delta->type,
+ Type(Type::i32),
+ curr,
+ "table.grow must match table index 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 c42a1089d..015df26ac 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -822,9 +822,9 @@ void RefNull::finalize() {}
void RefIs::finalize() {
if (value->type == Type::unreachable) {
type = Type::unreachable;
- return;
+ } else {
+ type = Type::i32;
}
- type = Type::i32;
}
void RefFunc::finalize() {
@@ -861,6 +861,14 @@ void TableSize::finalize() {
// Nothing to do - the type must have been set already during construction.
}
+void TableGrow::finalize() {
+ if (delta->type == Type::unreachable || value->type == Type::unreachable) {
+ type = Type::unreachable;
+ } else {
+ type = Type::i32;
+ }
+}
+
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.