diff options
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/fuzzing.h | 16 | ||||
-rw-r--r-- | src/tools/wasm-ctor-eval.cpp | 30 | ||||
-rw-r--r-- | src/tools/wasm-metadce.cpp | 16 | ||||
-rw-r--r-- | src/tools/wasm-reduce.cpp | 79 | ||||
-rw-r--r-- | src/tools/wasm-shell.cpp | 19 |
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); } |