summaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/fuzzing.h57
-rw-r--r--src/tools/wasm-ctor-eval.cpp15
-rw-r--r--src/tools/wasm-metadce.cpp20
-rw-r--r--src/tools/wasm-reduce.cpp8
-rw-r--r--src/tools/wasm-shell.cpp28
-rw-r--r--src/tools/wasm-split.cpp15
-rw-r--r--src/tools/wasm2js.cpp5
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';