summaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/fuzzing.h16
-rw-r--r--src/tools/wasm-ctor-eval.cpp30
-rw-r--r--src/tools/wasm-metadce.cpp16
-rw-r--r--src/tools/wasm-reduce.cpp79
-rw-r--r--src/tools/wasm-shell.cpp19
5 files changed, 94 insertions, 66 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index a0d5430d8..595652c94 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -723,7 +723,9 @@ private:
while (oneIn(3) && !finishedInput) {
auto& randomElem =
wasm.elementSegments[upTo(wasm.elementSegments.size())];
- randomElem->data.push_back(func->name);
+ // FIXME: make the type NonNullable when we support it!
+ auto type = Type(HeapType(func->sig), Nullable);
+ randomElem->data.push_back(builder.makeRefFunc(func->name, type));
}
numAddedFunctions++;
return func;
@@ -1436,11 +1438,13 @@ private:
bool isReturn;
while (1) {
// TODO: handle unreachable
- targetFn = wasm.getFunction(data[i]);
- isReturn = type == Type::unreachable && wasm.features.hasTailCall() &&
- funcContext->func->sig.results == targetFn->sig.results;
- if (targetFn->sig.results == type || isReturn) {
- break;
+ if (auto* get = data[i]->dynCast<RefFunc>()) {
+ targetFn = wasm.getFunction(get->func);
+ isReturn = type == Type::unreachable && wasm.features.hasTailCall() &&
+ funcContext->func->sig.results == targetFn->sig.results;
+ if (targetFn->sig.results == type || isReturn) {
+ break;
+ }
}
i++;
if (i == data.size()) {
diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp
index f39d8a34e..13a522135 100644
--- a/src/tools/wasm-ctor-eval.cpp
+++ b/src/tools/wasm-ctor-eval.cpp
@@ -251,19 +251,25 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
}
auto end = start + segment->data.size();
if (start <= index && index < end) {
- auto name = segment->data[index - start];
- // if this is one of our functions, we can call it; if it was imported,
- // fail
- auto* func = wasm->getFunction(name);
- if (func->sig != sig) {
- throw FailToEvalException(
- std::string("callTable signature mismatch: ") + name.str);
- }
- if (!func->imported()) {
- return instance.callFunctionInternal(name, arguments);
+ auto entry = segment->data[index - start];
+ if (auto* get = entry->dynCast<RefFunc>()) {
+ auto name = get->func;
+ // if this is one of our functions, we can call it; if it was
+ // imported, fail
+ auto* func = wasm->getFunction(name);
+ if (func->sig != sig) {
+ throw FailToEvalException(
+ std::string("callTable signature mismatch: ") + name.str);
+ }
+ if (!func->imported()) {
+ return instance.callFunctionInternal(name, arguments);
+ } else {
+ throw FailToEvalException(
+ std::string("callTable on imported function: ") + name.str);
+ }
} else {
throw FailToEvalException(
- std::string("callTable on imported function: ") + name.str);
+ std::string("callTable on uninitialized entry"));
}
}
}
@@ -295,7 +301,7 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
}
// called during initialization, but we don't keep track of a table
- void tableStore(Name tableName, Address addr, Name value) override {}
+ void tableStore(Name tableName, Address addr, Literal 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 71ea2f693..5ddf52dae 100644
--- a/src/tools/wasm-metadce.cpp
+++ b/src/tools/wasm-metadce.cpp
@@ -26,6 +26,7 @@
#include <memory>
+#include "ir/element-utils.h"
#include "ir/module-utils.h"
#include "pass.h"
#include "support/colors.h"
@@ -216,13 +217,14 @@ struct MetaDCEGraph {
ModuleUtils::iterActiveElementSegments(wasm, [&](ElementSegment* segment) {
// 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)]);
- }
- }
+ ElementUtils::iterElementSegmentFunctionNames(
+ segment, [&](Name name, Index) {
+ if (!wasm.getFunction(name)->imported()) {
+ roots.insert(functionToDCENode[name]);
+ } else {
+ roots.insert(importIdToDCENode[getFunctionImportId(name)]);
+ }
+ });
rooter.walk(segment->offset);
});
for (auto& segment : wasm.memory.segments) {
diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp
index efe5c1caa..19afc2032 100644
--- a/src/tools/wasm-reduce.cpp
+++ b/src/tools/wasm-reduce.cpp
@@ -766,7 +766,31 @@ struct Reducer
}
// the "opposite" of shrinking: copy a 'zero' element
for (auto& segment : curr->segments) {
- reduceByZeroing(&segment, 0, 2, shrank);
+ reduceByZeroing(
+ &segment, 0, [](char item) { return item == 0; }, 2, shrank);
+ }
+ }
+
+ template<typename T, typename U, typename C>
+ void
+ reduceByZeroing(T* segment, U zero, C isZero, size_t bonus, bool shrank) {
+ for (auto& item : segment->data) {
+ if (!shouldTryToReduce(bonus) || isZero(item)) {
+ continue;
+ }
+ auto save = item;
+ item = zero;
+ if (writeAndTestReduction()) {
+ std::cerr << "| zeroed elem segment\n";
+ noteReduction();
+ } else {
+ item = save;
+ }
+ if (shrank) {
+ // zeroing is fairly inefficient. if we are managing to shrink
+ // (which we do exponentially), just zero one per segment at most
+ break;
+ }
}
}
@@ -803,37 +827,9 @@ struct Reducer
return shrank;
}
- template<typename T, typename U>
- void reduceByZeroing(T* segment, U zero, size_t bonus, bool shrank) {
- if (segment->data.empty()) {
- return;
- }
- for (auto& item : segment->data) {
- if (!shouldTryToReduce(bonus)) {
- continue;
- }
- if (item == zero) {
- continue;
- }
- auto save = item;
- item = zero;
- if (writeAndTestReduction()) {
- std::cerr << "| zeroed elem segment\n";
- noteReduction();
- } else {
- item = save;
- }
- if (shrank) {
- // zeroing is fairly inefficient. if we are managing to shrink
- // (which we do exponentially), just zero one per segment at most
- break;
- }
- }
- }
-
void shrinkElementSegments(Module* module) {
std::cerr << "| try to simplify elem segments\n";
- Name first;
+ Expression* first = nullptr;
auto it =
std::find_if_not(module->elementSegments.begin(),
module->elementSegments.end(),
@@ -842,6 +838,10 @@ struct Reducer
if (it != module->elementSegments.end()) {
first = it->get()->data[0];
}
+ if (first == nullptr) {
+ // The elements are all empty, nothing to shrink
+ return;
+ }
// try to reduce to first function. first, shrink segment elements.
// while we are shrinking successfully, keep going exponentially.
@@ -851,7 +851,24 @@ struct Reducer
}
// the "opposite" of shrinking: copy a 'zero' element
for (auto& segment : module->elementSegments) {
- reduceByZeroing(segment.get(), first, 100, shrank);
+ reduceByZeroing(
+ segment.get(),
+ first,
+ [&](Expression* entry) {
+ if (entry->is<RefNull>()) {
+ // we don't need to replace a ref.null
+ return true;
+ } else if (first->is<RefNull>()) {
+ return false;
+ } else {
+ // Both are ref.func
+ auto* f = first->cast<RefFunc>();
+ auto* e = entry->cast<RefFunc>();
+ return f->func == e->func;
+ }
+ },
+ 100,
+ shrank);
}
}
diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp
index efa2c0ca4..6d2077e1c 100644
--- a/src/tools/wasm-shell.cpp
+++ b/src/tools/wasm-shell.cpp
@@ -23,6 +23,7 @@
#include <memory>
#include "execution-results.h"
+#include "ir/element-utils.h"
#include "pass.h"
#include "shell-interface.h"
#include "support/command-line.h"
@@ -166,18 +167,16 @@ run_asserts(Name moduleName,
reportUnknownImport(import);
}
});
- for (auto& segment : wasm.elementSegments) {
- 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;
- }
+ ElementUtils::iterAllElementFunctionNames(&wasm, [&](Name name) {
+ // 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);
}