diff options
author | Alon Zakai <alonzakai@gmail.com> | 2018-09-19 15:50:30 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-19 15:50:30 -0700 |
commit | fe88b47749115009da0447e340cbdc86edf30984 (patch) | |
tree | 7dfd9aba7086c8aa6dff4877ac1ee3b9d78bc5ce /src/passes/RemoveUnusedModuleElements.cpp | |
parent | a53356ab155a7d8c2f334dc9a3c1432bacbc78fe (diff) | |
download | binaryen-fe88b47749115009da0447e340cbdc86edf30984.tar.gz binaryen-fe88b47749115009da0447e340cbdc86edf30984.tar.bz2 binaryen-fe88b47749115009da0447e340cbdc86edf30984.zip |
Unify imported and non-imported things (#1678)
Fixes #1649
This moves us to a single object for functions, which can be imported or nor, and likewise for globals (as a result, GetGlobals do not need to check if the global is imported or not, etc.). All imported things now inherit from Importable, which has the module and base of the import, and if they are set then it is an import.
For convenient iteration, there are a few helpers like
ModuleUtils::iterDefinedGlobals(wasm, [&](Global* global) {
.. use global ..
});
as often iteration only cares about imported or defined (non-imported) things.
Diffstat (limited to 'src/passes/RemoveUnusedModuleElements.cpp')
-rw-r--r-- | src/passes/RemoveUnusedModuleElements.cpp | 73 |
1 files changed, 23 insertions, 50 deletions
diff --git a/src/passes/RemoveUnusedModuleElements.cpp b/src/passes/RemoveUnusedModuleElements.cpp index 6cd050da9..069137ff6 100644 --- a/src/passes/RemoveUnusedModuleElements.cpp +++ b/src/passes/RemoveUnusedModuleElements.cpp @@ -25,6 +25,7 @@ #include "wasm.h" #include "pass.h" +#include "ir/module-utils.h" #include "ir/utils.h" #include "asm_v_wasm.h" @@ -63,15 +64,15 @@ struct ReachabilityAnalyzer : public PostWalker<ReachabilityAnalyzer> { reachable.insert(curr); if (curr.first == ModuleElementKind::Function) { // if not an import, walk it - auto* func = module->getFunctionOrNull(curr.second); - if (func) { + auto* func = module->getFunction(curr.second); + if (!func->imported()) { walk(func->body); } } else { // if not imported, it has an init expression we need to walk - auto* glob = module->getGlobalOrNull(curr.second); - if (glob) { - walk(glob->init); + auto* global = module->getGlobal(curr.second); + if (!global->imported()) { + walk(global->init); } } } @@ -83,11 +84,6 @@ struct ReachabilityAnalyzer : public PostWalker<ReachabilityAnalyzer> { queue.emplace_back(ModuleElementKind::Function, curr->target); } } - void visitCallImport(CallImport* curr) { - if (reachable.count(ModuleElement(ModuleElementKind::Function, curr->target)) == 0) { - queue.emplace_back(ModuleElementKind::Function, curr->target); - } - } void visitCallIndirect(CallIndirect* curr) { usesTable = true; } @@ -131,19 +127,17 @@ struct ReachabilityAnalyzer : public PostWalker<ReachabilityAnalyzer> { // Finds function type usage struct FunctionTypeAnalyzer : public PostWalker<FunctionTypeAnalyzer> { - std::vector<Import*> functionImports; + std::vector<Function*> functionImports; std::vector<Function*> functions; std::vector<CallIndirect*> indirectCalls; - void visitImport(Import* curr) { - if (curr->kind == ExternalKind::Function && curr->functionType.is()) { - functionImports.push_back(curr); - } - } - void visitFunction(Function* curr) { if (curr->type.is()) { - functions.push_back(curr); + if (curr->imported()) { + functionImports.push_back(curr); + } else { + functions.push_back(curr); + } } } @@ -176,9 +170,9 @@ struct RemoveUnusedModuleElements : public Pass { } // If told to, root all the functions if (rootAllFunctions) { - for (auto& func : module->functions) { + ModuleUtils::iterDefinedFunctions(*module, [&](Function* func) { roots.emplace_back(ModuleElementKind::Function, func->name); - } + }); } // Exports are roots. bool exportsMemory = false; @@ -194,15 +188,14 @@ struct RemoveUnusedModuleElements : public Pass { exportsTable = true; } } - // Check for special imports are roots. + // Check for special imports, which are roots. bool importsMemory = false; bool importsTable = false; - for (auto& curr : module->imports) { - if (curr->kind == ExternalKind::Memory) { - importsMemory = true; - } else if (curr->kind == ExternalKind::Table) { - importsTable = true; - } + if (module->memory.imported()) { + importsMemory = true; + } + if (module->table.imported()) { + importsTable = true; } // For now, all functions that can be called indirectly are marked as roots. for (auto& segment : module->table.segments) { @@ -225,17 +218,6 @@ struct RemoveUnusedModuleElements : public Pass { return analyzer.reachable.count(ModuleElement(ModuleElementKind::Global, curr->name)) == 0; }), v.end()); } - { - auto& v = module->imports; - v.erase(std::remove_if(v.begin(), v.end(), [&](const std::unique_ptr<Import>& curr) { - if (curr->kind == ExternalKind::Function) { - return analyzer.reachable.count(ModuleElement(ModuleElementKind::Function, curr->name)) == 0; - } else if (curr->kind == ExternalKind::Global) { - return analyzer.reachable.count(ModuleElement(ModuleElementKind::Global, curr->name)) == 0; - } - return false; - }), v.end()); - } module->updateMaps(); // Handle the memory and table if (!exportsMemory && !analyzer.usesMemory) { @@ -245,10 +227,9 @@ struct RemoveUnusedModuleElements : public Pass { } if (module->memory.segments.empty()) { module->memory.exists = false; - module->memory.imported = false; + module->memory.module = module->memory.base = Name(); module->memory.initial = 0; module->memory.max = 0; - removeImport(ExternalKind::Memory, module); } } if (!exportsTable && !analyzer.usesTable) { @@ -258,21 +239,13 @@ struct RemoveUnusedModuleElements : public Pass { } if (module->table.segments.empty()) { module->table.exists = false; - module->table.imported = false; + module->table.module = module->table.base = Name(); module->table.initial = 0; module->table.max = 0; - removeImport(ExternalKind::Table, module); } } } - void removeImport(ExternalKind kind, Module* module) { - auto& v = module->imports; - v.erase(std::remove_if(v.begin(), v.end(), [&](const std::unique_ptr<Import>& curr) { - return curr->kind == kind; - }), v.end()); - } - void optimizeFunctionTypes(Module* module) { FunctionTypeAnalyzer analyzer; analyzer.walkModule(module); @@ -294,7 +267,7 @@ struct RemoveUnusedModuleElements : public Pass { }; // canonicalize all uses of function types for (auto* import : analyzer.functionImports) { - import->functionType = canonicalize(import->functionType); + import->type = canonicalize(import->type); } for (auto* func : analyzer.functions) { func->type = canonicalize(func->type); |