/* * Copyright 2015 WebAssembly Community Group participants * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef wasm_pass_h #define wasm_pass_h #include #include "wasm.h" #include "wasm-traversal.h" #include "mixed_arena.h" namespace wasm { class Pass; // // Global registry of all passes in /passes/ // struct PassRegistry { static PassRegistry* get(); typedef std::function Creator; void registerPass(const char* name, const char *description, Creator create); Pass* createPass(std::string name); std::vector getRegisteredNames(); std::string getPassDescription(std::string name); private: struct PassInfo { std::string description; Creator create; PassInfo() {} PassInfo(std::string description, Creator create) : description(description), create(create) {} }; std::map passInfos; }; // // Utility class to register a pass. See pass files for usage. // template struct RegisterPass { RegisterPass(const char* name, const char *description) { PassRegistry::get()->registerPass(name, description, []() { return new P(); }); } }; // // Runs a set of passes, in order // struct PassRunner { MixedArena* allocator; std::vector passes; Pass* currPass; bool debug = false; PassRunner(MixedArena* allocator) : allocator(allocator) {} void setDebug(bool debug_) { debug = debug_; } void add(std::string passName) { auto pass = PassRegistry::get()->createPass(passName); assert(pass); passes.push_back(pass); } template void add() { passes.push_back(new P()); } template void add(Arg& arg){ passes.push_back(new P(arg)); } // Adds the default set of optimization passes; this is // what -O does. void addDefaultOptimizationPasses(); void run(Module* module); // Get the last pass that was already executed of a certain type. template P* getLast(); ~PassRunner(); }; // // Core pass class // class Pass { public: virtual ~Pass() {}; // Override this to perform preparation work before the pass runs. virtual void prepare(PassRunner* runner, Module* module) {} virtual void run(PassRunner* runner, Module* module) = 0; // Override this to perform finalization work after the pass runs. virtual void finalize(PassRunner* runner, Module* module) {} std::string name; protected: Pass() {} Pass(Pass &) {} Pass &operator=(const Pass&) = delete; }; // // Core pass class that uses AST walking. This class can be parameterized by // different types of AST walkers. // template class WalkerPass : public Pass, public WalkerType { public: void run(PassRunner* runner, Module* module) override { prepare(runner, module); WalkerType::startWalk(module); finalize(runner, module); } }; // Standard passes. All passes in /passes/ are runnable from the shell, // but registering them here in addition allows them to communicate // e.g. through PassRunner::getLast // Handles names in a module, in particular adding names without duplicates class NameManager : public WalkerPass>> { public: Name getUnique(std::string prefix); // TODO: getUniqueInFunction // visitors void visitBlock(Block* curr); void visitLoop(Loop* curr); void visitBreak(Break* curr); void visitSwitch(Switch* curr); void visitCall(Call* curr); void visitCallImport(CallImport* curr); void visitFunctionType(FunctionType* curr); void visitFunction(Function* curr); void visitImport(Import* curr); void visitExport(Export* curr); private: std::set names; size_t counter = 0; }; // Prints out a module class Printer : public Pass { protected: std::ostream& o; public: Printer() : o(std::cout) {} Printer(std::ostream& o) : o(o) {} void run(PassRunner* runner, Module* module) override; }; } // namespace wasm #endif // wasm_pass_h