diff options
author | Thomas Lively <tlively@google.com> | 2022-09-30 18:17:45 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-30 23:17:45 +0000 |
commit | 2055ea3fd0391c1abb92cdec54f32274dc7fd971 (patch) | |
tree | 2d9ccaae076b065373b1507d75bc3886232363ec /src | |
parent | 62d056f889d4b94562a104e2fcad318857550d5b (diff) | |
download | binaryen-2055ea3fd0391c1abb92cdec54f32274dc7fd971.tar.gz binaryen-2055ea3fd0391c1abb92cdec54f32274dc7fd971.tar.bz2 binaryen-2055ea3fd0391c1abb92cdec54f32274dc7fd971.zip |
Refactor interaction between Pass and PassRunner (#5093)
Previously only WalkerPasses had access to the `getPassRunner` and
`getPassOptions` methods. Move those methods to `Pass` so all passes can use
them. As a result, the `PassRunner` passed to `Pass::run` and
`Pass::runOnFunction` is no longer necessary, so remove it.
Also update `Pass::create` to return a unique_ptr, which is more efficient than
having it return a raw pointer only to have the `PassRunner` wrap that raw
pointer in a `unique_ptr`.
Delete the unused template `PassRunner::getLast()`, which looks like it was
intended to enable retrieving previous analyses and has been in the code base
since 2015 but is not implemented anywhere.
Diffstat (limited to 'src')
93 files changed, 469 insertions, 336 deletions
diff --git a/src/ir/flat.h b/src/ir/flat.h index 70a6beac7..1a8722726 100644 --- a/src/ir/flat.h +++ b/src/ir/flat.h @@ -118,7 +118,9 @@ inline void verifyFlatness(Module* module) { bool modifiesBinaryenIR() override { return false; } - VerifyFlatness* create() override { return new VerifyFlatness(); } + std::unique_ptr<Pass> create() override { + return std::make_unique<VerifyFlatness>(); + } void doVisitFunction(Function* func) { verifyFlatness(func); } }; diff --git a/src/ir/hashed.h b/src/ir/hashed.h index 060fea453..4e90951f5 100644 --- a/src/ir/hashed.h +++ b/src/ir/hashed.h @@ -38,8 +38,8 @@ struct FunctionHasher : public WalkerPass<PostWalker<FunctionHasher>> { FunctionHasher(Map* output) : output(output), customHasher(ExpressionAnalyzer::nothingHasher) {} - FunctionHasher* create() override { - return new FunctionHasher(output, customHasher); + std::unique_ptr<Pass> create() override { + return std::make_unique<FunctionHasher>(output, customHasher); } static Map createMap(Module* module) { diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h index 319f1a7a4..cdafa9c8c 100644 --- a/src/ir/module-utils.h +++ b/src/ir/module-utils.h @@ -201,7 +201,9 @@ template<typename T> inline void renameFunctions(Module& wasm, T& map) { Updater(T& map) : map(map) {} - Updater* create() override { return new Updater(map); } + std::unique_ptr<Pass> create() override { + return std::make_unique<Updater>(map); + } void visitCall(Call* curr) { maybeUpdate(curr->target); } @@ -392,7 +394,9 @@ struct ParallelFunctionAnalysis { Mapper(Module& module, Map& map, Func work) : module(module), map(map), work(work) {} - Mapper* create() override { return new Mapper(module, map, work); } + std::unique_ptr<Pass> create() override { + return std::make_unique<Mapper>(module, map, work); + } void doWalkFunction(Function* curr) { assert(map.count(curr)); diff --git a/src/ir/type-updating.cpp b/src/ir/type-updating.cpp index c560ce236..2d75f0951 100644 --- a/src/ir/type-updating.cpp +++ b/src/ir/type-updating.cpp @@ -113,7 +113,9 @@ void GlobalTypeRewriter::update() { CodeUpdater(OldToNewTypes& oldToNewTypes) : oldToNewTypes(oldToNewTypes) {} - CodeUpdater* create() override { return new CodeUpdater(oldToNewTypes); } + std::unique_ptr<Pass> create() override { + return std::make_unique<CodeUpdater>(oldToNewTypes); + } Type getNew(Type type) { if (type.isRef()) { diff --git a/src/ir/utils.h b/src/ir/utils.h index b7cd65e19..4f4e5657b 100644 --- a/src/ir/utils.h +++ b/src/ir/utils.h @@ -123,7 +123,9 @@ struct ReFinalize // preserved. bool requiresNonNullableLocalFixups() override { return false; } - Pass* create() override { return new ReFinalize; } + std::unique_ptr<Pass> create() override { + return std::make_unique<ReFinalize>(); + } ReFinalize() { name = "refinalize"; } @@ -189,7 +191,9 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> { struct AutoDrop : public WalkerPass<ExpressionStackWalker<AutoDrop>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new AutoDrop; } + std::unique_ptr<Pass> create() override { + return std::make_unique<AutoDrop>(); + } AutoDrop() { name = "autodrop"; } diff --git a/src/pass.h b/src/pass.h index 45780f9e5..47e7a2789 100644 --- a/src/pass.h +++ b/src/pass.h @@ -271,9 +271,7 @@ struct PassRunner { } // Add a pass given an instance. - template<class P> void add(std::unique_ptr<P> pass) { - doAdd(std::move(pass)); - } + void add(std::unique_ptr<Pass> pass) { doAdd(std::move(pass)); } // Adds the pass if there are no DWARF-related issues. There is an issue if // there is DWARF and if the pass does not support DWARF (as defined by the @@ -312,9 +310,6 @@ struct PassRunner { // Run the passes on a specific function void runOnFunction(Function* func); - // Get the last pass that was already executed of a certain type. - template<class P> P* getLast(); - // When running a pass runner within another pass runner, this // flag should be set. This influences how pass debugging works, // and may influence other things in the future too. @@ -367,18 +362,18 @@ private: // Core pass class // class Pass { + PassRunner* runner = nullptr; + friend PassRunner; + public: virtual ~Pass() = default; // Implement this with code to run the pass on the whole module - virtual void run(PassRunner* runner, Module* module) { - WASM_UNREACHABLE("unimplemented"); - } + virtual void run(Module* module) { WASM_UNREACHABLE("unimplemented"); } // Implement this with code to run the pass on a single function, for // a function-parallel pass - virtual void - runOnFunction(PassRunner* runner, Module* module, Function* function) { + virtual void runOnFunction(Module* module, Function* function) { WASM_UNREACHABLE("unimplemented"); } @@ -404,7 +399,7 @@ public: // This method is used to create instances per function for a // function-parallel pass. You may need to override this if you subclass a // Walker, as otherwise this will create the parent class. - virtual Pass* create() { WASM_UNREACHABLE("unimplenented"); } + virtual std::unique_ptr<Pass> create() { WASM_UNREACHABLE("unimplenented"); } // Whether this pass modifies the Binaryen IR in the module. This is true for // most passes, except for passes that have no side effects, or passes that @@ -429,6 +424,14 @@ public: std::string name; + PassRunner* getPassRunner() { return runner; } + void setPassRunner(PassRunner* runner_) { + assert((!runner || runner == runner_) && "Pass already had a runner"); + runner = runner_; + } + + PassOptions& getPassOptions() { return runner->options; } + protected: Pass() = default; Pass(Pass&) = default; @@ -441,44 +444,49 @@ protected: // template<typename WalkerType> class WalkerPass : public Pass, public WalkerType { - PassRunner* runner = nullptr; protected: typedef WalkerPass<WalkerType> super; public: - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { + assert(getPassRunner()); // Parallel pass running is implemented in the PassRunner. if (isFunctionParallel()) { - PassRunner runner(module); + // TODO: We should almost certainly be propagating pass options here, but + // that is a widespread change, so make sure it doesn't unacceptably + // regress compile times. + PassRunner runner(module /*, getPassOptions()*/); runner.setIsNested(true); - std::unique_ptr<Pass> copy; - copy.reset(create()); - runner.add(std::move(copy)); + runner.add(create()); runner.run(); return; } // Single-thread running just calls the walkModule traversal. - setPassRunner(runner); WalkerType::walkModule(module); } - void - runOnFunction(PassRunner* runner, Module* module, Function* func) override { + // Utility for ad-hoc running. + void run(PassRunner* runner, Module* module) { setPassRunner(runner); + run(module); + } + + void runOnFunction(Module* module, Function* func) override { + assert(getPassRunner()); WalkerType::walkFunctionInModule(func, module); } + // Utility for ad-hoc running. + void runOnFunction(PassRunner* runner, Module* module, Function* func) { + setPassRunner(runner); + runOnFunction(module, func); + } + void runOnModuleCode(PassRunner* runner, Module* module) { setPassRunner(runner); WalkerType::walkModuleCode(module); } - - PassRunner* getPassRunner() { return runner; } - - PassOptions& getPassOptions() { return runner->options; } - - void setPassRunner(PassRunner* runner_) { runner = runner_; } }; } // namespace wasm diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp index b076c77d4..89e9a3ad5 100644 --- a/src/passes/Asyncify.cpp +++ b/src/passes/Asyncify.cpp @@ -839,12 +839,13 @@ struct AsyncifyFlow : public Pass { ModuleAnalyzer* analyzer; - AsyncifyFlow* create() override { return new AsyncifyFlow(analyzer); } + std::unique_ptr<Pass> create() override { + return std::make_unique<AsyncifyFlow>(analyzer); + } AsyncifyFlow(ModuleAnalyzer* analyzer) : analyzer(analyzer) {} - void - runOnFunction(PassRunner* runner, Module* module_, Function* func_) override { + void runOnFunction(Module* module_, Function* func_) override { module = module_; func = func_; builder = make_unique<AsyncifyBuilder>(*module); @@ -1213,7 +1214,9 @@ struct AsyncifyLocals : public WalkerPass<PostWalker<AsyncifyLocals>> { ModuleAnalyzer* analyzer; - AsyncifyLocals* create() override { return new AsyncifyLocals(analyzer); } + std::unique_ptr<Pass> create() override { + return std::make_unique<AsyncifyLocals>(analyzer); + } AsyncifyLocals(ModuleAnalyzer* analyzer) : analyzer(analyzer) {} @@ -1491,52 +1494,49 @@ static std::string getFullImportName(Name module, Name base) { } struct Asyncify : public Pass { - void run(PassRunner* runner, Module* module) override { - bool optimize = runner->options.optimizeLevel > 0; + void run(Module* module) override { + auto& options = getPassOptions(); + bool optimize = options.optimizeLevel > 0; // Ensure there is a memory, as we need it. MemoryUtils::ensureExists(module); // Find which things can change the state. auto stateChangingImports = String::trim(read_possible_response_file( - runner->options.getArgumentOrDefault("asyncify-imports", ""))); + options.getArgumentOrDefault("asyncify-imports", ""))); auto ignoreImports = - runner->options.getArgumentOrDefault("asyncify-ignore-imports", ""); + options.getArgumentOrDefault("asyncify-ignore-imports", ""); bool allImportsCanChangeState = stateChangingImports == "" && ignoreImports == ""; String::Split listedImports(stateChangingImports, ","); // TODO: consider renaming asyncify-ignore-indirect to // asyncify-ignore-nondirect, but that could break users. - auto ignoreNonDirect = runner->options.getArgumentOrDefault( - "asyncify-ignore-indirect", "") == ""; + auto ignoreNonDirect = + options.getArgumentOrDefault("asyncify-ignore-indirect", "") == ""; std::string removeListInput = - runner->options.getArgumentOrDefault("asyncify-removelist", ""); + options.getArgumentOrDefault("asyncify-removelist", ""); if (removeListInput.empty()) { // Support old name for now to avoid immediate breakage TODO remove - removeListInput = - runner->options.getArgumentOrDefault("asyncify-blacklist", ""); + removeListInput = options.getArgumentOrDefault("asyncify-blacklist", ""); } String::Split removeList( String::trim(read_possible_response_file(removeListInput)), ","); String::Split addList( String::trim(read_possible_response_file( - runner->options.getArgumentOrDefault("asyncify-addlist", ""))), + options.getArgumentOrDefault("asyncify-addlist", ""))), ","); std::string onlyListInput = - runner->options.getArgumentOrDefault("asyncify-onlylist", ""); + options.getArgumentOrDefault("asyncify-onlylist", ""); if (onlyListInput.empty()) { // Support old name for now to avoid immediate breakage TODO remove - onlyListInput = - runner->options.getArgumentOrDefault("asyncify-whitelist", ""); + onlyListInput = options.getArgumentOrDefault("asyncify-whitelist", ""); } String::Split onlyList( String::trim(read_possible_response_file(onlyListInput)), ","); - auto asserts = - runner->options.getArgumentOrDefault("asyncify-asserts", "") != ""; - auto verbose = - runner->options.getArgumentOrDefault("asyncify-verbose", "") != ""; + auto asserts = options.getArgumentOrDefault("asyncify-asserts", "") != ""; + auto verbose = options.getArgumentOrDefault("asyncify-verbose", "") != ""; auto relocatable = - runner->options.getArgumentOrDefault("asyncify-relocatable", "") != ""; + options.getArgumentOrDefault("asyncify-relocatable", "") != ""; removeList = handleBracketingOperators(removeList); addList = handleBracketingOperators(addList); @@ -1716,8 +1716,9 @@ struct ModAsyncify ModAsyncify<neverRewind, neverUnwind, importsAlwaysUnwind>>> { bool isFunctionParallel() override { return true; } - ModAsyncify* create() override { - return new ModAsyncify<neverRewind, neverUnwind, importsAlwaysUnwind>(); + std::unique_ptr<Pass> create() override { + return std::make_unique< + ModAsyncify<neverRewind, neverUnwind, importsAlwaysUnwind>>(); } void doWalkFunction(Function* func) { @@ -1840,7 +1841,7 @@ Pass* createModAsyncifyAlwaysOnlyUnwindPass() { // Assume that we never unwind, but may still rewind. // struct ModAsyncifyNeverUnwind : public Pass { - void run(PassRunner* runner, Module* module) override {} + void run(Module* module) override {} }; Pass* createModAsyncifyNeverUnwindPass() { diff --git a/src/passes/AvoidReinterprets.cpp b/src/passes/AvoidReinterprets.cpp index feea4871f..3f4795303 100644 --- a/src/passes/AvoidReinterprets.cpp +++ b/src/passes/AvoidReinterprets.cpp @@ -76,7 +76,9 @@ static bool isReinterpret(Unary* curr) { struct AvoidReinterprets : public WalkerPass<PostWalker<AvoidReinterprets>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new AvoidReinterprets; } + std::unique_ptr<Pass> create() override { + return std::make_unique<AvoidReinterprets>(); + } struct Info { // Info used when analyzing. diff --git a/src/passes/CoalesceLocals.cpp b/src/passes/CoalesceLocals.cpp index edf142039..558be07ff 100644 --- a/src/passes/CoalesceLocals.cpp +++ b/src/passes/CoalesceLocals.cpp @@ -51,7 +51,9 @@ struct CoalesceLocals // FIXME DWARF updating does not handle local changes yet. bool invalidatesDWARF() override { return true; } - Pass* create() override { return new CoalesceLocals; } + std::unique_ptr<Pass> create() override { + return std::make_unique<CoalesceLocals>(); + } // main entry point @@ -580,7 +582,9 @@ void CoalesceLocals::applyIndices(std::vector<Index>& indices, } struct CoalesceLocalsWithLearning : public CoalesceLocals { - virtual Pass* create() override { return new CoalesceLocalsWithLearning; } + std::unique_ptr<Pass> create() override { + return std::make_unique<CoalesceLocalsWithLearning>(); + } virtual void pickIndices(std::vector<Index>& indices) override; }; diff --git a/src/passes/CodeFolding.cpp b/src/passes/CodeFolding.cpp index 0323223e1..0e57a79a2 100644 --- a/src/passes/CodeFolding.cpp +++ b/src/passes/CodeFolding.cpp @@ -86,7 +86,9 @@ struct ExpressionMarker struct CodeFolding : public WalkerPass<ControlFlowWalker<CodeFolding>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new CodeFolding; } + std::unique_ptr<Pass> create() override { + return std::make_unique<CodeFolding>(); + } // information about a "tail" - code that reaches a point that we can // merge (e.g., a branch and some code leading up to it) diff --git a/src/passes/CodePushing.cpp b/src/passes/CodePushing.cpp index 5026773d4..c71078558 100644 --- a/src/passes/CodePushing.cpp +++ b/src/passes/CodePushing.cpp @@ -249,7 +249,9 @@ struct CodePushing : public WalkerPass<PostWalker<CodePushing>> { // way), so validation will be preserved. bool requiresNonNullableLocalFixups() override { return false; } - Pass* create() override { return new CodePushing; } + std::unique_ptr<Pass> create() override { + return std::make_unique<CodePushing>(); + } LocalAnalyzer analyzer; diff --git a/src/passes/ConstHoisting.cpp b/src/passes/ConstHoisting.cpp index 3d9ac5e90..6463221f4 100644 --- a/src/passes/ConstHoisting.cpp +++ b/src/passes/ConstHoisting.cpp @@ -44,7 +44,9 @@ static const Index MIN_USES = 2; struct ConstHoisting : public WalkerPass<PostWalker<ConstHoisting>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new ConstHoisting; } + std::unique_ptr<Pass> create() override { + return std::make_unique<ConstHoisting>(); + } InsertOrderedMap<Literal, std::vector<Expression**>> uses; diff --git a/src/passes/ConstantFieldPropagation.cpp b/src/passes/ConstantFieldPropagation.cpp index 0ec889e36..0f66fe28b 100644 --- a/src/passes/ConstantFieldPropagation.cpp +++ b/src/passes/ConstantFieldPropagation.cpp @@ -55,7 +55,9 @@ struct FunctionOptimizer : public WalkerPass<PostWalker<FunctionOptimizer>> { // Only modifies struct.get operations. bool requiresNonNullableLocalFixups() override { return false; } - Pass* create() override { return new FunctionOptimizer(infos); } + std::unique_ptr<Pass> create() override { + return std::make_unique<FunctionOptimizer>(infos); + } FunctionOptimizer(PCVStructValuesMap& infos) : infos(infos) {} @@ -126,8 +128,8 @@ private: struct PCVScanner : public StructUtils::StructScanner<PossibleConstantValues, PCVScanner> { - Pass* create() override { - return new PCVScanner(functionNewInfos, functionSetGetInfos); + std::unique_ptr<Pass> create() override { + return std::make_unique<PCVScanner>(functionNewInfos, functionSetGetInfos); } PCVScanner(StructUtils::FunctionStructValuesMap<PossibleConstantValues>& @@ -181,7 +183,7 @@ struct ConstantFieldPropagation : public Pass { // Only modifies struct.get operations. bool requiresNonNullableLocalFixups() override { return false; } - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { if (!module->features.hasGC()) { return; } @@ -193,6 +195,7 @@ struct ConstantFieldPropagation : public Pass { PCVFunctionStructValuesMap functionNewInfos(*module), functionSetInfos(*module); PCVScanner scanner(functionNewInfos, functionSetInfos); + auto* runner = getPassRunner(); scanner.run(runner, module); scanner.runOnModuleCode(runner, module); diff --git a/src/passes/DWARF.cpp b/src/passes/DWARF.cpp index bc2af3292..efde51ad6 100644 --- a/src/passes/DWARF.cpp +++ b/src/passes/DWARF.cpp @@ -30,9 +30,7 @@ namespace wasm { struct DWARFDump : public Pass { - void run(PassRunner* runner, Module* module) override { - Debug::dumpDWARF(*module); - } + void run(Module* module) override { Debug::dumpDWARF(*module); } }; Pass* createDWARFDumpPass() { return new DWARFDump(); } diff --git a/src/passes/DataFlowOpts.cpp b/src/passes/DataFlowOpts.cpp index 40e0c3c48..79878f4c9 100644 --- a/src/passes/DataFlowOpts.cpp +++ b/src/passes/DataFlowOpts.cpp @@ -39,7 +39,9 @@ namespace wasm { struct DataFlowOpts : public WalkerPass<PostWalker<DataFlowOpts>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new DataFlowOpts; } + std::unique_ptr<Pass> create() override { + return std::make_unique<DataFlowOpts>(); + } DataFlow::Users nodeUsers; diff --git a/src/passes/DeAlign.cpp b/src/passes/DeAlign.cpp index 795b6a228..15adc2ed6 100644 --- a/src/passes/DeAlign.cpp +++ b/src/passes/DeAlign.cpp @@ -27,7 +27,9 @@ namespace wasm { struct DeAlign : public WalkerPass<PostWalker<DeAlign>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new DeAlign(); } + std::unique_ptr<Pass> create() override { + return std::make_unique<DeAlign>(); + } void visitLoad(Load* curr) { curr->align = 1; } diff --git a/src/passes/DeadArgumentElimination.cpp b/src/passes/DeadArgumentElimination.cpp index 784aec31a..b84ebddd5 100644 --- a/src/passes/DeadArgumentElimination.cpp +++ b/src/passes/DeadArgumentElimination.cpp @@ -90,7 +90,9 @@ struct DAEScanner : public WalkerPass<PostWalker<DAEScanner, Visitor<DAEScanner>>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new DAEScanner(infoMap); } + std::unique_ptr<Pass> create() override { + return std::make_unique<DAEScanner>(infoMap); + } DAEScanner(DAEFunctionInfoMap* infoMap) : infoMap(infoMap) {} @@ -172,16 +174,16 @@ struct DAE : public Pass { bool optimize = false; - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { // Iterate to convergence. while (1) { - if (!iteration(runner, module)) { + if (!iteration(module)) { break; } } } - bool iteration(PassRunner* runner, Module* module) { + bool iteration(Module* module) { allDroppedCalls.clear(); DAEFunctionInfoMap infoMap; @@ -198,7 +200,7 @@ struct DAE : public Pass { } } // Scan all the functions. - scanner.run(runner, module); + scanner.run(getPassRunner(), module); // Combine all the info. std::map<Name, std::vector<Call*>> allCalls; std::unordered_set<Name> tailCallees; @@ -245,7 +247,7 @@ struct DAE : public Pass { // Changing a call expression's return type can propagate out to its // parents, and so we must refinalize. // TODO: We could track in which functions we actually make changes. - ReFinalize().run(runner, module); + ReFinalize().run(getPassRunner(), module); } // Track which functions we changed, and optimize them later if necessary. std::unordered_set<Function*> changed; @@ -260,7 +262,7 @@ struct DAE : public Pass { continue; } auto removedIndexes = ParamUtils::removeParameters( - {func}, infoMap[name].unusedParams, calls, {}, module, runner); + {func}, infoMap[name].unusedParams, calls, {}, module, getPassRunner()); if (!removedIndexes.empty()) { // Success! changed.insert(func); @@ -304,7 +306,7 @@ struct DAE : public Pass { } } if (optimize && !changed.empty()) { - OptUtils::optimizeAfterInlining(changed, module, runner); + OptUtils::optimizeAfterInlining(changed, module, getPassRunner()); } return !changed.empty() || refinedReturnTypes; } diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp index caafb755d..0b382f465 100644 --- a/src/passes/DeadCodeElimination.cpp +++ b/src/passes/DeadCodeElimination.cpp @@ -48,7 +48,9 @@ struct DeadCodeElimination // local.get might have prevented validation). bool requiresNonNullableLocalFixups() override { return false; } - Pass* create() override { return new DeadCodeElimination; } + std::unique_ptr<Pass> create() override { + return std::make_unique<DeadCodeElimination>(); + } // as we remove code, we must keep the types of other nodes valid TypeUpdater typeUpdater; diff --git a/src/passes/Directize.cpp b/src/passes/Directize.cpp index af020aca6..ba99d62e9 100644 --- a/src/passes/Directize.cpp +++ b/src/passes/Directize.cpp @@ -69,7 +69,9 @@ using TableInfoMap = std::unordered_map<Name, TableInfo>; struct FunctionDirectizer : public WalkerPass<PostWalker<FunctionDirectizer>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new FunctionDirectizer(tables); } + std::unique_ptr<Pass> create() override { + return std::make_unique<FunctionDirectizer>(tables); + } FunctionDirectizer(const TableInfoMap& tables) : tables(tables) {} @@ -199,14 +201,14 @@ private: }; struct Directize : public Pass { - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { if (module->tables.empty()) { return; } // TODO: consider a per-table option here auto initialContentsImmutable = - runner->options.getArgumentOrDefault( + getPassOptions().getArgumentOrDefault( "directize-initial-contents-immutable", "") != ""; // Set up the initial info. @@ -273,7 +275,7 @@ struct Directize : public Pass { } // We can optimize! - FunctionDirectizer(tables).run(runner, module); + FunctionDirectizer(tables).run(getPassRunner(), module); } }; diff --git a/src/passes/DuplicateFunctionElimination.cpp b/src/passes/DuplicateFunctionElimination.cpp index 2ebdca4ba..e797cd843 100644 --- a/src/passes/DuplicateFunctionElimination.cpp +++ b/src/passes/DuplicateFunctionElimination.cpp @@ -37,11 +37,11 @@ struct DuplicateFunctionElimination : public Pass { // This pass merges functions but does not alter their contents. bool requiresNonNullableLocalFixups() override { return false; } - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { // Multiple iterations may be necessary: A and B may be identical only after // we see the functions C1 and C2 that they call are in fact identical. // Rarely, such "chains" can be very long, so we limit how many we do. - auto& options = runner->options; + auto& options = getPassOptions(); Index limit; if (options.optimizeLevel >= 3 || options.shrinkLevel >= 1) { limit = module->functions.size(); // no limit @@ -56,7 +56,7 @@ struct DuplicateFunctionElimination : public Pass { limit--; // Hash all the functions auto hashes = FunctionHasher::createMap(module); - FunctionHasher(&hashes).run(runner, module); + FunctionHasher(&hashes).run(getPassRunner(), module); // Find hash-equal groups std::map<uint32_t, std::vector<Function*>> hashGroups; ModuleUtils::iterDefinedFunctions(*module, [&](Function* func) { @@ -96,7 +96,7 @@ struct DuplicateFunctionElimination : public Pass { // remove the duplicates module->removeFunctions( [&](Function* func) { return duplicates.count(func->name) > 0; }); - OptUtils::replaceFunctions(runner, *module, replacements); + OptUtils::replaceFunctions(getPassRunner(), *module, replacements); } else { break; } diff --git a/src/passes/DuplicateImportElimination.cpp b/src/passes/DuplicateImportElimination.cpp index 1a0319e3a..33ce2288a 100644 --- a/src/passes/DuplicateImportElimination.cpp +++ b/src/passes/DuplicateImportElimination.cpp @@ -31,7 +31,7 @@ struct DuplicateImportElimination : public Pass { // This pass does not alter function contents. bool requiresNonNullableLocalFixups() override { return false; } - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { ImportInfo imports(*module); std::map<Name, Name> replacements; std::map<std::pair<Name, Name>, Name> seen; @@ -54,7 +54,7 @@ struct DuplicateImportElimination : public Pass { } if (!replacements.empty()) { module->updateMaps(); - OptUtils::replaceFunctions(runner, *module, replacements); + OptUtils::replaceFunctions(getPassRunner(), *module, replacements); for (auto name : toRemove) { module->removeFunction(name); } diff --git a/src/passes/ExtractFunction.cpp b/src/passes/ExtractFunction.cpp index f75c04cbe..e3f2a5538 100644 --- a/src/passes/ExtractFunction.cpp +++ b/src/passes/ExtractFunction.cpp @@ -54,25 +54,24 @@ static void extract(PassRunner* runner, Module* module, Name name) { // Remove unneeded things. PassRunner postRunner(runner); postRunner.add("remove-unused-module-elements"); - postRunner.setIsNested(true); postRunner.run(); } struct ExtractFunction : public Pass { - void run(PassRunner* runner, Module* module) override { - Name name = runner->options.getArgument( + void run(Module* module) override { + Name name = getPassOptions().getArgument( "extract-function", "ExtractFunction usage: wasm-opt --extract-function=FUNCTION_NAME"); - extract(runner, module, name); + extract(getPassRunner(), module, name); } }; struct ExtractFunctionIndex : public Pass { - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { std::string index = - runner->options.getArgument("extract-function-index", - "ExtractFunctionIndex usage: wasm-opt " - "--extract-function-index=FUNCTION_INDEX"); + getPassOptions().getArgument("extract-function-index", + "ExtractFunctionIndex usage: wasm-opt " + "--extract-function-index=FUNCTION_INDEX"); for (char c : index) { if (!std::isdigit(c)) { Fatal() << "Expected numeric function index"; @@ -85,7 +84,7 @@ struct ExtractFunctionIndex : public Pass { } // Assumes imports are at the beginning Name name = module->functions[i]->name; - extract(runner, module, name); + extract(getPassRunner(), module, name); } }; diff --git a/src/passes/Flatten.cpp b/src/passes/Flatten.cpp index 771183d2c..e8dec3010 100644 --- a/src/passes/Flatten.cpp +++ b/src/passes/Flatten.cpp @@ -76,7 +76,9 @@ struct Flatten // FIXME DWARF updating does not handle local changes yet. bool invalidatesDWARF() override { return true; } - Pass* create() override { return new Flatten; } + std::unique_ptr<Pass> create() override { + return std::make_unique<Flatten>(); + } // For each expression, a bunch of expressions that should execute right // before it diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp index 5e62ec9fc..80818907f 100644 --- a/src/passes/FuncCastEmulation.cpp +++ b/src/passes/FuncCastEmulation.cpp @@ -116,8 +116,8 @@ struct ParallelFuncCastEmulation : public WalkerPass<PostWalker<ParallelFuncCastEmulation>> { bool isFunctionParallel() override { return true; } - Pass* create() override { - return new ParallelFuncCastEmulation(ABIType, numParams); + std::unique_ptr<Pass> create() override { + return std::make_unique<ParallelFuncCastEmulation>(ABIType, numParams); } ParallelFuncCastEmulation(HeapType ABIType, Index numParams) @@ -151,9 +151,9 @@ private: }; struct FuncCastEmulation : public Pass { - void run(PassRunner* runner, Module* module) override { - Index numParams = - std::stoul(runner->options.getArgumentOrDefault("max-func-params", "16")); + void run(Module* module) override { + Index numParams = std::stoul( + getPassOptions().getArgumentOrDefault("max-func-params", "16")); // we just need the one ABI function type for all indirect calls HeapType ABIType( Signature(Type(std::vector<Type>(numParams, Type::i64)), Type::i64)); @@ -171,7 +171,7 @@ struct FuncCastEmulation : public Pass { }); // update call_indirects - ParallelFuncCastEmulation(ABIType, numParams).run(runner, module); + ParallelFuncCastEmulation(ABIType, numParams).run(getPassRunner(), module); } private: diff --git a/src/passes/GUFA.cpp b/src/passes/GUFA.cpp index 1f620f8db..eedf5f20c 100644 --- a/src/passes/GUFA.cpp +++ b/src/passes/GUFA.cpp @@ -63,8 +63,8 @@ struct GUFAOptimizer GUFAOptimizer(ContentOracle& oracle, bool optimizing) : oracle(oracle), optimizing(optimizing) {} - GUFAOptimizer* create() override { - return new GUFAOptimizer(oracle, optimizing); + std::unique_ptr<Pass> create() override { + return std::make_unique<GUFAOptimizer>(oracle, optimizing); } bool optimized = false; @@ -289,8 +289,7 @@ struct GUFAOptimizer return; } - PassRunner runner(getModule(), getPassOptions()); - runner.setIsNested(true); + PassRunner runner(getPassRunner()); // New unreachables we added have created dead code we can remove. If we do // not do this, then running GUFA repeatedly can actually increase code size // (by adding multiple unneeded unreachables). @@ -329,9 +328,9 @@ struct GUFAPass : public Pass { GUFAPass(bool optimizing) : optimizing(optimizing) {} - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { ContentOracle oracle(*module); - GUFAOptimizer(oracle, optimizing).run(runner, module); + GUFAOptimizer(oracle, optimizing).run(getPassRunner(), module); } }; diff --git a/src/passes/GlobalEffects.cpp b/src/passes/GlobalEffects.cpp index 2f816a0bd..6ed2d413a 100644 --- a/src/passes/GlobalEffects.cpp +++ b/src/passes/GlobalEffects.cpp @@ -26,11 +26,11 @@ namespace wasm { struct GenerateGlobalEffects : public Pass { - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { // TODO: Full transitive closure of effects. For now, we just look at each // function by itself. - auto& funcEffectsMap = runner->options.funcEffectsMap; + auto& funcEffectsMap = getPassOptions().funcEffectsMap; // First, clear any previous effects. funcEffectsMap.reset(); @@ -50,7 +50,7 @@ struct GenerateGlobalEffects : public Pass { // Gather the effects. auto effects = - std::make_unique<EffectAnalyzer>(runner->options, *module, func); + std::make_unique<EffectAnalyzer>(getPassOptions(), *module, func); // If the body has a call, give up - that means we can't infer a more // specific set of effects than the pessimistic case of just assuming @@ -80,9 +80,7 @@ struct GenerateGlobalEffects : public Pass { }; struct DiscardGlobalEffects : public Pass { - void run(PassRunner* runner, Module* module) override { - runner->options.funcEffectsMap.reset(); - } + void run(Module* module) override { getPassOptions().funcEffectsMap.reset(); } }; Pass* createGenerateGlobalEffectsPass() { return new GenerateGlobalEffects(); } diff --git a/src/passes/GlobalRefining.cpp b/src/passes/GlobalRefining.cpp index 626fbaeb5..f3bea3d3d 100644 --- a/src/passes/GlobalRefining.cpp +++ b/src/passes/GlobalRefining.cpp @@ -34,7 +34,7 @@ struct GlobalRefining : public Pass { // Only modifies globals and global.get operations. bool requiresNonNullableLocalFixups() override { return false; } - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { if (!module->features.hasGC()) { return; } @@ -114,7 +114,9 @@ struct GlobalRefining : public Pass { GetUpdater(GlobalRefining& parent, Module& wasm) : parent(parent), wasm(wasm) {} - GetUpdater* create() override { return new GetUpdater(parent, wasm); } + std::unique_ptr<Pass> create() override { + return std::make_unique<GetUpdater>(parent, wasm); + } // If we modify anything in a function then we must refinalize so that // types propagate outwards. @@ -135,7 +137,7 @@ struct GlobalRefining : public Pass { } } }; - GetUpdater(*this, *module).run(runner, module); + GetUpdater(*this, *module).run(getPassRunner(), module); } }; diff --git a/src/passes/GlobalStructInference.cpp b/src/passes/GlobalStructInference.cpp index 1cba976a6..d0810a7fa 100644 --- a/src/passes/GlobalStructInference.cpp +++ b/src/passes/GlobalStructInference.cpp @@ -64,7 +64,7 @@ struct GlobalStructInference : public Pass { // them. If a global is not present here, it cannot be optimized. std::unordered_map<HeapType, std::vector<Name>> typeGlobals; - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { if (!module->features.hasGC()) { return; } @@ -185,7 +185,9 @@ struct GlobalStructInference : public Pass { : public WalkerPass<PostWalker<FunctionOptimizer>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new FunctionOptimizer(parent); } + std::unique_ptr<Pass> create() override { + return std::make_unique<FunctionOptimizer>(parent); + } FunctionOptimizer(GlobalStructInference& parent) : parent(parent) {} @@ -312,7 +314,7 @@ struct GlobalStructInference : public Pass { GlobalStructInference& parent; }; - FunctionOptimizer(*this).run(runner, module); + FunctionOptimizer(*this).run(getPassRunner(), module); } }; diff --git a/src/passes/GlobalTypeOptimization.cpp b/src/passes/GlobalTypeOptimization.cpp index dad54d116..694523200 100644 --- a/src/passes/GlobalTypeOptimization.cpp +++ b/src/passes/GlobalTypeOptimization.cpp @@ -62,8 +62,9 @@ struct FieldInfo { struct FieldInfoScanner : public StructUtils::StructScanner<FieldInfo, FieldInfoScanner> { - Pass* create() override { - return new FieldInfoScanner(functionNewInfos, functionSetGetInfos); + std::unique_ptr<Pass> create() override { + return std::make_unique<FieldInfoScanner>(functionNewInfos, + functionSetGetInfos); } FieldInfoScanner( @@ -112,7 +113,7 @@ struct GlobalTypeOptimization : public Pass { static const Index RemovedField = Index(-1); std::unordered_map<HeapType, std::vector<Index>> indexesAfterRemovals; - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { if (!module->features.hasGC()) { return; } @@ -124,8 +125,8 @@ struct GlobalTypeOptimization : public Pass { StructUtils::FunctionStructValuesMap<FieldInfo> functionNewInfos(*module), functionSetGetInfos(*module); FieldInfoScanner scanner(functionNewInfos, functionSetGetInfos); - scanner.run(runner, module); - scanner.runOnModuleCode(runner, module); + scanner.run(getPassRunner(), module); + scanner.runOnModuleCode(getPassRunner(), module); // Combine the data from the functions. functionSetGetInfos.combineInto(combinedSetGetInfos); @@ -241,7 +242,7 @@ struct GlobalTypeOptimization : public Pass { // that we can identify, and only after this should we update all the types // throughout the module.) if (!indexesAfterRemovals.empty()) { - removeFieldsInInstructions(runner, *module); + removeFieldsInInstructions(*module); } // Update the types in the entire module. @@ -314,7 +315,7 @@ struct GlobalTypeOptimization : public Pass { // After updating the types to remove certain fields, we must also remove // them from struct instructions. - void removeFieldsInInstructions(PassRunner* runner, Module& wasm) { + void removeFieldsInInstructions(Module& wasm) { struct FieldRemover : public WalkerPass<PostWalker<FieldRemover>> { bool isFunctionParallel() override { return true; } @@ -322,7 +323,9 @@ struct GlobalTypeOptimization : public Pass { FieldRemover(GlobalTypeOptimization& parent) : parent(parent) {} - FieldRemover* create() override { return new FieldRemover(parent); } + std::unique_ptr<Pass> create() override { + return std::make_unique<FieldRemover>(parent); + } void visitStructNew(StructNew* curr) { if (curr->type == Type::unreachable) { @@ -433,8 +436,8 @@ struct GlobalTypeOptimization : public Pass { }; FieldRemover remover(*this); - remover.run(runner, &wasm); - remover.runOnModuleCode(runner, &wasm); + remover.run(getPassRunner(), &wasm); + remover.runOnModuleCode(getPassRunner(), &wasm); } }; diff --git a/src/passes/Heap2Local.cpp b/src/passes/Heap2Local.cpp index 104a5bbcd..91298106d 100644 --- a/src/passes/Heap2Local.cpp +++ b/src/passes/Heap2Local.cpp @@ -732,7 +732,9 @@ struct Heap2LocalOptimizer { struct Heap2Local : public WalkerPass<PostWalker<Heap2Local>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new Heap2Local(); } + std::unique_ptr<Pass> create() override { + return std::make_unique<Heap2Local>(); + } void doWalkFunction(Function* func) { // Multiple rounds of optimization may work in theory, as once we turn one diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp index 002e4568d..313070e9a 100644 --- a/src/passes/I64ToI32Lowering.cpp +++ b/src/passes/I64ToI32Lowering.cpp @@ -99,7 +99,9 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { // TODO: allow module-level transformations in parallel passes bool isFunctionParallel() override { return false; } - Pass* create() override { return new I64ToI32Lowering; } + std::unique_ptr<Pass> create() override { + return std::make_unique<I64ToI32Lowering>(); + } void doWalkModule(Module* module) { if (!builder) { diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp index 21c06e528..c03b404b0 100644 --- a/src/passes/Inlining.cpp +++ b/src/passes/Inlining.cpp @@ -140,8 +140,8 @@ struct FunctionInfoScanner FunctionInfoScanner(NameInfoMap* infos) : infos(infos) {} - FunctionInfoScanner* create() override { - return new FunctionInfoScanner(infos); + std::unique_ptr<Pass> create() override { + return std::make_unique<FunctionInfoScanner>(infos); } void visitLoop(Loop* curr) { @@ -209,7 +209,9 @@ struct Planner : public WalkerPass<PostWalker<Planner>> { Planner(InliningState* state) : state(state) {} - Planner* create() override { return new Planner(state); } + std::unique_ptr<Pass> create() override { + return std::make_unique<Planner>(state); + } void visitCall(Call* curr) { // plan to inline if we know this is valid to inline, and if the call is @@ -832,11 +834,9 @@ struct Inlining : public Pass { std::unique_ptr<FunctionSplitter> functionSplitter; - PassRunner* runner = nullptr; Module* module = nullptr; - void run(PassRunner* runner_, Module* module_) override { - runner = runner_; + void run(Module* module_) override { module = module_; // No point to do more iterations than the number of functions, as it means @@ -919,9 +919,8 @@ struct Inlining : public Pass { infos[func->name]; } { - PassRunner runner(module); FunctionInfoScanner scanner(&infos); - scanner.run(&runner, module); + scanner.run(getPassRunner(), module); scanner.walkModuleCode(module); } for (auto& ex : module->exports) { @@ -935,9 +934,9 @@ struct Inlining : public Pass { // When optimizing heavily for size, we may potentially split functions in // order to inline parts of them. - if (runner->options.optimizeLevel >= 3 && !runner->options.shrinkLevel) { + if (getPassOptions().optimizeLevel >= 3 && !getPassOptions().shrinkLevel) { functionSplitter = - std::make_unique<FunctionSplitter>(module, runner->options); + std::make_unique<FunctionSplitter>(module, getPassOptions()); } } @@ -962,7 +961,7 @@ struct Inlining : public Pass { funcNames.push_back(func->name); } // find and plan inlinings - Planner(&state).run(runner, module); + Planner(&state).run(getPassRunner(), module); // perform inlinings TODO: parallelize std::unordered_map<Name, Index> inlinedUses; // how many uses we inlined // which functions were inlined into @@ -1015,7 +1014,7 @@ struct Inlining : public Pass { wasm::UniqueNameMapper::uniquify(func->body); } if (optimize && inlinedInto.size() > 0) { - OptUtils::optimizeAfterInlining(inlinedInto, module, runner); + OptUtils::optimizeAfterInlining(inlinedInto, module, getPassRunner()); } // remove functions that we no longer need after inlining module->removeFunctions([&](Function* func) { @@ -1028,7 +1027,7 @@ struct Inlining : public Pass { bool worthInlining(Name name) { // Check if the function itself is worth inlining as it is. - if (infos[name].worthInlining(runner->options)) { + if (infos[name].worthInlining(getPassOptions())) { return true; } @@ -1051,7 +1050,7 @@ struct Inlining : public Pass { // are guaranteed to inline after this. Function* getActuallyInlinedFunction(Function* func) { // If we want to inline this function itself, do so. - if (infos[func->name].worthInlining(runner->options)) { + if (infos[func->name].worthInlining(getPassOptions())) { return func; } @@ -1095,7 +1094,7 @@ static const char* MAIN = "main"; static const char* ORIGINAL_MAIN = "__original_main"; struct InlineMainPass : public Pass { - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { auto* main = module->getFunctionOrNull(MAIN); auto* originalMain = module->getFunctionOrNull(ORIGINAL_MAIN); if (!main || main->imported() || !originalMain || diff --git a/src/passes/Intrinsics.cpp b/src/passes/Intrinsics.cpp index 1b5a50bbb..faba23816 100644 --- a/src/passes/Intrinsics.cpp +++ b/src/passes/Intrinsics.cpp @@ -24,7 +24,9 @@ namespace wasm { struct IntrinsicLowering : public WalkerPass<PostWalker<IntrinsicLowering>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new IntrinsicLowering; } + std::unique_ptr<Pass> create() override { + return std::make_unique<IntrinsicLowering>(); + } void visitCall(Call* curr) { if (Intrinsics(*getModule()).isCallWithoutEffects(curr)) { diff --git a/src/passes/JSPI.cpp b/src/passes/JSPI.cpp index c7c8493d8..9660b962d 100644 --- a/src/passes/JSPI.cpp +++ b/src/passes/JSPI.cpp @@ -40,7 +40,7 @@ struct JSPI : public Pass { Type externref = Type(HeapType::ext, Nullable); - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { Builder builder(*module); // Create a global to store the suspender that is passed into exported // functions and will then need to be passed out to the imported functions. diff --git a/src/passes/LegalizeJSInterface.cpp b/src/passes/LegalizeJSInterface.cpp index dd702ba7d..bbef5109d 100644 --- a/src/passes/LegalizeJSInterface.cpp +++ b/src/passes/LegalizeJSInterface.cpp @@ -58,15 +58,15 @@ struct LegalizeJSInterface : public Pass { LegalizeJSInterface(bool full) : full(full) {} - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { setTempRet0 = nullptr; getTempRet0 = nullptr; auto exportOriginals = - !runner->options + !getPassOptions() .getArgumentOrDefault("legalize-js-interface-export-originals", "") .empty(); exportedHelpers = - !runner->options + !getPassOptions() .getArgumentOrDefault("legalize-js-interface-exported-helpers", "") .empty(); // for each illegal export, we must export a legalized stub instead @@ -129,7 +129,9 @@ struct LegalizeJSInterface : public Pass { struct Fixer : public WalkerPass<PostWalker<Fixer>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new Fixer(illegalImportsToLegal); } + std::unique_ptr<Pass> create() override { + return std::make_unique<Fixer>(illegalImportsToLegal); + } std::map<Name, Name>* illegalImportsToLegal; @@ -159,8 +161,8 @@ struct LegalizeJSInterface : public Pass { }; Fixer fixer(&illegalImportsToLegal); - fixer.run(runner, module); - fixer.runOnModuleCode(runner, module); + fixer.run(getPassRunner(), module); + fixer.runOnModuleCode(getPassRunner(), module); // Finally we can remove all the now-unused illegal imports for (const auto& pair : illegalImportsToLegal) { diff --git a/src/passes/LimitSegments.cpp b/src/passes/LimitSegments.cpp index 0af54c582..2ea95b56a 100644 --- a/src/passes/LimitSegments.cpp +++ b/src/passes/LimitSegments.cpp @@ -21,7 +21,7 @@ namespace wasm { struct LimitSegments : public Pass { - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { if (!MemoryUtils::ensureLimitedSegments(*module)) { std::cerr << "Unable to merge segments. " << "wasm VMs may not accept this binary" << std::endl; diff --git a/src/passes/LocalCSE.cpp b/src/passes/LocalCSE.cpp index e777241a4..97d31b9d3 100644 --- a/src/passes/LocalCSE.cpp +++ b/src/passes/LocalCSE.cpp @@ -526,7 +526,9 @@ struct LocalCSE : public WalkerPass<PostWalker<LocalCSE>> { // FIXME DWARF updating does not handle local changes yet. bool invalidatesDWARF() override { return true; } - Pass* create() override { return new LocalCSE(); } + std::unique_ptr<Pass> create() override { + return std::make_unique<LocalCSE>(); + } void doWalkFunction(Function* func) { auto& options = getPassOptions(); diff --git a/src/passes/LocalSubtyping.cpp b/src/passes/LocalSubtyping.cpp index 31e689075..cf8570986 100644 --- a/src/passes/LocalSubtyping.cpp +++ b/src/passes/LocalSubtyping.cpp @@ -41,7 +41,9 @@ struct LocalSubtyping : public WalkerPass<PostWalker<LocalSubtyping>> { // type to be non-nullable if it would validate. bool requiresNonNullableLocalFixups() override { return false; } - Pass* create() override { return new LocalSubtyping(); } + std::unique_ptr<Pass> create() override { + return std::make_unique<LocalSubtyping>(); + } void doWalkFunction(Function* func) { if (!getModule()->features.hasGC()) { diff --git a/src/passes/LoopInvariantCodeMotion.cpp b/src/passes/LoopInvariantCodeMotion.cpp index c70c8e5fe..61c85d8a4 100644 --- a/src/passes/LoopInvariantCodeMotion.cpp +++ b/src/passes/LoopInvariantCodeMotion.cpp @@ -37,7 +37,9 @@ struct LoopInvariantCodeMotion : public WalkerPass<ExpressionStackWalker<LoopInvariantCodeMotion>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new LoopInvariantCodeMotion; } + std::unique_ptr<Pass> create() override { + return std::make_unique<LoopInvariantCodeMotion>(); + } typedef std::unordered_set<LocalSet*> LoopSets; diff --git a/src/passes/MemoryPacking.cpp b/src/passes/MemoryPacking.cpp index 0f2cf6f14..98b9c1df7 100644 --- a/src/passes/MemoryPacking.cpp +++ b/src/passes/MemoryPacking.cpp @@ -99,11 +99,10 @@ struct MemoryPacking : public Pass { // TODO: don't run at all if the module has no memories bool requiresNonNullableLocalFixups() override { return false; } - void run(PassRunner* runner, Module* module) override; + void run(Module* module) override; bool canOptimize(std::vector<std::unique_ptr<Memory>>& memories, - std::vector<std::unique_ptr<DataSegment>>& dataSegments, - const PassOptions& passOptions); - void optimizeBulkMemoryOps(PassRunner* runner, Module* module); + std::vector<std::unique_ptr<DataSegment>>& dataSegments); + void optimizeBulkMemoryOps(Module* module); void getSegmentReferrers(Module* module, ReferrersMap& referrers); void dropUnusedSegments(Module* module, std::vector<std::unique_ptr<DataSegment>>& segments, @@ -123,14 +122,12 @@ struct MemoryPacking : public Pass { const Referrers& referrers, Replacements& replacements, const Index segmentIndex); - void replaceBulkMemoryOps(PassRunner* runner, - Module* module, - Replacements& replacements); + void replaceBulkMemoryOps(Module* module, Replacements& replacements); }; -void MemoryPacking::run(PassRunner* runner, Module* module) { +void MemoryPacking::run(Module* module) { // Does not have multi-memories support - if (!canOptimize(module->memories, module->dataSegments, runner->options)) { + if (!canOptimize(module->memories, module->dataSegments)) { return; } @@ -145,7 +142,7 @@ void MemoryPacking::run(PassRunner* runner, Module* module) { // segments that can be dropped entirely and allows later replacement // creation to make more assumptions about what these instructions will look // like, such as memory.inits not having both zero offset and size. - optimizeBulkMemoryOps(runner, module); + optimizeBulkMemoryOps(module); getSegmentReferrers(module, referrers); dropUnusedSegments(module, segments, referrers); } @@ -181,14 +178,13 @@ void MemoryPacking::run(PassRunner* runner, Module* module) { module->updateDataSegmentsMap(); if (module->features.hasBulkMemory()) { - replaceBulkMemoryOps(runner, module, replacements); + replaceBulkMemoryOps(module, replacements); } } bool MemoryPacking::canOptimize( std::vector<std::unique_ptr<Memory>>& memories, - std::vector<std::unique_ptr<DataSegment>>& dataSegments, - const PassOptions& passOptions) { + std::vector<std::unique_ptr<DataSegment>>& dataSegments) { if (memories.empty() || memories.size() > 1) { return false; } @@ -196,7 +192,7 @@ bool MemoryPacking::canOptimize( // We must optimize under the assumption that memory has been initialized to // zero. That is the case for a memory declared in the module, but for a // memory that is imported, we must be told that it is zero-initialized. - if (memory->imported() && !passOptions.zeroFilledMemory) { + if (memory->imported() && !getPassOptions().zeroFilledMemory) { return false; } @@ -378,14 +374,16 @@ void MemoryPacking::calculateRanges(const std::unique_ptr<DataSegment>& segment, std::swap(ranges, mergedRanges); } -void MemoryPacking::optimizeBulkMemoryOps(PassRunner* runner, Module* module) { +void MemoryPacking::optimizeBulkMemoryOps(Module* module) { struct Optimizer : WalkerPass<PostWalker<Optimizer>> { bool isFunctionParallel() override { return true; } // This operates on linear memory, and does not affect reference locals. bool requiresNonNullableLocalFixups() override { return false; } - Pass* create() override { return new Optimizer; } + std::unique_ptr<Pass> create() override { + return std::make_unique<Optimizer>(); + } bool needsRefinalizing; @@ -448,7 +446,7 @@ void MemoryPacking::optimizeBulkMemoryOps(PassRunner* runner, Module* module) { } } } optimizer; - optimizer.run(runner, module); + optimizer.run(getPassRunner(), module); } void MemoryPacking::getSegmentReferrers(Module* module, @@ -779,8 +777,7 @@ void MemoryPacking::createReplacements(Module* module, } } -void MemoryPacking::replaceBulkMemoryOps(PassRunner* runner, - Module* module, +void MemoryPacking::replaceBulkMemoryOps(Module* module, Replacements& replacements) { struct Replacer : WalkerPass<PostWalker<Replacer>> { bool isFunctionParallel() override { return true; } @@ -791,7 +788,9 @@ void MemoryPacking::replaceBulkMemoryOps(PassRunner* runner, Replacements& replacements; Replacer(Replacements& replacements) : replacements(replacements){}; - Pass* create() override { return new Replacer(replacements); } + std::unique_ptr<Pass> create() override { + return std::make_unique<Replacer>(replacements); + } void visitMemoryInit(MemoryInit* curr) { auto replacement = replacements.find(curr); @@ -805,7 +804,7 @@ void MemoryPacking::replaceBulkMemoryOps(PassRunner* runner, replaceCurrent(replacement->second(getFunction())); } } replacer(replacements); - replacer.run(runner, module); + replacer.run(getPassRunner(), module); } Pass* createMemoryPackingPass() { return new MemoryPacking(); } diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp index 225f4f05d..45b9ebd9e 100644 --- a/src/passes/MergeBlocks.cpp +++ b/src/passes/MergeBlocks.cpp @@ -403,7 +403,9 @@ struct MergeBlocks PostWalker<MergeBlocks, UnifiedExpressionVisitor<MergeBlocks>>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new MergeBlocks; } + std::unique_ptr<Pass> create() override { + return std::make_unique<MergeBlocks>(); + } BranchUtils::BranchSeekerCache branchInfo; diff --git a/src/passes/MergeLocals.cpp b/src/passes/MergeLocals.cpp index e478db739..a7f765cb4 100644 --- a/src/passes/MergeLocals.cpp +++ b/src/passes/MergeLocals.cpp @@ -62,7 +62,9 @@ struct MergeLocals // FIXME DWARF updating does not handle local changes yet. bool invalidatesDWARF() override { return true; } - Pass* create() override { return new MergeLocals(); } + std::unique_ptr<Pass> create() override { + return std::make_unique<MergeLocals>(); + } void doWalkFunction(Function* func) { // first, instrument the graph by modifying each copy diff --git a/src/passes/MergeSimilarFunctions.cpp b/src/passes/MergeSimilarFunctions.cpp index 38cae8059..e5e50423a 100644 --- a/src/passes/MergeSimilarFunctions.cpp +++ b/src/passes/MergeSimilarFunctions.cpp @@ -174,7 +174,7 @@ struct EquivalentClass { struct MergeSimilarFunctions : public Pass { bool invalidatesDWARF() override { return true; } - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { std::vector<EquivalentClass> classes; collectEquivalentClasses(classes, module); std::sort( diff --git a/src/passes/MinifyImportsAndExports.cpp b/src/passes/MinifyImportsAndExports.cpp index 3e919c799..2105f025c 100644 --- a/src/passes/MinifyImportsAndExports.cpp +++ b/src/passes/MinifyImportsAndExports.cpp @@ -59,7 +59,7 @@ private: // Generates minified names that are valid in JS. // Names are computed lazily. - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { // Minify the imported names. Names::MinifiedNameGenerator names; std::map<Name, Name> oldToNew; diff --git a/src/passes/NameList.cpp b/src/passes/NameList.cpp index a0078e263..8556065ba 100644 --- a/src/passes/NameList.cpp +++ b/src/passes/NameList.cpp @@ -28,7 +28,7 @@ namespace wasm { struct NameList : public Pass { bool modifiesBinaryenIR() override { return false; } - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { ModuleUtils::iterDefinedFunctions(*module, [&](Function* func) { std::cout << " " << func->name << " : " << Measurer::measure(func->body) << '\n'; diff --git a/src/passes/NameTypes.cpp b/src/passes/NameTypes.cpp index 3ad35fa1d..fcf6df5ab 100644 --- a/src/passes/NameTypes.cpp +++ b/src/passes/NameTypes.cpp @@ -30,7 +30,7 @@ static const size_t NameLenLimit = 20; struct NameTypes : public Pass { bool requiresNonNullableLocalFixups() override { return false; } - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { // Find all the types. std::vector<HeapType> types = ModuleUtils::collectHeapTypes(*module); diff --git a/src/passes/OnceReduction.cpp b/src/passes/OnceReduction.cpp index 1eb76c29e..c1500f185 100644 --- a/src/passes/OnceReduction.cpp +++ b/src/passes/OnceReduction.cpp @@ -88,7 +88,9 @@ struct Scanner : public WalkerPass<PostWalker<Scanner>> { Scanner(OptInfo& optInfo) : optInfo(optInfo) {} - Scanner* create() override { return new Scanner(optInfo); } + std::unique_ptr<Pass> create() override { + return std::make_unique<Scanner>(optInfo); + } // All the globals we read from. Any read of a global prevents us from // optimizing, unless it is the single read at the top of an "only" function @@ -219,7 +221,9 @@ struct Optimizer Optimizer(OptInfo& optInfo) : optInfo(optInfo) {} - Optimizer* create() override { return new Optimizer(optInfo); } + std::unique_ptr<Pass> create() override { + return std::make_unique<Optimizer>(optInfo); + } void visitGlobalSet(GlobalSet* curr) { if (currBasicBlock) { @@ -344,7 +348,7 @@ private: } // anonymous namespace struct OnceReduction : public Pass { - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { OptInfo optInfo; // Fill out the initial data. @@ -374,7 +378,7 @@ struct OnceReduction : public Pass { } // Scan the module to find out which globals and functions are "once". - Scanner(optInfo).run(runner, module); + Scanner(optInfo).run(getPassRunner(), module); // Combine the information. We found which globals appear to be "once", but // other information may have proven they are not so, in fact. Specifically, @@ -419,7 +423,7 @@ struct OnceReduction : public Pass { optInfo.newOnceGlobalsSetInFuncs[func->name]; } - Optimizer(optInfo).run(runner, module); + Optimizer(optInfo).run(getPassRunner(), module); optInfo.onceGlobalsSetInFuncs = std::move(optInfo.newOnceGlobalsSetInFuncs); diff --git a/src/passes/OptimizeAddedConstants.cpp b/src/passes/OptimizeAddedConstants.cpp index f48989d5b..aadff5112 100644 --- a/src/passes/OptimizeAddedConstants.cpp +++ b/src/passes/OptimizeAddedConstants.cpp @@ -264,7 +264,9 @@ struct OptimizeAddedConstants OptimizeAddedConstants(bool propagate) : propagate(propagate) {} - Pass* create() override { return new OptimizeAddedConstants(propagate); } + std::unique_ptr<Pass> create() override { + return std::make_unique<OptimizeAddedConstants>(propagate); + } void visitLoad(Load* curr) { MemoryAccessOptimizer<OptimizeAddedConstants, Load> optimizer( diff --git a/src/passes/OptimizeForJS.cpp b/src/passes/OptimizeForJS.cpp index 589374c06..0f68412dd 100644 --- a/src/passes/OptimizeForJS.cpp +++ b/src/passes/OptimizeForJS.cpp @@ -28,7 +28,9 @@ namespace wasm { struct OptimizeForJSPass : public WalkerPass<PostWalker<OptimizeForJSPass>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new OptimizeForJSPass; } + std::unique_ptr<Pass> create() override { + return std::make_unique<OptimizeForJSPass>(); + } void visitBinary(Binary* curr) { using namespace Abstract; diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index e9cf3baaa..fc034a24f 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -201,7 +201,9 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new OptimizeInstructions; } + std::unique_ptr<Pass> create() override { + return std::make_unique<OptimizeInstructions>(); + } bool fastMath; diff --git a/src/passes/PickLoadSigns.cpp b/src/passes/PickLoadSigns.cpp index f55013ff3..d30e0a381 100644 --- a/src/passes/PickLoadSigns.cpp +++ b/src/passes/PickLoadSigns.cpp @@ -28,7 +28,9 @@ namespace wasm { struct PickLoadSigns : public WalkerPass<ExpressionStackWalker<PickLoadSigns>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new PickLoadSigns; } + std::unique_ptr<Pass> create() override { + return std::make_unique<PickLoadSigns>(); + } struct Usage { Index signedUsages = 0; diff --git a/src/passes/Poppify.cpp b/src/passes/Poppify.cpp index f787fb904..582753c4b 100644 --- a/src/passes/Poppify.cpp +++ b/src/passes/Poppify.cpp @@ -447,21 +447,22 @@ void Poppifier::poppify(Expression* expr) { class PoppifyFunctionsPass : public Pass { bool isFunctionParallel() override { return true; } - void - runOnFunction(PassRunner* runner, Module* module, Function* func) override { + void runOnFunction(Module* module, Function* func) override { if (func->profile != IRProfile::Poppy) { Poppifier(func, module).write(); func->profile = IRProfile::Poppy; } } - Pass* create() override { return new PoppifyFunctionsPass; } + std::unique_ptr<Pass> create() override { + return std::make_unique<PoppifyFunctionsPass>(); + } }; } // anonymous namespace class PoppifyPass : public Pass { - void run(PassRunner* runner, Module* module) { - PassRunner subRunner(runner); + void run(Module* module) { + PassRunner subRunner(getPassRunner()); subRunner.add(std::make_unique<PoppifyFunctionsPass>()); // TODO: Enable this once it handles Poppy blocks correctly // subRunner.add(std::make_unique<ReFinalize>()); diff --git a/src/passes/PostEmscripten.cpp b/src/passes/PostEmscripten.cpp index b4828a852..e17c529bb 100644 --- a/src/passes/PostEmscripten.cpp +++ b/src/passes/PostEmscripten.cpp @@ -46,7 +46,9 @@ struct SegmentRemover : WalkerPass<PostWalker<SegmentRemover>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new SegmentRemover(segment); } + std::unique_ptr<Pass> create() override { + return std::make_unique<SegmentRemover>(segment); + } void visitMemoryInit(MemoryInit* curr) { if (segment == curr->segment) { @@ -197,14 +199,14 @@ struct EmJsWalker : public PostWalker<EmJsWalker> { } // namespace struct PostEmscripten : public Pass { - void run(PassRunner* runner, Module* module) override { - removeExports(runner, *module); - removeEmJsExports(runner, *module); + void run(Module* module) override { + removeExports(*module); + removeEmJsExports(*module); // Optimize exceptions - optimizeExceptions(runner, module); + optimizeExceptions(module); } - void removeExports(PassRunner* runner, Module& module) { + void removeExports(Module& module) { std::vector<Address> segmentOffsets; // segment index => address offset calcSegmentOffsets(module, segmentOffsets); @@ -216,7 +218,7 @@ struct PostEmscripten : public Pass { module.removeExport("__stop_em_js"); } - void removeEmJsExports(PassRunner* runner, Module& module) { + void removeEmJsExports(Module& module) { EmJsWalker walker; walker.walkModule(&module); for (const Export& exp : walker.toRemove) { @@ -233,7 +235,7 @@ struct PostEmscripten : public Pass { // An invoke is a call to JS with a function pointer; JS does a try-catch // and calls the pointer, catching and reporting any error. If we know no // exception will be thrown, we can simply skip the invoke. - void optimizeExceptions(PassRunner* runner, Module* module) { + void optimizeExceptions(Module* module) { // First, check if this code even uses invokes. bool hasInvokes = false; for (auto& imp : module->functions) { @@ -277,7 +279,9 @@ struct PostEmscripten : public Pass { struct OptimizeInvokes : public WalkerPass<PostWalker<OptimizeInvokes>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new OptimizeInvokes(map, flatTable); } + std::unique_ptr<Pass> create() override { + return std::make_unique<OptimizeInvokes>(map, flatTable); + } std::map<Function*, Info>& map; TableUtils::FlatTable& flatTable; @@ -317,7 +321,7 @@ struct PostEmscripten : public Pass { } } }; - OptimizeInvokes(analyzer.map, flatTable).run(runner, module); + OptimizeInvokes(analyzer.map, flatTable).run(getPassRunner(), module); } }; diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp index 35f218362..466614d14 100644 --- a/src/passes/Precompute.cpp +++ b/src/passes/Precompute.cpp @@ -199,7 +199,9 @@ struct Precompute PostWalker<Precompute, UnifiedExpressionVisitor<Precompute>>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new Precompute(propagate); } + std::unique_ptr<Pass> create() override { + return std::make_unique<Precompute>(propagate); + } bool propagate = false; diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 2a031ad01..01b004d97 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -3365,9 +3365,9 @@ public: bool modifiesBinaryenIR() override { return false; } - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { PrintSExpression print(o); - print.setDebugInfo(runner->options.debugInfo); + print.setDebugInfo(getPassOptions().debugInfo); print.visitModule(module); } }; @@ -3381,10 +3381,10 @@ public: MinifiedPrinter() = default; MinifiedPrinter(std::ostream* o) : Printer(o) {} - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { PrintSExpression print(o); print.setMinify(true); - print.setDebugInfo(runner->options.debugInfo); + print.setDebugInfo(getPassOptions().debugInfo); print.visitModule(module); } }; @@ -3398,10 +3398,10 @@ public: FullPrinter() = default; FullPrinter(std::ostream* o) : Printer(o) {} - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { PrintSExpression print(o); print.setFull(true); - print.setDebugInfo(runner->options.debugInfo); + print.setDebugInfo(getPassOptions().debugInfo); print.currModule = module; print.visitModule(module); } @@ -3416,9 +3416,9 @@ public: PrintStackIR() = default; PrintStackIR(std::ostream* o) : Printer(o) {} - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { PrintSExpression print(o); - print.setDebugInfo(runner->options.debugInfo); + print.setDebugInfo(getPassOptions().debugInfo); print.setStackIR(true); print.currModule = module; print.visitModule(module); @@ -3603,7 +3603,12 @@ namespace std { std::ostream& operator<<(std::ostream& o, wasm::Module& module) { wasm::PassRunner runner(&module); - wasm::Printer(&o).run(&runner, &module); + wasm::Printer printer(&o); + // Do not use runner.run(), since that will cause an infinite recursion in + // BINARYEN_PASS_DEBUG=3, which prints modules (using this function) as part + // of running passes. + printer.setPassRunner(&runner); + printer.run(&module); return o; } diff --git a/src/passes/PrintCallGraph.cpp b/src/passes/PrintCallGraph.cpp index 79938e650..6022c8703 100644 --- a/src/passes/PrintCallGraph.cpp +++ b/src/passes/PrintCallGraph.cpp @@ -33,7 +33,7 @@ namespace wasm { struct PrintCallGraph : public Pass { bool modifiesBinaryenIR() override { return false; } - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { std::ostream& o = std::cout; o << "digraph call {\n" " rankdir = LR;\n" diff --git a/src/passes/PrintFeatures.cpp b/src/passes/PrintFeatures.cpp index 6b89e18d6..4b7e201e9 100644 --- a/src/passes/PrintFeatures.cpp +++ b/src/passes/PrintFeatures.cpp @@ -27,7 +27,7 @@ namespace wasm { struct PrintFeatures : public Pass { bool modifiesBinaryenIR() override { return false; } - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { module->features.iterFeatures([](FeatureSet::Feature f) { std::cout << "--enable-" << FeatureSet::toString(f) << std::endl; }); diff --git a/src/passes/PrintFunctionMap.cpp b/src/passes/PrintFunctionMap.cpp index 325f4e48d..08f5a359b 100644 --- a/src/passes/PrintFunctionMap.cpp +++ b/src/passes/PrintFunctionMap.cpp @@ -34,10 +34,10 @@ namespace wasm { struct PrintFunctionMap : public Pass { bool modifiesBinaryenIR() override { return false; } - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { // If an argument is provided, write to that file; otherwise write to // stdout. - auto outFile = runner->options.getArgumentOrDefault("symbolmap", ""); + auto outFile = getPassOptions().getArgumentOrDefault("symbolmap", ""); Output output(outFile, Flags::Text); auto& o = output.getStream(); Index i = 0; diff --git a/src/passes/ReReloop.cpp b/src/passes/ReReloop.cpp index 4499bb07b..9fef75367 100644 --- a/src/passes/ReReloop.cpp +++ b/src/passes/ReReloop.cpp @@ -36,7 +36,9 @@ namespace wasm { struct ReReloop final : public Pass { bool isFunctionParallel() override { return true; } - Pass* create() override { return new ReReloop; } + std::unique_ptr<Pass> create() override { + return std::make_unique<ReReloop>(); + } std::unique_ptr<CFG::Relooper> relooper; std::unique_ptr<Builder> builder; @@ -291,9 +293,7 @@ struct ReReloop final : public Pass { // TODO: optimize with this? } - void runOnFunction(PassRunner* runner, - Module* module, - Function* function) override { + void runOnFunction(Module* module, Function* function) override { Flat::verifyFlatness(function); // since control flow is flattened, this is pretty simple diff --git a/src/passes/RedundantSetElimination.cpp b/src/passes/RedundantSetElimination.cpp index 0b4cad056..9a60331dd 100644 --- a/src/passes/RedundantSetElimination.cpp +++ b/src/passes/RedundantSetElimination.cpp @@ -63,7 +63,9 @@ struct RedundantSetElimination Info>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new RedundantSetElimination(); } + std::unique_ptr<Pass> create() override { + return std::make_unique<RedundantSetElimination>(); + } Index numLocals; diff --git a/src/passes/RemoveMemory.cpp b/src/passes/RemoveMemory.cpp index 6f2f9aee7..1520be1e8 100644 --- a/src/passes/RemoveMemory.cpp +++ b/src/passes/RemoveMemory.cpp @@ -24,7 +24,7 @@ namespace wasm { struct RemoveMemory : public Pass { - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { module->removeDataSegments([&](DataSegment* curr) { return true; }); } }; diff --git a/src/passes/RemoveNonJSOps.cpp b/src/passes/RemoveNonJSOps.cpp index 84df4ec1e..227046b81 100644 --- a/src/passes/RemoveNonJSOps.cpp +++ b/src/passes/RemoveNonJSOps.cpp @@ -56,7 +56,9 @@ struct RemoveNonJSOpsPass : public WalkerPass<PostWalker<RemoveNonJSOpsPass>> { bool isFunctionParallel() override { return false; } - Pass* create() override { return new RemoveNonJSOpsPass; } + std::unique_ptr<Pass> create() override { + return std::make_unique<RemoveNonJSOpsPass>(); + } void doWalkModule(Module* module) { // Intrinsics may use scratch memory, ensure it. @@ -339,7 +341,9 @@ struct StubUnsupportedJSOpsPass : public WalkerPass<PostWalker<StubUnsupportedJSOpsPass>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new StubUnsupportedJSOpsPass; } + std::unique_ptr<Pass> create() override { + return std::make_unique<StubUnsupportedJSOpsPass>(); + } void visitUnary(Unary* curr) { switch (curr->op) { diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp index b867dc4c2..e0f82b4a4 100644 --- a/src/passes/RemoveUnusedBrs.cpp +++ b/src/passes/RemoveUnusedBrs.cpp @@ -117,7 +117,9 @@ static bool tooCostlyToRunUnconditionally(const PassOptions& passOptions, struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new RemoveUnusedBrs; } + std::unique_ptr<Pass> create() override { + return std::make_unique<RemoveUnusedBrs>(); + } bool anotherCycle; diff --git a/src/passes/RemoveUnusedModuleElements.cpp b/src/passes/RemoveUnusedModuleElements.cpp index 139f6f655..c77bff9af 100644 --- a/src/passes/RemoveUnusedModuleElements.cpp +++ b/src/passes/RemoveUnusedModuleElements.cpp @@ -239,7 +239,7 @@ struct RemoveUnusedModuleElements : public Pass { RemoveUnusedModuleElements(bool rootAllFunctions) : rootAllFunctions(rootAllFunctions) {} - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { std::vector<ModuleElement> roots; // Module start is a root. if (module->start.is()) { diff --git a/src/passes/RemoveUnusedNames.cpp b/src/passes/RemoveUnusedNames.cpp index 4c74245f0..e7cc4aef6 100644 --- a/src/passes/RemoveUnusedNames.cpp +++ b/src/passes/RemoveUnusedNames.cpp @@ -35,7 +35,9 @@ struct RemoveUnusedNames // without names are ignored, see the README section on non-nullable locals). bool requiresNonNullableLocalFixups() override { return false; } - Pass* create() override { return new RemoveUnusedNames; } + std::unique_ptr<Pass> create() override { + return std::make_unique<RemoveUnusedNames>(); + } // We maintain a list of branches that we saw in children, then when we reach // a parent block, we know if it was branched to diff --git a/src/passes/ReorderFunctions.cpp b/src/passes/ReorderFunctions.cpp index 6f87e74a6..b6c7a4984 100644 --- a/src/passes/ReorderFunctions.cpp +++ b/src/passes/ReorderFunctions.cpp @@ -44,7 +44,9 @@ struct CallCountScanner : public WalkerPass<PostWalker<CallCountScanner>> { CallCountScanner(NameCountMap* counts) : counts(counts) {} - CallCountScanner* create() override { return new CallCountScanner(counts); } + std::unique_ptr<Pass> create() override { + return std::make_unique<CallCountScanner>(counts); + } void visitCall(Call* curr) { // can't add a new element in parallel @@ -60,7 +62,7 @@ struct ReorderFunctions : public Pass { // Only reorders functions, does not change their contents. bool requiresNonNullableLocalFixups() override { return false; } - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { NameCountMap counts; // fill in info, as we operate on it in parallel (each function to its own // entry) @@ -68,7 +70,7 @@ struct ReorderFunctions : public Pass { counts[func->name]; } // find counts on function calls - CallCountScanner(&counts).run(runner, module); + CallCountScanner(&counts).run(getPassRunner(), module); // find counts on global usages if (module->start.is()) { counts[module->start]++; diff --git a/src/passes/ReorderLocals.cpp b/src/passes/ReorderLocals.cpp index ce06afd68..d931cca2a 100644 --- a/src/passes/ReorderLocals.cpp +++ b/src/passes/ReorderLocals.cpp @@ -35,7 +35,9 @@ struct ReorderLocals : public WalkerPass<PostWalker<ReorderLocals>> { // Sorting and removing unused locals cannot affect validation. bool requiresNonNullableLocalFixups() override { return false; } - Pass* create() override { return new ReorderLocals; } + std::unique_ptr<Pass> create() override { + return std::make_unique<ReorderLocals>(); + } // local index => times it is used std::vector<Index> counts; diff --git a/src/passes/RoundTrip.cpp b/src/passes/RoundTrip.cpp index f2bdffefb..0e289d529 100644 --- a/src/passes/RoundTrip.cpp +++ b/src/passes/RoundTrip.cpp @@ -28,7 +28,7 @@ namespace wasm { struct RoundTrip : public Pass { - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { BufferWithRandomAccess buffer; // Save features, which would not otherwise make it through a round trip if // the target features section has been stripped. We also need them in order @@ -39,7 +39,7 @@ struct RoundTrip : public Pass { ModuleUtils::clearModule(*module); auto input = buffer.getAsChars(); WasmBinaryBuilder parser(*module, features, input); - parser.setDWARF(runner->options.debugInfo); + parser.setDWARF(getPassOptions().debugInfo); try { parser.read(); } catch (ParseException& p) { diff --git a/src/passes/SSAify.cpp b/src/passes/SSAify.cpp index 089def301..3d9b8bda6 100644 --- a/src/passes/SSAify.cpp +++ b/src/passes/SSAify.cpp @@ -73,7 +73,9 @@ struct SSAify : public Pass { // FIXME DWARF updating does not handle local changes yet. bool invalidatesDWARF() override { return true; } - Pass* create() override { return new SSAify(allowMerges); } + std::unique_ptr<Pass> create() override { + return std::make_unique<SSAify>(allowMerges); + } SSAify(bool allowMerges) : allowMerges(allowMerges) {} @@ -84,8 +86,7 @@ struct SSAify : public Pass { // things we add to the function prologue std::vector<Expression*> functionPrepends; - void - runOnFunction(PassRunner* runner, Module* module_, Function* func_) override { + void runOnFunction(Module* module_, Function* func_) override { module = module_; func = func_; LocalGraph graph(func); diff --git a/src/passes/SafeHeap.cpp b/src/passes/SafeHeap.cpp index eccb521d2..0e9e8aeef 100644 --- a/src/passes/SafeHeap.cpp +++ b/src/passes/SafeHeap.cpp @@ -69,8 +69,8 @@ struct AccessInstrumenter : public WalkerPass<PostWalker<AccessInstrumenter>> { bool isFunctionParallel() override { return true; } - AccessInstrumenter* create() override { - return new AccessInstrumenter(ignoreFunctions); + std::unique_ptr<Pass> create() override { + return std::make_unique<AccessInstrumenter>(ignoreFunctions); } AccessInstrumenter(std::set<Name> ignoreFunctions) @@ -131,10 +131,8 @@ static std::set<Name> findCalledFunctions(Module* module, Name startFunc) { } struct SafeHeap : public Pass { - PassOptions options; - void run(PassRunner* runner, Module* module) override { - options = runner->options; + void run(Module* module) override { assert(!module->memories.empty()); // add imports addImports(module); @@ -147,7 +145,7 @@ struct SafeHeap : public Pass { // not available until after it has run. std::set<Name> ignoreFunctions = findCalledFunctions(module, module->start); ignoreFunctions.insert(getSbrkPtr); - AccessInstrumenter(ignoreFunctions).run(runner, module); + AccessInstrumenter(ignoreFunctions).run(getPassRunner(), module); // add helper checking funcs and imports addGlobals(module, module->features); } @@ -394,9 +392,10 @@ struct SafeHeap : public Pass { Type indexType, bool is64, Name memory) { - auto upperOp = is64 ? options.lowMemoryUnused ? LtUInt64 : EqInt64 - : options.lowMemoryUnused ? LtUInt32 : EqInt32; - auto upperBound = options.lowMemoryUnused ? PassOptions::LowMemoryBound : 0; + bool lowMemUnused = getPassOptions().lowMemoryUnused; + auto upperOp = is64 ? lowMemUnused ? LtUInt64 : EqInt64 + : lowMemUnused ? LtUInt32 : EqInt32; + auto upperBound = lowMemUnused ? PassOptions::LowMemoryBound : 0; Expression* brkLocation; if (sbrk.is()) { brkLocation = diff --git a/src/passes/SetGlobals.cpp b/src/passes/SetGlobals.cpp index 4109eb69b..58a82a50b 100644 --- a/src/passes/SetGlobals.cpp +++ b/src/passes/SetGlobals.cpp @@ -28,8 +28,8 @@ struct SetGlobals : public Pass { // Only modifies globals. bool requiresNonNullableLocalFixups() override { return false; } - void run(PassRunner* runner, Module* module) override { - Name input = runner->options.getArgument( + void run(Module* module) override { + Name input = getPassRunner()->options.getArgument( "set-globals", "SetGlobals usage: wasm-opt --pass-arg=set-globals@x=y,z=w"); diff --git a/src/passes/SignaturePruning.cpp b/src/passes/SignaturePruning.cpp index ca7bd0548..4e6334057 100644 --- a/src/passes/SignaturePruning.cpp +++ b/src/passes/SignaturePruning.cpp @@ -48,7 +48,7 @@ struct SignaturePruning : public Pass { // type has no improvement that we can find, it will not appear in this map. std::unordered_map<HeapType, Signature> newSignatures; - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { if (!module->features.hasGC()) { return; } @@ -193,8 +193,12 @@ struct SignaturePruning : public Pass { } auto oldParams = sig.params; - auto removedIndexes = ParamUtils::removeParameters( - funcs, unusedParams, info.calls, info.callRefs, module, runner); + auto removedIndexes = ParamUtils::removeParameters(funcs, + unusedParams, + info.calls, + info.callRefs, + module, + getPassRunner()); if (removedIndexes.empty()) { continue; } diff --git a/src/passes/SignatureRefining.cpp b/src/passes/SignatureRefining.cpp index d00626fca..488e2c6cc 100644 --- a/src/passes/SignatureRefining.cpp +++ b/src/passes/SignatureRefining.cpp @@ -50,7 +50,7 @@ struct SignatureRefining : public Pass { // will not appear in this map. std::unordered_map<HeapType, Signature> newSignatures; - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { if (!module->features.hasGC()) { return; } @@ -254,7 +254,9 @@ struct SignatureRefining : public Pass { CodeUpdater(SignatureRefining& parent, Module& wasm) : parent(parent), wasm(wasm) {} - CodeUpdater* create() override { return new CodeUpdater(parent, wasm); } + std::unique_ptr<Pass> create() override { + return std::make_unique<CodeUpdater>(parent, wasm); + } void doWalkFunction(Function* func) { auto iter = parent.newSignatures.find(func->type); @@ -275,7 +277,7 @@ struct SignatureRefining : public Pass { } } }; - CodeUpdater(*this, *module).run(runner, module); + CodeUpdater(*this, *module).run(getPassRunner(), module); // Rewrite the types. GlobalTypeRewriter::updateSignatures(newSignatures, *module); @@ -283,7 +285,7 @@ struct SignatureRefining : public Pass { if (refinedResults) { // After return types change we need to propagate. // TODO: we could do this only in relevant functions perhaps - ReFinalize().run(runner, module); + ReFinalize().run(getPassRunner(), module); } } }; diff --git a/src/passes/SimplifyGlobals.cpp b/src/passes/SimplifyGlobals.cpp index daaa82447..463261d35 100644 --- a/src/passes/SimplifyGlobals.cpp +++ b/src/passes/SimplifyGlobals.cpp @@ -97,7 +97,9 @@ struct GlobalUseScanner : public WalkerPass<PostWalker<GlobalUseScanner>> { GlobalUseScanner(GlobalInfoMap* infos) : infos(infos) {} - GlobalUseScanner* create() override { return new GlobalUseScanner(infos); } + std::unique_ptr<Pass> create() override { + return std::make_unique<GlobalUseScanner>(infos); + } void visitGlobalSet(GlobalSet* curr) { (*infos)[curr->name].written++; @@ -307,8 +309,8 @@ struct GlobalUseModifier : public WalkerPass<PostWalker<GlobalUseModifier>> { GlobalUseModifier(NameNameMap* copiedParentMap) : copiedParentMap(copiedParentMap) {} - GlobalUseModifier* create() override { - return new GlobalUseModifier(copiedParentMap); + std::unique_ptr<Pass> create() override { + return std::make_unique<GlobalUseModifier>(copiedParentMap); } void visitGlobalGet(GlobalGet* curr) { @@ -331,8 +333,8 @@ struct ConstantGlobalApplier ConstantGlobalApplier(NameSet* constantGlobals, bool optimize) : constantGlobals(constantGlobals), optimize(optimize) {} - ConstantGlobalApplier* create() override { - return new ConstantGlobalApplier(constantGlobals, optimize); + std::unique_ptr<Pass> create() override { + return std::make_unique<ConstantGlobalApplier>(constantGlobals, optimize); } void visitExpression(Expression* curr) { @@ -377,8 +379,7 @@ struct ConstantGlobalApplier void visitFunction(Function* curr) { if (replaced && optimize) { - PassRunner runner(getModule(), getPassRunner()->options); - runner.setIsNested(true); + PassRunner runner(getPassRunner()); runner.addDefaultFunctionOptimizationPasses(); runner.runOnFunction(curr); } @@ -399,8 +400,8 @@ struct GlobalSetRemover : public WalkerPass<PostWalker<GlobalSetRemover>> { bool isFunctionParallel() override { return true; } - GlobalSetRemover* create() override { - return new GlobalSetRemover(toRemove, optimize); + std::unique_ptr<Pass> create() override { + return std::make_unique<GlobalSetRemover>(toRemove, optimize); } void visitGlobalSet(GlobalSet* curr) { @@ -412,8 +413,7 @@ struct GlobalSetRemover : public WalkerPass<PostWalker<GlobalSetRemover>> { void visitFunction(Function* curr) { if (removed && optimize) { - PassRunner runner(getModule(), getPassRunner()->options); - runner.setIsNested(true); + PassRunner runner(getPassRunner()); runner.addDefaultFunctionOptimizationPasses(); runner.runOnFunction(curr); } @@ -428,7 +428,6 @@ private: } // anonymous namespace struct SimplifyGlobals : public Pass { - PassRunner* runner; Module* module; GlobalInfoMap map; @@ -436,8 +435,7 @@ struct SimplifyGlobals : public Pass { SimplifyGlobals(bool optimize = false) : optimize(optimize) {} - void run(PassRunner* runner_, Module* module_) override { - runner = runner_; + void run(Module* module_) override { module = module_; while (iteration()) { @@ -475,7 +473,7 @@ struct SimplifyGlobals : public Pass { map[ex->value].exported = true; } } - GlobalUseScanner(&map).run(runner, module); + GlobalUseScanner(&map).run(getPassRunner(), module); // We now know which are immutable in practice. for (auto& global : module->globals) { auto& info = map[global->name]; @@ -564,7 +562,8 @@ struct SimplifyGlobals : public Pass { // then see that since the global has no writes, it is a constant, which // will lead to removal of gets, and after removing them, the global itself // will be removed as well. - GlobalSetRemover(&globalsNotNeedingSets, optimize).run(runner, module); + GlobalSetRemover(&globalsNotNeedingSets, optimize) + .run(getPassRunner(), module); return more; } @@ -595,7 +594,7 @@ struct SimplifyGlobals : public Pass { } } // Apply to the gets. - GlobalUseModifier(&copiedParentMap).run(runner, module); + GlobalUseModifier(&copiedParentMap).run(getPassRunner(), module); } } @@ -633,7 +632,8 @@ struct SimplifyGlobals : public Pass { constantGlobals.insert(global->name); } } - ConstantGlobalApplier(&constantGlobals, optimize).run(runner, module); + ConstantGlobalApplier(&constantGlobals, optimize) + .run(getPassRunner(), module); } }; diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp index 6250b1321..dfbc7551a 100644 --- a/src/passes/SimplifyLocals.cpp +++ b/src/passes/SimplifyLocals.cpp @@ -71,8 +71,9 @@ struct SimplifyLocals SimplifyLocals<allowTee, allowStructure, allowNesting>>> { bool isFunctionParallel() override { return true; } - Pass* create() override { - return new SimplifyLocals<allowTee, allowStructure, allowNesting>(); + std::unique_ptr<Pass> create() override { + return std::make_unique< + SimplifyLocals<allowTee, allowStructure, allowNesting>>(); } // information for a local.set we can sink diff --git a/src/passes/SpillPointers.cpp b/src/passes/SpillPointers.cpp index 04193c2d2..991a7b8c1 100644 --- a/src/passes/SpillPointers.cpp +++ b/src/passes/SpillPointers.cpp @@ -37,7 +37,9 @@ struct SpillPointers : public WalkerPass<LivenessWalker<SpillPointers, Visitor<SpillPointers>>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new SpillPointers; } + std::unique_ptr<Pass> create() override { + return std::make_unique<SpillPointers>(); + } // a mapping of the pointers to all the spillable things. We need to know // how to replace them, and as we spill we may modify them. This map diff --git a/src/passes/StackCheck.cpp b/src/passes/StackCheck.cpp index 11ab1fe4e..9fba683b8 100644 --- a/src/passes/StackCheck.cpp +++ b/src/passes/StackCheck.cpp @@ -70,8 +70,8 @@ struct EnforceStackLimits : public WalkerPass<PostWalker<EnforceStackLimits>> { // Only affects linear memory operations. bool requiresNonNullableLocalFixups() override { return false; } - Pass* create() override { - return new EnforceStackLimits( + std::unique_ptr<Pass> create() override { + return std::make_unique<EnforceStackLimits>( stackPointer, stackBase, stackLimit, builder, handler); } @@ -126,7 +126,7 @@ private: }; struct StackCheck : public Pass { - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { Global* stackPointer = getStackPointerGlobal(*module); if (!stackPointer) { BYN_DEBUG(std::cerr << "no stack pointer found\n"); @@ -139,7 +139,7 @@ struct StackCheck : public Pass { Name handler; auto handlerName = - runner->options.getArgumentOrDefault("stack-check-handler", ""); + getPassOptions().getArgumentOrDefault("stack-check-handler", ""); if (handlerName != "") { handler = handlerName; importStackOverflowHandler( @@ -163,9 +163,8 @@ struct StackCheck : public Pass { Builder::Mutable)); // Instrument all the code. - PassRunner innerRunner(module); EnforceStackLimits(stackPointer, stackBase, stackLimit, builder, handler) - .run(&innerRunner, module); + .run(getPassRunner(), module); // Generate the exported function. auto limitsFunc = builder.makeFunction( diff --git a/src/passes/StackIR.cpp b/src/passes/StackIR.cpp index e896af0f5..2614a36a1 100644 --- a/src/passes/StackIR.cpp +++ b/src/passes/StackIR.cpp @@ -31,7 +31,9 @@ namespace wasm { struct GenerateStackIR : public WalkerPass<PostWalker<GenerateStackIR>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new GenerateStackIR; } + std::unique_ptr<Pass> create() override { + return std::make_unique<GenerateStackIR>(); + } bool modifiesBinaryenIR() override { return false; } @@ -336,7 +338,9 @@ private: struct OptimizeStackIR : public WalkerPass<PostWalker<OptimizeStackIR>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new OptimizeStackIR; } + std::unique_ptr<Pass> create() override { + return std::make_unique<OptimizeStackIR>(); + } bool modifiesBinaryenIR() override { return false; } diff --git a/src/passes/Strip.cpp b/src/passes/Strip.cpp index 7c9f61061..00cd87ae0 100644 --- a/src/passes/Strip.cpp +++ b/src/passes/Strip.cpp @@ -36,7 +36,7 @@ struct Strip : public Pass { Strip(Decider decider) : decider(decider) {} - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { // Remove name and debug sections. auto& sections = module->userSections; sections.erase(std::remove_if(sections.begin(), sections.end(), decider), diff --git a/src/passes/StripTargetFeatures.cpp b/src/passes/StripTargetFeatures.cpp index 878004a98..cb5b8c814 100644 --- a/src/passes/StripTargetFeatures.cpp +++ b/src/passes/StripTargetFeatures.cpp @@ -23,7 +23,7 @@ struct StripTargetFeatures : public Pass { bool isStripped = false; StripTargetFeatures(bool isStripped) : isStripped(isStripped) {} - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { module->hasFeaturesSection = !isStripped; } }; diff --git a/src/passes/TrapMode.cpp b/src/passes/TrapMode.cpp index ee245af88..8ea6fbfa1 100644 --- a/src/passes/TrapMode.cpp +++ b/src/passes/TrapMode.cpp @@ -306,7 +306,9 @@ public: TrapModePass(TrapMode mode) : mode(mode) { assert(mode != TrapMode::Allow); } - Pass* create() override { return new TrapModePass(mode); } + std::unique_ptr<Pass> create() override { + return std::make_unique<TrapModePass>(mode); + } void visitUnary(Unary* curr) { replaceCurrent(makeTrappingUnary(curr, *trappingFunctions)); diff --git a/src/passes/TypeRefining.cpp b/src/passes/TypeRefining.cpp index 3d3f981db..6ce503cc0 100644 --- a/src/passes/TypeRefining.cpp +++ b/src/passes/TypeRefining.cpp @@ -38,8 +38,9 @@ using FieldInfo = LUBFinder; struct FieldInfoScanner : public StructUtils::StructScanner<FieldInfo, FieldInfoScanner> { - Pass* create() override { - return new FieldInfoScanner(functionNewInfos, functionSetGetInfos); + std::unique_ptr<Pass> create() override { + return std::make_unique<FieldInfoScanner>(functionNewInfos, + functionSetGetInfos); } FieldInfoScanner( @@ -98,7 +99,7 @@ struct TypeRefining : public Pass { StructUtils::StructValuesMap<FieldInfo> finalInfos; - void run(PassRunner* runner, Module* module) override { + void run(Module* module) override { if (!module->features.hasGC()) { return; } @@ -111,8 +112,8 @@ struct TypeRefining : public Pass { StructUtils::FunctionStructValuesMap<FieldInfo> functionNewInfos(*module), functionSetGetInfos(*module); FieldInfoScanner scanner(functionNewInfos, functionSetGetInfos); - scanner.run(runner, module); - scanner.runOnModuleCode(runner, module); + scanner.run(getPassRunner(), module); + scanner.runOnModuleCode(getPassRunner(), module); // Combine the data from the functions. StructUtils::StructValuesMap<FieldInfo> combinedNewInfos; @@ -222,8 +223,8 @@ struct TypeRefining : public Pass { } if (canOptimize) { - updateInstructions(*module, runner); - updateTypes(*module, runner); + updateInstructions(*module); + updateTypes(*module); } } @@ -234,7 +235,7 @@ struct TypeRefining : public Pass { // at all, and we can end up with a situation where we alter the type to // something that is invalid for that read. To ensure the code still // validates, simply remove such reads. - void updateInstructions(Module& wasm, PassRunner* runner) { + void updateInstructions(Module& wasm) { struct ReadUpdater : public WalkerPass<PostWalker<ReadUpdater>> { bool isFunctionParallel() override { return true; } @@ -245,7 +246,9 @@ struct TypeRefining : public Pass { ReadUpdater(TypeRefining& parent) : parent(parent) {} - ReadUpdater* create() override { return new ReadUpdater(parent); } + std::unique_ptr<Pass> create() override { + return std::make_unique<ReadUpdater>(parent); + } void visitStructGet(StructGet* curr) { if (curr->ref->type == Type::unreachable) { @@ -274,11 +277,11 @@ struct TypeRefining : public Pass { }; ReadUpdater updater(*this); - updater.run(runner, &wasm); - updater.runOnModuleCode(runner, &wasm); + updater.run(getPassRunner(), &wasm); + updater.runOnModuleCode(getPassRunner(), &wasm); } - void updateTypes(Module& wasm, PassRunner* runner) { + void updateTypes(Module& wasm) { class TypeRewriter : public GlobalTypeRewriter { TypeRefining& parent; @@ -303,7 +306,7 @@ struct TypeRefining : public Pass { TypeRewriter(wasm, *this).update(); - ReFinalize().run(runner, &wasm); + ReFinalize().run(getPassRunner(), &wasm); } }; diff --git a/src/passes/Untee.cpp b/src/passes/Untee.cpp index 848e88a65..0123ed45f 100644 --- a/src/passes/Untee.cpp +++ b/src/passes/Untee.cpp @@ -31,7 +31,7 @@ namespace wasm { struct Untee : public WalkerPass<PostWalker<Untee>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new Untee; } + std::unique_ptr<Pass> create() override { return std::make_unique<Untee>(); } void visitLocalSet(LocalSet* curr) { if (curr->isTee()) { diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp index a29c74a89..44abed27b 100644 --- a/src/passes/Vacuum.cpp +++ b/src/passes/Vacuum.cpp @@ -33,7 +33,7 @@ namespace wasm { struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new Vacuum; } + std::unique_ptr<Pass> create() override { return std::make_unique<Vacuum>(); } TypeUpdater typeUpdater; diff --git a/src/passes/opt-utils.h b/src/passes/opt-utils.h index 28ace047a..9bc81c382 100644 --- a/src/passes/opt-utils.h +++ b/src/passes/opt-utils.h @@ -64,8 +64,8 @@ struct FunctionRefReplacer FunctionRefReplacer(MaybeReplace maybeReplace) : maybeReplace(maybeReplace) {} - FunctionRefReplacer* create() override { - return new FunctionRefReplacer(maybeReplace); + std::unique_ptr<Pass> create() override { + return std::make_unique<FunctionRefReplacer>(maybeReplace); } void visitCall(Call* curr) { maybeReplace(curr->target); } diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index c548b66c5..4036b8f47 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -896,7 +896,11 @@ void PassRunner::runPass(Pass* pass) { checker = std::unique_ptr<AfterEffectModuleChecker>( new AfterEffectModuleChecker(wasm)); } - pass->run(this, wasm); + // Passes can only be run once and we deliberately do not clear the pass + // runner after running the pass, so there must not already be a runner here. + assert(!pass->getPassRunner()); + pass->setPassRunner(this); + pass->run(wasm); handleAfterEffects(pass); if (getPassDebug()) { checker->check(); @@ -925,15 +929,17 @@ void PassRunner::runPassOnFunction(Pass* pass, Function* func) { bodyBefore << *func->body << '\n'; } - // function-parallel passes get a new instance per function - auto instance = std::unique_ptr<Pass>(pass->create()); std::unique_ptr<AfterEffectFunctionChecker> checker; if (passDebug) { - checker = std::unique_ptr<AfterEffectFunctionChecker>( - new AfterEffectFunctionChecker(func)); + checker = std::make_unique<AfterEffectFunctionChecker>(func); } - instance->runOnFunction(this, wasm, func); + + // Function-parallel passes get a new instance per function + auto instance = pass->create(); + instance->setPassRunner(this); + instance->runOnFunction(wasm, func); handleAfterEffects(pass, func); + if (passDebug) { checker->check(); } diff --git a/src/passes/test_passes.cpp b/src/passes/test_passes.cpp index 4ea5b8696..54c4818e8 100644 --- a/src/passes/test_passes.cpp +++ b/src/passes/test_passes.cpp @@ -31,12 +31,13 @@ namespace { // Pass to test EHUtil::handleBlockNestedPops function struct CatchPopFixup : public WalkerPass<PostWalker<CatchPopFixup>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new CatchPopFixup; } + std::unique_ptr<Pass> create() override { + return std::make_unique<CatchPopFixup>(); + } void doWalkFunction(Function* func) { EHUtils::handleBlockNestedPops(func, *getModule()); } - void run(PassRunner* runner, Module* module) override {} }; } // anonymous namespace diff --git a/src/tools/wasm-metadce.cpp b/src/tools/wasm-metadce.cpp index 741afb22f..5699b40f2 100644 --- a/src/tools/wasm-metadce.cpp +++ b/src/tools/wasm-metadce.cpp @@ -244,7 +244,9 @@ struct MetaDCEGraph { Scanner(MetaDCEGraph* parent) : parent(parent) {} - Scanner* create() override { return new Scanner(parent); } + std::unique_ptr<Pass> create() override { + return std::make_unique<Scanner>(parent); + } void visitCall(Call* curr) { if (!getModule()->getFunction(curr->target)->imported()) { diff --git a/src/tools/wasm-split/instrumenter.cpp b/src/tools/wasm-split/instrumenter.cpp index 7f9ff9c75..86a52688e 100644 --- a/src/tools/wasm-split/instrumenter.cpp +++ b/src/tools/wasm-split/instrumenter.cpp @@ -26,8 +26,7 @@ Instrumenter::Instrumenter(const InstrumenterConfig& config, uint64_t moduleHash) : config(config), moduleHash(moduleHash) {} -void Instrumenter::run(PassRunner* runner, Module* wasm) { - this->runner = runner; +void Instrumenter::run(Module* wasm) { this->wasm = wasm; size_t numFuncs = 0; diff --git a/src/tools/wasm-split/instrumenter.h b/src/tools/wasm-split/instrumenter.h index f4f2f2119..135d2b74f 100644 --- a/src/tools/wasm-split/instrumenter.h +++ b/src/tools/wasm-split/instrumenter.h @@ -41,7 +41,6 @@ struct InstrumenterConfig { // at the beginning of each function to set its timestamp, and a new exported // function for dumping the profile data. struct Instrumenter : public Pass { - PassRunner* runner = nullptr; Module* wasm = nullptr; const InstrumenterConfig& config; @@ -54,7 +53,7 @@ struct Instrumenter : public Pass { Instrumenter(const InstrumenterConfig& config, uint64_t moduleHash); - void run(PassRunner* runner, Module* wasm) override; + void run(Module* wasm) override; private: void addGlobals(size_t numFuncs); diff --git a/src/tools/wasm-split/wasm-split.cpp b/src/tools/wasm-split/wasm-split.cpp index ec1f5555c..49a15e934 100644 --- a/src/tools/wasm-split/wasm-split.cpp +++ b/src/tools/wasm-split/wasm-split.cpp @@ -110,7 +110,6 @@ void instrumentModule(const WasmSplitOptions& options) { } uint64_t moduleHash = hashFile(options.inputFiles[0]); - PassRunner runner(&wasm, options.passOptions); InstrumenterConfig config; if (options.importNamespace.size()) { config.importNamespace = options.importNamespace; @@ -120,7 +119,10 @@ void instrumentModule(const WasmSplitOptions& options) { } config.storageKind = options.storageKind; config.profileExport = options.profileExport; - Instrumenter(config, moduleHash).run(&runner, &wasm); + + PassRunner runner(&wasm, options.passOptions); + runner.add(std::make_unique<Instrumenter>(config, moduleHash)); + runner.run(); adjustTableSize(wasm, options.initialTableSize); diff --git a/src/tools/wasm2js.cpp b/src/tools/wasm2js.cpp index 061cd386f..7cecb5f6d 100644 --- a/src/tools/wasm2js.cpp +++ b/src/tools/wasm2js.cpp @@ -39,7 +39,9 @@ static void optimizeWasm(Module& wasm, PassOptions options) { struct OptimizeForJS : public WalkerPass<PostWalker<OptimizeForJS>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new OptimizeForJS; } + std::unique_ptr<Pass> create() override { + return std::make_unique<OptimizeForJS>(); + } void visitBinary(Binary* curr) { // x - -c (where c is a constant) is larger than x + c, in js (but not diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index a6356766e..5e3fdc6e7 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -208,7 +208,9 @@ struct ValidationInfo { struct FunctionValidator : public WalkerPass<PostWalker<FunctionValidator>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new FunctionValidator(*getModule(), &info); } + std::unique_ptr<Pass> create() override { + return std::make_unique<FunctionValidator>(*getModule(), &info); + } bool modifiesBinaryenIR() override { return false; } |