diff options
author | Alon Zakai <azakai@google.com> | 2023-10-06 16:41:13 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-06 16:41:13 -0700 |
commit | b3775b5e4e150439276ad3d34f1bb564b28e8ef5 (patch) | |
tree | eb7b09492205249f08459ffee38e081b83cbf17d /src | |
parent | 9c1107d17c0b7223bd377d9ab4f36fe54ef07c7d (diff) | |
download | binaryen-b3775b5e4e150439276ad3d34f1bb564b28e8ef5.tar.gz binaryen-b3775b5e4e150439276ad3d34f1bb564b28e8ef5.tar.bz2 binaryen-b3775b5e4e150439276ad3d34f1bb564b28e8ef5.zip |
Automatically discard global effects in the rare passes that add effects (#5999)
All logging/instrumentation passes need to do this, to avoid us using stale
global effects that are too low (too high is not optimal either, but at least it
cannot cause bugs).
Diffstat (limited to 'src')
-rw-r--r-- | src/pass.h | 7 | ||||
-rw-r--r-- | src/passes/Asyncify.cpp | 5 | ||||
-rw-r--r-- | src/passes/DeNaN.cpp | 2 | ||||
-rw-r--r-- | src/passes/ExtractFunction.cpp | 6 | ||||
-rw-r--r-- | src/passes/FuncCastEmulation.cpp | 5 | ||||
-rw-r--r-- | src/passes/I64ToI32Lowering.cpp | 3 | ||||
-rw-r--r-- | src/passes/InstrumentLocals.cpp | 3 | ||||
-rw-r--r-- | src/passes/InstrumentMemory.cpp | 3 | ||||
-rw-r--r-- | src/passes/LegalizeJSInterface.cpp | 3 | ||||
-rw-r--r-- | src/passes/LogExecution.cpp | 3 | ||||
-rw-r--r-- | src/passes/SafeHeap.cpp | 2 | ||||
-rw-r--r-- | src/passes/SpillPointers.cpp | 3 | ||||
-rw-r--r-- | src/passes/StackCheck.cpp | 3 | ||||
-rw-r--r-- | src/passes/pass.cpp | 5 |
14 files changed, 53 insertions, 0 deletions
diff --git a/src/pass.h b/src/pass.h index 090aa8d33..da9a12b95 100644 --- a/src/pass.h +++ b/src/pass.h @@ -466,6 +466,13 @@ public: // For more details see the LocalStructuralDominance class. virtual bool requiresNonNullableLocalFixups() { return true; } + // Many passes can remove effects, for example, by finding some path is not + // reached and removing a throw or a call there. The few passes that *add* + // effects must mark themselves as such, so that we know to discard global + // effects after running them. For example, a logging pass that adds new calls + // to imports must override this to return true. + virtual bool addsEffects() { return false; } + std::string name; PassRunner* getPassRunner() { return runner; } diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp index d0674d97c..2412a754a 100644 --- a/src/passes/Asyncify.cpp +++ b/src/passes/Asyncify.cpp @@ -870,6 +870,8 @@ struct InstrumentedProxy : public Pass { bool invalidatesDWARF() override { return pass->invalidatesDWARF(); } + bool addsEffects() override { return pass->addsEffects(); } + bool requiresNonNullableLocalFixups() override { return pass->requiresNonNullableLocalFixups(); } @@ -1610,6 +1612,9 @@ static std::string getFullImportName(Name module, Name base) { } struct Asyncify : public Pass { + // Adds calls. + bool addsEffects() override { return true; } + void run(Module* module) override { auto& options = getPassOptions(); bool optimize = options.optimizeLevel > 0; diff --git a/src/passes/DeNaN.cpp b/src/passes/DeNaN.cpp index 44dd0bf15..97f71c39f 100644 --- a/src/passes/DeNaN.cpp +++ b/src/passes/DeNaN.cpp @@ -32,6 +32,8 @@ namespace wasm { struct DeNaN : public WalkerPass< ControlFlowWalker<DeNaN, UnifiedExpressionVisitor<DeNaN>>> { + // Adds calls. + bool addsEffects() override { return true; } Name deNan32, deNan64; diff --git a/src/passes/ExtractFunction.cpp b/src/passes/ExtractFunction.cpp index e3f2a5538..440468ede 100644 --- a/src/passes/ExtractFunction.cpp +++ b/src/passes/ExtractFunction.cpp @@ -58,6 +58,9 @@ static void extract(PassRunner* runner, Module* module, Name name) { } struct ExtractFunction : public Pass { + // Turns functions into imported functions. + bool addsEffects() override { return true; } + void run(Module* module) override { Name name = getPassOptions().getArgument( "extract-function", @@ -67,6 +70,9 @@ struct ExtractFunction : public Pass { }; struct ExtractFunctionIndex : public Pass { + // See above. + bool addsEffects() override { return true; } + void run(Module* module) override { std::string index = getPassOptions().getArgument("extract-function-index", diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp index 3255208fe..23eb98a8c 100644 --- a/src/passes/FuncCastEmulation.cpp +++ b/src/passes/FuncCastEmulation.cpp @@ -151,6 +151,11 @@ private: }; struct FuncCastEmulation : public Pass { + // Changes the ABI, which alters which indirect calls will trap (normally, + // this should prevent traps, but it depends on code this is linked to at + // runtime in the case of dynamic linking etc.). + bool addsEffects() override { return true; } + void run(Module* module) override { Index numParams = std::stoul( getPassOptions().getArgumentOrDefault("max-func-params", "16")); diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp index ec66b1121..0f591871b 100644 --- a/src/passes/I64ToI32Lowering.cpp +++ b/src/passes/I64ToI32Lowering.cpp @@ -39,6 +39,9 @@ namespace wasm { static Name makeHighName(Name n) { return n.toString() + "$hi"; } struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { + // Adds calls to helper functions. + bool addsEffects() override { return true; } + struct TempVar { TempVar(Index idx, Type ty, I64ToI32Lowering& pass) : idx(idx), pass(pass), moved(false), ty(ty) {} diff --git a/src/passes/InstrumentLocals.cpp b/src/passes/InstrumentLocals.cpp index 311d4a27b..bf5de644c 100644 --- a/src/passes/InstrumentLocals.cpp +++ b/src/passes/InstrumentLocals.cpp @@ -68,6 +68,9 @@ Name set_funcref("set_funcref"); Name set_externref("set_externref"); struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> { + // Adds calls to new imports. + bool addsEffects() override { return true; } + void visitLocalGet(LocalGet* curr) { Builder builder(*getModule()); Name import; diff --git a/src/passes/InstrumentMemory.cpp b/src/passes/InstrumentMemory.cpp index 486bc7c1f..b3c9aebbd 100644 --- a/src/passes/InstrumentMemory.cpp +++ b/src/passes/InstrumentMemory.cpp @@ -97,6 +97,9 @@ static Name array_set_index("array_set_index"); // TODO: Add support for atomicRMW/cmpxchg struct InstrumentMemory : public WalkerPass<PostWalker<InstrumentMemory>> { + // Adds calls to new imports. + bool addsEffects() override { return true; } + void visitLoad(Load* curr) { id++; Builder builder(*getModule()); diff --git a/src/passes/LegalizeJSInterface.cpp b/src/passes/LegalizeJSInterface.cpp index 6667862f4..3ca6b7095 100644 --- a/src/passes/LegalizeJSInterface.cpp +++ b/src/passes/LegalizeJSInterface.cpp @@ -54,6 +54,9 @@ static Name GET_TEMP_RET_IMPORT("getTempRet0"); static Name SET_TEMP_RET_IMPORT("setTempRet0"); struct LegalizeJSInterface : public Pass { + // Adds calls to new imports. + bool addsEffects() override { return true; } + bool full; LegalizeJSInterface(bool full) : full(full) {} diff --git a/src/passes/LogExecution.cpp b/src/passes/LogExecution.cpp index 63ada5819..1b90842bc 100644 --- a/src/passes/LogExecution.cpp +++ b/src/passes/LogExecution.cpp @@ -39,6 +39,9 @@ namespace wasm { Name LOGGER("log_execution"); struct LogExecution : public WalkerPass<PostWalker<LogExecution>> { + // Adds calls to new imports. + bool addsEffects() override { return true; } + void visitLoop(Loop* curr) { curr->body = makeLogCall(curr->body); } void visitReturn(Return* curr) { replaceCurrent(makeLogCall(curr)); } diff --git a/src/passes/SafeHeap.cpp b/src/passes/SafeHeap.cpp index 0e9e8aeef..b2f7db567 100644 --- a/src/passes/SafeHeap.cpp +++ b/src/passes/SafeHeap.cpp @@ -131,6 +131,8 @@ static std::set<Name> findCalledFunctions(Module* module, Name startFunc) { } struct SafeHeap : public Pass { + // Adds calls to new imports. + bool addsEffects() override { return true; } void run(Module* module) override { assert(!module->memories.empty()); diff --git a/src/passes/SpillPointers.cpp b/src/passes/SpillPointers.cpp index f496b8c79..3af7039cd 100644 --- a/src/passes/SpillPointers.cpp +++ b/src/passes/SpillPointers.cpp @@ -37,6 +37,9 @@ struct SpillPointers : public WalkerPass<LivenessWalker<SpillPointers, Visitor<SpillPointers>>> { bool isFunctionParallel() override { return true; } + // Adds writes to memory. + bool addsEffects() override { return true; } + std::unique_ptr<Pass> create() override { return std::make_unique<SpillPointers>(); } diff --git a/src/passes/StackCheck.cpp b/src/passes/StackCheck.cpp index 9fba683b8..229a97f26 100644 --- a/src/passes/StackCheck.cpp +++ b/src/passes/StackCheck.cpp @@ -126,6 +126,9 @@ private: }; struct StackCheck : public Pass { + // Adds calls to new imports. + bool addsEffects() override { return true; } + void run(Module* module) override { Global* stackPointer = getStackPointerGlobal(*module); if (!stackPointer) { diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 3880519da..9b03310b5 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -1056,6 +1056,11 @@ void PassRunner::handleAfterEffects(Pass* pass, Function* func) { if (pass->requiresNonNullableLocalFixups()) { TypeUpdating::handleNonDefaultableLocals(func, *wasm); } + + if (options.funcEffectsMap && pass->addsEffects()) { + // Effects were added, so discard any computed effects for this function. + options.funcEffectsMap->erase(func->name); + } } int PassRunner::getPassDebug() { |