diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 23 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 18 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 5 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 19 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 12 |
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. |