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