diff options
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/fuzzing.h | 57 | ||||
-rw-r--r-- | src/tools/wasm-ctor-eval.cpp | 15 | ||||
-rw-r--r-- | src/tools/wasm-metadce.cpp | 20 | ||||
-rw-r--r-- | src/tools/wasm-reduce.cpp | 8 | ||||
-rw-r--r-- | src/tools/wasm-shell.cpp | 28 | ||||
-rw-r--r-- | src/tools/wasm-split.cpp | 15 | ||||
-rw-r--r-- | src/tools/wasm2js.cpp | 5 |
7 files changed, 92 insertions, 56 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index 66f175414..714e2c84b 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -423,10 +423,19 @@ private: } } + // TODO(reference-types): allow the fuzzer to create multiple tables void setupTable() { - wasm.table.exists = true; - wasm.table.initial = wasm.table.max = 0; - wasm.table.segments.emplace_back(builder.makeConst(int32_t(0))); + if (wasm.tables.size() > 0) { + auto& table = wasm.tables[0]; + table->initial = table->max = 0; + table->segments.emplace_back(builder.makeConst(int32_t(0))); + } else { + auto table = builder.makeTable( + Names::getValidTableName(wasm, "fuzzing_table"), 0, 0); + table->hasExplicitName = true; + table->segments.emplace_back(builder.makeConst(int32_t(0))); + wasm.addTable(std::move(table)); + } } std::map<Type, std::vector<Name>> globalsByType; @@ -522,26 +531,27 @@ private: } void finalizeTable() { - for (auto& segment : wasm.table.segments) { - // If the offset is a global that was imported (which is ok) but no - // longer is (not ok) we need to change that. - if (auto* offset = segment.offset->dynCast<GlobalGet>()) { - if (!wasm.getGlobal(offset->name)->imported()) { - // TODO: the segments must not overlap... - segment.offset = - builder.makeConst(Literal::makeFromInt32(0, Type::i32)); + for (auto& table : wasm.tables) { + for (auto& segment : table->segments) { + // If the offset is a global that was imported (which is ok) but no + // longer is (not ok) we need to change that. + if (auto* offset = segment.offset->dynCast<GlobalGet>()) { + if (!wasm.getGlobal(offset->name)->imported()) { + // TODO: the segments must not overlap... + segment.offset = + builder.makeConst(Literal::makeFromInt32(0, Type::i32)); + } } + Address maxOffset = segment.data.size(); + if (auto* offset = segment.offset->dynCast<Const>()) { + maxOffset = maxOffset + offset->value.getInteger(); + } + table->initial = std::max(table->initial, maxOffset); } - Address maxOffset = segment.data.size(); - if (auto* offset = segment.offset->dynCast<Const>()) { - maxOffset = maxOffset + offset->value.getInteger(); - } - wasm.table.initial = std::max(wasm.table.initial, maxOffset); + table->max = oneIn(2) ? Address(Table::kUnlimitedSize) : table->initial; + // Avoid an imported table (which the fuzz harness would need to handle). + table->module = table->base = Name(); } - wasm.table.max = - oneIn(2) ? Address(Table::kUnlimitedSize) : wasm.table.initial; - // Avoid an imported table (which the fuzz harness would need to handle). - wasm.table.module = wasm.table.base = Name(); } Name HANG_LIMIT_GLOBAL; @@ -705,7 +715,7 @@ private: } // add some to the table while (oneIn(3) && !finishedInput) { - wasm.table.segments[0].data.push_back(func->name); + wasm.tables[0]->segments[0].data.push_back(func->name); } numAddedFunctions++; return func; @@ -1425,7 +1435,7 @@ private: } Expression* makeCallIndirect(Type type) { - auto& data = wasm.table.segments[0].data; + auto& data = wasm.tables[0]->segments[0].data; if (data.empty()) { return make(type); } @@ -1462,7 +1472,8 @@ private: for (const auto& type : targetFn->sig.params) { args.push_back(make(type)); } - return builder.makeCallIndirect(target, args, targetFn->sig, isReturn); + return builder.makeCallIndirect( + wasm.tables[0]->name, target, args, targetFn->sig, isReturn); } Expression* makeCallRef(Type type) { diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 4ad9979cd..9e3915073 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -215,14 +215,23 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface { extra); } - Literals callTable(Index index, + Literals callTable(Name tableName, + Index index, Signature sig, LiteralList& arguments, Type result, EvallingModuleInstance& instance) override { + + std::unordered_map<wasm::Name, std::vector<wasm::Name>>::iterator it; + + auto* table = wasm->getTableOrNull(tableName); + if (!table) { + throw FailToEvalException("callTable on non-existing table"); + } + // we assume the table is not modified (hmm) // look through the segments, try to find the function - for (auto& segment : wasm->table.segments) { + for (auto& segment : table->segments) { Index start; // look for the index in this segment. if it has a constant offset, we // look in the proper range. if it instead gets a global, we rely on the @@ -282,7 +291,7 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface { } // called during initialization, but we don't keep track of a table - void tableStore(Address addr, Name value) override {} + void tableStore(Name tableName, Address addr, Name value) override {} bool growMemory(Address /*oldSize*/, Address newSize) override { throw FailToEvalException("grow memory"); diff --git a/src/tools/wasm-metadce.cpp b/src/tools/wasm-metadce.cpp index 87bb293b6..46b66c986 100644 --- a/src/tools/wasm-metadce.cpp +++ b/src/tools/wasm-metadce.cpp @@ -213,17 +213,19 @@ struct MetaDCEGraph { // we can't remove segments, so root what they need InitScanner rooter(this, Name()); rooter.setModule(&wasm); - for (auto& segment : wasm.table.segments) { - // TODO: currently, all functions in the table are roots, but we - // should add an option to refine that - for (auto& name : segment.data) { - if (!wasm.getFunction(name)->imported()) { - roots.insert(functionToDCENode[name]); - } else { - roots.insert(importIdToDCENode[getFunctionImportId(name)]); + for (auto& table : wasm.tables) { + for (auto& segment : table->segments) { + // TODO: currently, all functions in the table are roots, but we + // should add an option to refine that + for (auto& name : segment.data) { + if (!wasm.getFunction(name)->imported()) { + roots.insert(functionToDCENode[name]); + } else { + roots.insert(importIdToDCENode[getFunctionImportId(name)]); + } } + rooter.walk(segment.offset); } - rooter.walk(segment.offset); } for (auto& segment : wasm.memory.segments) { if (!segment.isPassive) { diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index 3860630af..4bb4b6f9a 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -898,8 +898,14 @@ struct Reducer } // If we are left with a single function that is not exported or used in // a table, that is useful as then we can change the return type. + bool allTablesEmpty = std::all_of( + module->tables.begin(), module->tables.end(), [&](auto& table) { + return std::all_of(table->segments.begin(), + table->segments.end(), + [&](auto& segment) { return segment.data.empty(); }); + }); if (module->functions.size() == 1 && module->exports.empty() && - module->table.segments.empty()) { + allTablesEmpty) { auto* func = module->functions[0].get(); // We can't remove something that might have breaks to it. if (!func->imported() && !Properties::isNamedControlFlow(func->body)) { diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp index 20d4b9344..b3b52d9a1 100644 --- a/src/tools/wasm-shell.cpp +++ b/src/tools/wasm-shell.cpp @@ -161,6 +161,7 @@ static void run_asserts(Name moduleName, invalid = true; }; ModuleUtils::iterImportedGlobals(wasm, reportUnknownImport); + ModuleUtils::iterImportedTables(wasm, reportUnknownImport); ModuleUtils::iterImportedFunctions(wasm, [&](Importable* import) { if (import->module == SPECTEST && import->base.startsWith(PRINT)) { // We can handle it. @@ -168,23 +169,22 @@ static void run_asserts(Name moduleName, reportUnknownImport(import); } }); - if (wasm.memory.imported()) { - reportUnknownImport(&wasm.memory); - } - if (wasm.table.imported()) { - reportUnknownImport(&wasm.table); - } - for (auto& segment : wasm.table.segments) { - for (auto name : segment.data) { - // spec tests consider it illegal to use spectest.print in a table - if (auto* import = wasm.getFunction(name)) { - if (import->imported() && import->module == SPECTEST && - import->base.startsWith(PRINT)) { - std::cerr << "cannot put spectest.print in table\n"; - invalid = true; + ModuleUtils::iterDefinedTables(wasm, [&](Table* table) { + for (auto& segment : table->segments) { + for (auto name : segment.data) { + // spec tests consider it illegal to use spectest.print in a table + if (auto* import = wasm.getFunction(name)) { + if (import->imported() && import->module == SPECTEST && + import->base.startsWith(PRINT)) { + std::cerr << "cannot put spectest.print in table\n"; + invalid = true; + } } } } + }); + if (wasm.memory.imported()) { + reportUnknownImport(&wasm.memory); } } if (!invalid) { diff --git a/src/tools/wasm-split.cpp b/src/tools/wasm-split.cpp index 5b44e5f0e..171774d82 100644 --- a/src/tools/wasm-split.cpp +++ b/src/tools/wasm-split.cpp @@ -472,18 +472,21 @@ void adjustTableSize(Module& wasm, int initialSize) { if (initialSize < 0) { return; } - if (!wasm.table.exists) { + if (wasm.tables.empty()) { Fatal() << "--initial-table used but there is no table"; } - if ((uint64_t)initialSize < wasm.table.initial) { + + auto& table = wasm.tables.front(); + + if ((uint64_t)initialSize < table->initial) { Fatal() << "Specified initial table size too small, should be at least " - << wasm.table.initial; + << table->initial; } - if ((uint64_t)initialSize > wasm.table.max) { + if ((uint64_t)initialSize > table->max) { Fatal() << "Specified initial table size larger than max table size " - << wasm.table.max; + << table->max; } - wasm.table.initial = initialSize; + table->initial = initialSize; } void instrumentModule(Module& wasm, const WasmSplitOptions& options) { diff --git a/src/tools/wasm2js.cpp b/src/tools/wasm2js.cpp index 1464f48f8..8659ef6e2 100644 --- a/src/tools/wasm2js.cpp +++ b/src/tools/wasm2js.cpp @@ -982,6 +982,11 @@ int main(int argc, const char* argv[]) { "request for silly amounts of memory)"; } + // TODO: Remove this restriction when wasm2js can handle multiple tables + if (wasm.tables.size() > 1) { + Fatal() << "error: modules with multiple tables are not supported yet."; + } + if (options.passOptions.validate) { if (!WasmValidator().validate(wasm)) { std::cout << wasm << '\n'; |