diff options
Diffstat (limited to 'src/passes')
81 files changed, 399 insertions, 292 deletions
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 |