diff options
author | Heejin Ahn <aheejin@gmail.com> | 2019-05-31 20:02:37 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-31 20:02:37 -0700 |
commit | fe99e3458f11d1a01fa3ad5b68883dbcba3903af (patch) | |
tree | 6f5eda61c7c7cba9c3b16be5e361cdc148d8b315 /src/passes/RemoveUnusedModuleElements.cpp | |
parent | 7306f60a4474ca1fa948bddee5c068e7c2f635f6 (diff) | |
download | binaryen-fe99e3458f11d1a01fa3ad5b68883dbcba3903af.tar.gz binaryen-fe99e3458f11d1a01fa3ad5b68883dbcba3903af.tar.bz2 binaryen-fe99e3458f11d1a01fa3ad5b68883dbcba3903af.zip |
Add event section (#2151)
This adds support for the event and the event section, as specified in
https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md#changes-to-the-binary-model.
Wasm events are features that suspend the current execution and transfer
the control flow to a corresponding handler. Currently the only
supported event kind is exceptions.
For events, this includes support for
- Binary file reading/writing
- Wast file reading/writing
- Binaryen.js API
- Fuzzer
- Validation
- Metadce
- Passes: metrics, minify-imports-and-exports,
remove-unused-module-elements
Diffstat (limited to 'src/passes/RemoveUnusedModuleElements.cpp')
-rw-r--r-- | src/passes/RemoveUnusedModuleElements.cpp | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/src/passes/RemoveUnusedModuleElements.cpp b/src/passes/RemoveUnusedModuleElements.cpp index c96ce1a8c..20c30d271 100644 --- a/src/passes/RemoveUnusedModuleElements.cpp +++ b/src/passes/RemoveUnusedModuleElements.cpp @@ -15,9 +15,9 @@ */ // -// Removes module elements that are are never used: functions and globals, -// which may be imported or not, and function types (which we merge -// and remove if unneeded) +// Removes module elements that are are never used: functions, globals, and +// events, which may be imported or not, and function types (which we merge and +// remove if unneeded) // #include <memory> @@ -30,7 +30,7 @@ namespace wasm { -enum class ModuleElementKind { Function, Global }; +enum class ModuleElementKind { Function, Global, Event }; typedef std::pair<ModuleElementKind, Name> ModuleElement; @@ -68,7 +68,7 @@ struct ReachabilityAnalyzer : public PostWalker<ReachabilityAnalyzer> { if (!func->imported()) { walk(func->body); } - } else { + } else if (curr.first == ModuleElementKind::Global) { // if not imported, it has an init expression we need to walk auto* global = module->getGlobal(curr.second); if (!global->imported()) { @@ -122,6 +122,7 @@ struct ReachabilityAnalyzer : public PostWalker<ReachabilityAnalyzer> { struct FunctionTypeAnalyzer : public PostWalker<FunctionTypeAnalyzer> { std::vector<Function*> functions; std::vector<CallIndirect*> indirectCalls; + std::vector<Event*> events; void visitFunction(Function* curr) { if (curr->type.is()) { @@ -129,6 +130,8 @@ struct FunctionTypeAnalyzer : public PostWalker<FunctionTypeAnalyzer> { } } + void visitEvent(Event* curr) { events.push_back(curr); } + void visitCallIndirect(CallIndirect* curr) { indirectCalls.push_back(curr); } }; @@ -139,11 +142,11 @@ struct RemoveUnusedModuleElements : public Pass { : rootAllFunctions(rootAllFunctions) {} void run(PassRunner* runner, Module* module) override { - optimizeGlobalsAndFunctions(module); + optimizeGlobalsAndFunctionsAndEvents(module); optimizeFunctionTypes(module); } - void optimizeGlobalsAndFunctions(Module* module) { + void optimizeGlobalsAndFunctionsAndEvents(Module* module) { std::vector<ModuleElement> roots; // Module start is a root. if (module->start.is()) { @@ -169,6 +172,8 @@ struct RemoveUnusedModuleElements : public Pass { roots.emplace_back(ModuleElementKind::Function, curr->value); } else if (curr->kind == ExternalKind::Global) { roots.emplace_back(ModuleElementKind::Global, curr->value); + } else if (curr->kind == ExternalKind::Event) { + roots.emplace_back(ModuleElementKind::Event, curr->value); } else if (curr->kind == ExternalKind::Memory) { exportsMemory = true; } else if (curr->kind == ExternalKind::Table) { @@ -215,6 +220,17 @@ struct RemoveUnusedModuleElements : public Pass { }), v.end()); } + { + auto& v = module->events; + v.erase(std::remove_if(v.begin(), + v.end(), + [&](const std::unique_ptr<Event>& curr) { + return analyzer.reachable.count( + ModuleElement(ModuleElementKind::Event, + curr->name)) == 0; + }), + v.end()); + } module->updateMaps(); // Handle the memory and table if (!exportsMemory && !analyzer.usesMemory) { @@ -272,6 +288,9 @@ struct RemoveUnusedModuleElements : public Pass { for (auto* call : analyzer.indirectCalls) { call->fullType = canonicalize(call->fullType); } + for (auto* event : analyzer.events) { + event->type = canonicalize(event->type); + } // remove no-longer used types module->functionTypes.erase( std::remove_if(module->functionTypes.begin(), |