18155e41aSRiver Riddle //===- Pass.cpp - MLIR pass registration generator ------------------------===// 28155e41aSRiver Riddle // 38155e41aSRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 48155e41aSRiver Riddle // See https://llvm.org/LICENSE.txt for license information. 58155e41aSRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68155e41aSRiver Riddle // 78155e41aSRiver Riddle //===----------------------------------------------------------------------===// 88155e41aSRiver Riddle // 98155e41aSRiver Riddle // PassGen uses the description of passes to generate base classes for passes 108155e41aSRiver Riddle // and command line registration. 118155e41aSRiver Riddle // 128155e41aSRiver Riddle //===----------------------------------------------------------------------===// 138155e41aSRiver Riddle 148155e41aSRiver Riddle #include "mlir/TableGen/GenInfo.h" 158155e41aSRiver Riddle #include "mlir/TableGen/Pass.h" 168155e41aSRiver Riddle #include "llvm/ADT/StringExtras.h" 172a6c8b2eSRiver Riddle #include "llvm/Support/CommandLine.h" 188155e41aSRiver Riddle #include "llvm/Support/FormatVariadic.h" 198155e41aSRiver Riddle #include "llvm/TableGen/Error.h" 208155e41aSRiver Riddle #include "llvm/TableGen/Record.h" 218155e41aSRiver Riddle 228155e41aSRiver Riddle using namespace mlir; 238155e41aSRiver Riddle using namespace mlir::tblgen; 24bccd37f6SRahul Joshi using llvm::formatv; 25bccd37f6SRahul Joshi using llvm::RecordKeeper; 268155e41aSRiver Riddle 272a6c8b2eSRiver Riddle static llvm::cl::OptionCategory passGenCat("Options for -gen-pass-decls"); 282a6c8b2eSRiver Riddle static llvm::cl::opt<std::string> 292a6c8b2eSRiver Riddle groupName("name", llvm::cl::desc("The name of this group of passes"), 302a6c8b2eSRiver Riddle llvm::cl::cat(passGenCat)); 312a6c8b2eSRiver Riddle 3232c5578bSMichele Scuttari /// Extract the list of passes from the TableGen records. 33*e8137503SRahul Joshi static std::vector<Pass> getPasses(const RecordKeeper &records) { 3432c5578bSMichele Scuttari std::vector<Pass> passes; 3532c5578bSMichele Scuttari 36*e8137503SRahul Joshi for (const auto *def : records.getAllDerivedDefinitions("PassBase")) 3732c5578bSMichele Scuttari passes.emplace_back(def); 3832c5578bSMichele Scuttari 3932c5578bSMichele Scuttari return passes; 4032c5578bSMichele Scuttari } 4132c5578bSMichele Scuttari 4232c5578bSMichele Scuttari const char *const passHeader = R"( 4332c5578bSMichele Scuttari //===----------------------------------------------------------------------===// 4432c5578bSMichele Scuttari // {0} 4532c5578bSMichele Scuttari //===----------------------------------------------------------------------===// 4632c5578bSMichele Scuttari )"; 4732c5578bSMichele Scuttari 4832c5578bSMichele Scuttari //===----------------------------------------------------------------------===// 4932c5578bSMichele Scuttari // GEN: Pass registration generation 5032c5578bSMichele Scuttari //===----------------------------------------------------------------------===// 5132c5578bSMichele Scuttari 5232c5578bSMichele Scuttari /// The code snippet used to generate a pass registration. 5332c5578bSMichele Scuttari /// 5432c5578bSMichele Scuttari /// {0}: The def name of the pass record. 5532c5578bSMichele Scuttari /// {1}: The pass constructor call. 5632c5578bSMichele Scuttari const char *const passRegistrationCode = R"( 5732c5578bSMichele Scuttari //===----------------------------------------------------------------------===// 5832c5578bSMichele Scuttari // {0} Registration 5932c5578bSMichele Scuttari //===----------------------------------------------------------------------===// 6032c5578bSMichele Scuttari 6132c5578bSMichele Scuttari inline void register{0}() {{ 6232c5578bSMichele Scuttari ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {{ 6332c5578bSMichele Scuttari return {1}; 6432c5578bSMichele Scuttari }); 6532c5578bSMichele Scuttari } 6632c5578bSMichele Scuttari 6732c5578bSMichele Scuttari // Old registration code, kept for temporary backwards compatibility. 6832c5578bSMichele Scuttari inline void register{0}Pass() {{ 6932c5578bSMichele Scuttari ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {{ 7032c5578bSMichele Scuttari return {1}; 7132c5578bSMichele Scuttari }); 7232c5578bSMichele Scuttari } 7332c5578bSMichele Scuttari )"; 7432c5578bSMichele Scuttari 7532c5578bSMichele Scuttari /// The code snippet used to generate a function to register all passes in a 7632c5578bSMichele Scuttari /// group. 7732c5578bSMichele Scuttari /// 7832c5578bSMichele Scuttari /// {0}: The name of the pass group. 7932c5578bSMichele Scuttari const char *const passGroupRegistrationCode = R"( 8032c5578bSMichele Scuttari //===----------------------------------------------------------------------===// 8132c5578bSMichele Scuttari // {0} Registration 8232c5578bSMichele Scuttari //===----------------------------------------------------------------------===// 8332c5578bSMichele Scuttari 8432c5578bSMichele Scuttari inline void register{0}Passes() {{ 8532c5578bSMichele Scuttari )"; 8632c5578bSMichele Scuttari 8732c5578bSMichele Scuttari /// Emits the definition of the struct to be used to control the pass options. 8832c5578bSMichele Scuttari static void emitPassOptionsStruct(const Pass &pass, raw_ostream &os) { 8932c5578bSMichele Scuttari StringRef passName = pass.getDef()->getName(); 9032c5578bSMichele Scuttari ArrayRef<PassOption> options = pass.getOptions(); 9132c5578bSMichele Scuttari 9232c5578bSMichele Scuttari // Emit the struct only if the pass has at least one option. 9332c5578bSMichele Scuttari if (options.empty()) 9432c5578bSMichele Scuttari return; 9532c5578bSMichele Scuttari 96bccd37f6SRahul Joshi os << formatv("struct {0}Options {{\n", passName); 9732c5578bSMichele Scuttari 9832c5578bSMichele Scuttari for (const PassOption &opt : options) { 9932c5578bSMichele Scuttari std::string type = opt.getType().str(); 10032c5578bSMichele Scuttari 10132c5578bSMichele Scuttari if (opt.isListOption()) 102fef3566aSNikhil Kalra type = "::llvm::SmallVector<" + type + ">"; 10332c5578bSMichele Scuttari 104bccd37f6SRahul Joshi os.indent(2) << formatv("{0} {1}", type, opt.getCppVariableName()); 10532c5578bSMichele Scuttari 1063cfe412eSFangrui Song if (std::optional<StringRef> defaultVal = opt.getDefaultValue()) 10732c5578bSMichele Scuttari os << " = " << defaultVal; 10832c5578bSMichele Scuttari 10932c5578bSMichele Scuttari os << ";\n"; 11032c5578bSMichele Scuttari } 11132c5578bSMichele Scuttari 11232c5578bSMichele Scuttari os << "};\n"; 11332c5578bSMichele Scuttari } 11432c5578bSMichele Scuttari 115868a8fd8Srkayaith static std::string getPassDeclVarName(const Pass &pass) { 116868a8fd8Srkayaith return "GEN_PASS_DECL_" + pass.getDef()->getName().upper(); 117868a8fd8Srkayaith } 118868a8fd8Srkayaith 11932c5578bSMichele Scuttari /// Emit the code to be included in the public header of the pass. 12032c5578bSMichele Scuttari static void emitPassDecls(const Pass &pass, raw_ostream &os) { 12132c5578bSMichele Scuttari StringRef passName = pass.getDef()->getName(); 122868a8fd8Srkayaith std::string enableVarName = getPassDeclVarName(pass); 12332c5578bSMichele Scuttari 12432c5578bSMichele Scuttari os << "#ifdef " << enableVarName << "\n"; 12532c5578bSMichele Scuttari emitPassOptionsStruct(pass, os); 12632c5578bSMichele Scuttari 12732c5578bSMichele Scuttari if (StringRef constructor = pass.getConstructor(); constructor.empty()) { 12832c5578bSMichele Scuttari // Default constructor declaration. 12932c5578bSMichele Scuttari os << "std::unique_ptr<::mlir::Pass> create" << passName << "();\n"; 13032c5578bSMichele Scuttari 13132c5578bSMichele Scuttari // Declaration of the constructor with options. 13232c5578bSMichele Scuttari if (ArrayRef<PassOption> options = pass.getOptions(); !options.empty()) 133bccd37f6SRahul Joshi os << formatv("std::unique_ptr<::mlir::Pass> create{0}(" 134fef3566aSNikhil Kalra "{0}Options options);\n", 13532c5578bSMichele Scuttari passName); 13632c5578bSMichele Scuttari } 13732c5578bSMichele Scuttari 13832c5578bSMichele Scuttari os << "#undef " << enableVarName << "\n"; 13932c5578bSMichele Scuttari os << "#endif // " << enableVarName << "\n"; 14032c5578bSMichele Scuttari } 14132c5578bSMichele Scuttari 14232c5578bSMichele Scuttari /// Emit the code for registering each of the given passes with the global 14332c5578bSMichele Scuttari /// PassRegistry. 14432c5578bSMichele Scuttari static void emitRegistrations(llvm::ArrayRef<Pass> passes, raw_ostream &os) { 14532c5578bSMichele Scuttari os << "#ifdef GEN_PASS_REGISTRATION\n"; 14632c5578bSMichele Scuttari 14732c5578bSMichele Scuttari for (const Pass &pass : passes) { 14832c5578bSMichele Scuttari std::string constructorCall; 14932c5578bSMichele Scuttari if (StringRef constructor = pass.getConstructor(); !constructor.empty()) 15032c5578bSMichele Scuttari constructorCall = constructor.str(); 15132c5578bSMichele Scuttari else 152bccd37f6SRahul Joshi constructorCall = formatv("create{0}()", pass.getDef()->getName()).str(); 15332c5578bSMichele Scuttari 154bccd37f6SRahul Joshi os << formatv(passRegistrationCode, pass.getDef()->getName(), 15532c5578bSMichele Scuttari constructorCall); 15632c5578bSMichele Scuttari } 15732c5578bSMichele Scuttari 158bccd37f6SRahul Joshi os << formatv(passGroupRegistrationCode, groupName); 15932c5578bSMichele Scuttari 16032c5578bSMichele Scuttari for (const Pass &pass : passes) 16132c5578bSMichele Scuttari os << " register" << pass.getDef()->getName() << "();\n"; 16232c5578bSMichele Scuttari 16332c5578bSMichele Scuttari os << "}\n"; 16432c5578bSMichele Scuttari os << "#undef GEN_PASS_REGISTRATION\n"; 16532c5578bSMichele Scuttari os << "#endif // GEN_PASS_REGISTRATION\n"; 16632c5578bSMichele Scuttari } 16732c5578bSMichele Scuttari 1688155e41aSRiver Riddle //===----------------------------------------------------------------------===// 1699a277af2SRiver Riddle // GEN: Pass base class generation 1709a277af2SRiver Riddle //===----------------------------------------------------------------------===// 1719a277af2SRiver Riddle 1729a277af2SRiver Riddle /// The code snippet used to generate the start of a pass base class. 1739a277af2SRiver Riddle /// 1749a277af2SRiver Riddle /// {0}: The def name of the pass record. 1751834ad4aSRiver Riddle /// {1}: The base class for the pass. 1761834ad4aSRiver Riddle /// {2): The command line argument for the pass. 1773dff20cfSmlevesquedion /// {3}: The summary for the pass. 1783dff20cfSmlevesquedion /// {4}: The dependent dialects registration. 1790815281fSMichele Scuttari const char *const baseClassBegin = R"( 18032c5578bSMichele Scuttari template <typename DerivedT> 18132c5578bSMichele Scuttari class {0}Base : public {1} { 18232c5578bSMichele Scuttari public: 18332c5578bSMichele Scuttari using Base = {0}Base; 1849a277af2SRiver Riddle 18532c5578bSMichele Scuttari {0}Base() : {1}(::mlir::TypeID::get<DerivedT>()) {{} 18632c5578bSMichele Scuttari {0}Base(const {0}Base &other) : {1}(other) {{} 18790e9e962SAndrei Golubev {0}Base& operator=(const {0}Base &) = delete; 18890e9e962SAndrei Golubev {0}Base({0}Base &&) = delete; 18990e9e962SAndrei Golubev {0}Base& operator=({0}Base &&) = delete; 19090e9e962SAndrei Golubev ~{0}Base() = default; 19132c5578bSMichele Scuttari 19232c5578bSMichele Scuttari /// Returns the command-line argument attached to this pass. 19332c5578bSMichele Scuttari static constexpr ::llvm::StringLiteral getArgumentName() { 19432c5578bSMichele Scuttari return ::llvm::StringLiteral("{2}"); 19532c5578bSMichele Scuttari } 19632c5578bSMichele Scuttari ::llvm::StringRef getArgument() const override { return "{2}"; } 19732c5578bSMichele Scuttari 19832c5578bSMichele Scuttari ::llvm::StringRef getDescription() const override { return "{3}"; } 19932c5578bSMichele Scuttari 20032c5578bSMichele Scuttari /// Returns the derived pass name. 20132c5578bSMichele Scuttari static constexpr ::llvm::StringLiteral getPassName() { 20232c5578bSMichele Scuttari return ::llvm::StringLiteral("{0}"); 20332c5578bSMichele Scuttari } 20432c5578bSMichele Scuttari ::llvm::StringRef getName() const override { return "{0}"; } 20532c5578bSMichele Scuttari 20632c5578bSMichele Scuttari /// Support isa/dyn_cast functionality for the derived pass class. 20732c5578bSMichele Scuttari static bool classof(const ::mlir::Pass *pass) {{ 20832c5578bSMichele Scuttari return pass->getTypeID() == ::mlir::TypeID::get<DerivedT>(); 20932c5578bSMichele Scuttari } 21032c5578bSMichele Scuttari 21132c5578bSMichele Scuttari /// A clone method to create a copy of this pass. 21232c5578bSMichele Scuttari std::unique_ptr<::mlir::Pass> clonePass() const override {{ 21332c5578bSMichele Scuttari return std::make_unique<DerivedT>(*static_cast<const DerivedT *>(this)); 21432c5578bSMichele Scuttari } 21532c5578bSMichele Scuttari 21632c5578bSMichele Scuttari /// Return the dialect that must be loaded in the context before this pass. 21732c5578bSMichele Scuttari void getDependentDialects(::mlir::DialectRegistry ®istry) const override { 21832c5578bSMichele Scuttari {4} 21932c5578bSMichele Scuttari } 22032c5578bSMichele Scuttari 22132c5578bSMichele Scuttari /// Explicitly declare the TypeID for this class. We declare an explicit private 22232c5578bSMichele Scuttari /// instantiation because Pass classes should only be visible by the current 22332c5578bSMichele Scuttari /// library. 22432c5578bSMichele Scuttari MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID({0}Base<DerivedT>) 22532c5578bSMichele Scuttari 22632c5578bSMichele Scuttari )"; 22732c5578bSMichele Scuttari 22832c5578bSMichele Scuttari /// Registration for a single dependent dialect, to be inserted for each 22932c5578bSMichele Scuttari /// dependent dialect in the `getDependentDialects` above. 2303dff20cfSmlevesquedion const char *const dialectRegistrationTemplate = "registry.insert<{0}>();"; 23132c5578bSMichele Scuttari 2320815281fSMichele Scuttari const char *const friendDefaultConstructorDeclTemplate = R"( 2330815281fSMichele Scuttari namespace impl {{ 2340815281fSMichele Scuttari std::unique_ptr<::mlir::Pass> create{0}(); 2350815281fSMichele Scuttari } // namespace impl 2360815281fSMichele Scuttari )"; 2370815281fSMichele Scuttari 2380815281fSMichele Scuttari const char *const friendDefaultConstructorWithOptionsDeclTemplate = R"( 2390815281fSMichele Scuttari namespace impl {{ 240fef3566aSNikhil Kalra std::unique_ptr<::mlir::Pass> create{0}({0}Options options); 2410815281fSMichele Scuttari } // namespace impl 2420815281fSMichele Scuttari )"; 2430815281fSMichele Scuttari 2440815281fSMichele Scuttari const char *const friendDefaultConstructorDefTemplate = R"( 24532c5578bSMichele Scuttari friend std::unique_ptr<::mlir::Pass> create{0}() {{ 24632c5578bSMichele Scuttari return std::make_unique<DerivedT>(); 24732c5578bSMichele Scuttari } 24832c5578bSMichele Scuttari )"; 24932c5578bSMichele Scuttari 2500815281fSMichele Scuttari const char *const friendDefaultConstructorWithOptionsDefTemplate = R"( 251fef3566aSNikhil Kalra friend std::unique_ptr<::mlir::Pass> create{0}({0}Options options) {{ 252fef3566aSNikhil Kalra return std::make_unique<DerivedT>(std::move(options)); 25332c5578bSMichele Scuttari } 25432c5578bSMichele Scuttari )"; 25532c5578bSMichele Scuttari 2560815281fSMichele Scuttari const char *const defaultConstructorDefTemplate = R"( 2570815281fSMichele Scuttari std::unique_ptr<::mlir::Pass> create{0}() {{ 2580815281fSMichele Scuttari return impl::create{0}(); 2590815281fSMichele Scuttari } 2600815281fSMichele Scuttari )"; 2610815281fSMichele Scuttari 2620815281fSMichele Scuttari const char *const defaultConstructorWithOptionsDefTemplate = R"( 263fef3566aSNikhil Kalra std::unique_ptr<::mlir::Pass> create{0}({0}Options options) {{ 264fef3566aSNikhil Kalra return impl::create{0}(std::move(options)); 2650815281fSMichele Scuttari } 2660815281fSMichele Scuttari )"; 2670815281fSMichele Scuttari 26832c5578bSMichele Scuttari /// Emit the declarations for each of the pass options. 26932c5578bSMichele Scuttari static void emitPassOptionDecls(const Pass &pass, raw_ostream &os) { 27032c5578bSMichele Scuttari for (const PassOption &opt : pass.getOptions()) { 27132c5578bSMichele Scuttari os.indent(2) << "::mlir::Pass::" 27232c5578bSMichele Scuttari << (opt.isListOption() ? "ListOption" : "Option"); 27332c5578bSMichele Scuttari 274bccd37f6SRahul Joshi os << formatv(R"(<{0}> {1}{{*this, "{2}", ::llvm::cl::desc("{3}"))", 275bccd37f6SRahul Joshi opt.getType(), opt.getCppVariableName(), opt.getArgument(), 276bccd37f6SRahul Joshi opt.getDescription()); 2773cfe412eSFangrui Song if (std::optional<StringRef> defaultVal = opt.getDefaultValue()) 27832c5578bSMichele Scuttari os << ", ::llvm::cl::init(" << defaultVal << ")"; 2793cfe412eSFangrui Song if (std::optional<StringRef> additionalFlags = opt.getAdditionalFlags()) 28032c5578bSMichele Scuttari os << ", " << *additionalFlags; 28132c5578bSMichele Scuttari os << "};\n"; 28232c5578bSMichele Scuttari } 28332c5578bSMichele Scuttari } 28432c5578bSMichele Scuttari 28532c5578bSMichele Scuttari /// Emit the declarations for each of the pass statistics. 28632c5578bSMichele Scuttari static void emitPassStatisticDecls(const Pass &pass, raw_ostream &os) { 28732c5578bSMichele Scuttari for (const PassStatistic &stat : pass.getStatistics()) { 288bccd37f6SRahul Joshi os << formatv(" ::mlir::Pass::Statistic {0}{{this, \"{1}\", \"{2}\"};\n", 289bccd37f6SRahul Joshi stat.getCppVariableName(), stat.getName(), 290bccd37f6SRahul Joshi stat.getDescription()); 29132c5578bSMichele Scuttari } 29232c5578bSMichele Scuttari } 29332c5578bSMichele Scuttari 29432c5578bSMichele Scuttari /// Emit the code to be used in the implementation of the pass. 29532c5578bSMichele Scuttari static void emitPassDefs(const Pass &pass, raw_ostream &os) { 29632c5578bSMichele Scuttari StringRef passName = pass.getDef()->getName(); 29732c5578bSMichele Scuttari std::string enableVarName = "GEN_PASS_DEF_" + passName.upper(); 2980815281fSMichele Scuttari bool emitDefaultConstructors = pass.getConstructor().empty(); 2990815281fSMichele Scuttari bool emitDefaultConstructorWithOptions = !pass.getOptions().empty(); 30032c5578bSMichele Scuttari 30132c5578bSMichele Scuttari os << "#ifdef " << enableVarName << "\n"; 30232c5578bSMichele Scuttari 3030815281fSMichele Scuttari if (emitDefaultConstructors) { 304bccd37f6SRahul Joshi os << formatv(friendDefaultConstructorDeclTemplate, passName); 3050815281fSMichele Scuttari 3060815281fSMichele Scuttari if (emitDefaultConstructorWithOptions) 307bccd37f6SRahul Joshi os << formatv(friendDefaultConstructorWithOptionsDeclTemplate, passName); 3080815281fSMichele Scuttari } 3090815281fSMichele Scuttari 31032c5578bSMichele Scuttari std::string dependentDialectRegistrations; 31132c5578bSMichele Scuttari { 31232c5578bSMichele Scuttari llvm::raw_string_ostream dialectsOs(dependentDialectRegistrations); 3133dff20cfSmlevesquedion llvm::interleave( 3143dff20cfSmlevesquedion pass.getDependentDialects(), dialectsOs, 3153dff20cfSmlevesquedion [&](StringRef dependentDialect) { 316bccd37f6SRahul Joshi dialectsOs << formatv(dialectRegistrationTemplate, dependentDialect); 3173dff20cfSmlevesquedion }, 3183dff20cfSmlevesquedion "\n "); 31932c5578bSMichele Scuttari } 32032c5578bSMichele Scuttari 3210815281fSMichele Scuttari os << "namespace impl {\n"; 322bccd37f6SRahul Joshi os << formatv(baseClassBegin, passName, pass.getBaseClass(), 32332c5578bSMichele Scuttari pass.getArgument(), pass.getSummary(), 32432c5578bSMichele Scuttari dependentDialectRegistrations); 32532c5578bSMichele Scuttari 32632c5578bSMichele Scuttari if (ArrayRef<PassOption> options = pass.getOptions(); !options.empty()) { 327bccd37f6SRahul Joshi os.indent(2) << formatv("{0}Base({0}Options options) : {0}Base() {{\n", 328bccd37f6SRahul Joshi passName); 32932c5578bSMichele Scuttari 33032c5578bSMichele Scuttari for (const PassOption &opt : pass.getOptions()) 331bccd37f6SRahul Joshi os.indent(4) << formatv("{0} = std::move(options.{0});\n", 33232c5578bSMichele Scuttari opt.getCppVariableName()); 33332c5578bSMichele Scuttari 33432c5578bSMichele Scuttari os.indent(2) << "}\n"; 33532c5578bSMichele Scuttari } 33632c5578bSMichele Scuttari 33732c5578bSMichele Scuttari // Protected content 33832c5578bSMichele Scuttari os << "protected:\n"; 33932c5578bSMichele Scuttari emitPassOptionDecls(pass, os); 34032c5578bSMichele Scuttari emitPassStatisticDecls(pass, os); 34132c5578bSMichele Scuttari 34232c5578bSMichele Scuttari // Private content 34332c5578bSMichele Scuttari os << "private:\n"; 34432c5578bSMichele Scuttari 3450815281fSMichele Scuttari if (emitDefaultConstructors) { 346bccd37f6SRahul Joshi os << formatv(friendDefaultConstructorDefTemplate, passName); 34732c5578bSMichele Scuttari 34832c5578bSMichele Scuttari if (!pass.getOptions().empty()) 349bccd37f6SRahul Joshi os << formatv(friendDefaultConstructorWithOptionsDefTemplate, passName); 35032c5578bSMichele Scuttari } 35132c5578bSMichele Scuttari 35232c5578bSMichele Scuttari os << "};\n"; 3530815281fSMichele Scuttari os << "} // namespace impl\n"; 3540815281fSMichele Scuttari 3550815281fSMichele Scuttari if (emitDefaultConstructors) { 356bccd37f6SRahul Joshi os << formatv(defaultConstructorDefTemplate, passName); 3570815281fSMichele Scuttari 3580815281fSMichele Scuttari if (emitDefaultConstructorWithOptions) 359bccd37f6SRahul Joshi os << formatv(defaultConstructorWithOptionsDefTemplate, passName); 3600815281fSMichele Scuttari } 36132c5578bSMichele Scuttari 36232c5578bSMichele Scuttari os << "#undef " << enableVarName << "\n"; 36332c5578bSMichele Scuttari os << "#endif // " << enableVarName << "\n"; 36432c5578bSMichele Scuttari } 36532c5578bSMichele Scuttari 36613ed6958SMichele Scuttari static void emitPass(const Pass &pass, raw_ostream &os) { 36713ed6958SMichele Scuttari StringRef passName = pass.getDef()->getName(); 368bccd37f6SRahul Joshi os << formatv(passHeader, passName); 36913ed6958SMichele Scuttari 37013ed6958SMichele Scuttari emitPassDecls(pass, os); 37113ed6958SMichele Scuttari emitPassDefs(pass, os); 37213ed6958SMichele Scuttari } 37313ed6958SMichele Scuttari 374a22af3e1SMichele Scuttari // TODO: Drop old pass declarations. 375a22af3e1SMichele Scuttari // The old pass base class is being kept until all the passes have switched to 376a22af3e1SMichele Scuttari // the new decls/defs design. 377a22af3e1SMichele Scuttari const char *const oldPassDeclBegin = R"( 378a22af3e1SMichele Scuttari template <typename DerivedT> 379a22af3e1SMichele Scuttari class {0}Base : public {1} { 380a22af3e1SMichele Scuttari public: 381a22af3e1SMichele Scuttari using Base = {0}Base; 382a22af3e1SMichele Scuttari 383a22af3e1SMichele Scuttari {0}Base() : {1}(::mlir::TypeID::get<DerivedT>()) {{} 384a22af3e1SMichele Scuttari {0}Base(const {0}Base &other) : {1}(other) {{} 38590e9e962SAndrei Golubev {0}Base& operator=(const {0}Base &) = delete; 38690e9e962SAndrei Golubev {0}Base({0}Base &&) = delete; 38790e9e962SAndrei Golubev {0}Base& operator=({0}Base &&) = delete; 38890e9e962SAndrei Golubev ~{0}Base() = default; 389a22af3e1SMichele Scuttari 390a22af3e1SMichele Scuttari /// Returns the command-line argument attached to this pass. 391a22af3e1SMichele Scuttari static constexpr ::llvm::StringLiteral getArgumentName() { 392a22af3e1SMichele Scuttari return ::llvm::StringLiteral("{2}"); 393a22af3e1SMichele Scuttari } 394a22af3e1SMichele Scuttari ::llvm::StringRef getArgument() const override { return "{2}"; } 395a22af3e1SMichele Scuttari 396a22af3e1SMichele Scuttari ::llvm::StringRef getDescription() const override { return "{3}"; } 397a22af3e1SMichele Scuttari 398a22af3e1SMichele Scuttari /// Returns the derived pass name. 399a22af3e1SMichele Scuttari static constexpr ::llvm::StringLiteral getPassName() { 400a22af3e1SMichele Scuttari return ::llvm::StringLiteral("{0}"); 401a22af3e1SMichele Scuttari } 402a22af3e1SMichele Scuttari ::llvm::StringRef getName() const override { return "{0}"; } 403a22af3e1SMichele Scuttari 404a22af3e1SMichele Scuttari /// Support isa/dyn_cast functionality for the derived pass class. 405a22af3e1SMichele Scuttari static bool classof(const ::mlir::Pass *pass) {{ 406a22af3e1SMichele Scuttari return pass->getTypeID() == ::mlir::TypeID::get<DerivedT>(); 407a22af3e1SMichele Scuttari } 408a22af3e1SMichele Scuttari 409a22af3e1SMichele Scuttari /// A clone method to create a copy of this pass. 410a22af3e1SMichele Scuttari std::unique_ptr<::mlir::Pass> clonePass() const override {{ 411a22af3e1SMichele Scuttari return std::make_unique<DerivedT>(*static_cast<const DerivedT *>(this)); 412a22af3e1SMichele Scuttari } 413a22af3e1SMichele Scuttari 4143dff20cfSmlevesquedion /// Register the dialects that must be loaded in the context before this pass. 415a22af3e1SMichele Scuttari void getDependentDialects(::mlir::DialectRegistry ®istry) const override { 416a22af3e1SMichele Scuttari {4} 417a22af3e1SMichele Scuttari } 418a22af3e1SMichele Scuttari 419a22af3e1SMichele Scuttari /// Explicitly declare the TypeID for this class. We declare an explicit private 420a22af3e1SMichele Scuttari /// instantiation because Pass classes should only be visible by the current 421a22af3e1SMichele Scuttari /// library. 422a22af3e1SMichele Scuttari MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID({0}Base<DerivedT>) 423a22af3e1SMichele Scuttari 424a22af3e1SMichele Scuttari protected: 425a22af3e1SMichele Scuttari )"; 426a22af3e1SMichele Scuttari 427a22af3e1SMichele Scuttari // TODO: Drop old pass declarations. 428a22af3e1SMichele Scuttari /// Emit a backward-compatible declaration of the pass base class. 429a22af3e1SMichele Scuttari static void emitOldPassDecl(const Pass &pass, raw_ostream &os) { 430a22af3e1SMichele Scuttari StringRef defName = pass.getDef()->getName(); 431a22af3e1SMichele Scuttari std::string dependentDialectRegistrations; 432a22af3e1SMichele Scuttari { 433a22af3e1SMichele Scuttari llvm::raw_string_ostream dialectsOs(dependentDialectRegistrations); 4343dff20cfSmlevesquedion llvm::interleave( 4353dff20cfSmlevesquedion pass.getDependentDialects(), dialectsOs, 4363dff20cfSmlevesquedion [&](StringRef dependentDialect) { 437bccd37f6SRahul Joshi dialectsOs << formatv(dialectRegistrationTemplate, dependentDialect); 4383dff20cfSmlevesquedion }, 4393dff20cfSmlevesquedion "\n "); 440a22af3e1SMichele Scuttari } 441bccd37f6SRahul Joshi os << formatv(oldPassDeclBegin, defName, pass.getBaseClass(), 442a22af3e1SMichele Scuttari pass.getArgument(), pass.getSummary(), 443a22af3e1SMichele Scuttari dependentDialectRegistrations); 444a22af3e1SMichele Scuttari emitPassOptionDecls(pass, os); 445a22af3e1SMichele Scuttari emitPassStatisticDecls(pass, os); 446a22af3e1SMichele Scuttari os << "};\n"; 447a22af3e1SMichele Scuttari } 448a22af3e1SMichele Scuttari 449*e8137503SRahul Joshi static void emitPasses(const RecordKeeper &records, raw_ostream &os) { 450*e8137503SRahul Joshi std::vector<Pass> passes = getPasses(records); 45113ed6958SMichele Scuttari os << "/* Autogenerated by mlir-tblgen; don't manually edit */\n"; 45213ed6958SMichele Scuttari 453868a8fd8Srkayaith os << "\n"; 454868a8fd8Srkayaith os << "#ifdef GEN_PASS_DECL\n"; 455868a8fd8Srkayaith os << "// Generate declarations for all passes.\n"; 456868a8fd8Srkayaith for (const Pass &pass : passes) 457868a8fd8Srkayaith os << "#define " << getPassDeclVarName(pass) << "\n"; 458868a8fd8Srkayaith os << "#undef GEN_PASS_DECL\n"; 459868a8fd8Srkayaith os << "#endif // GEN_PASS_DECL\n"; 460868a8fd8Srkayaith 46113ed6958SMichele Scuttari for (const Pass &pass : passes) 46213ed6958SMichele Scuttari emitPass(pass, os); 46313ed6958SMichele Scuttari 46413ed6958SMichele Scuttari emitRegistrations(passes, os); 465a22af3e1SMichele Scuttari 466a22af3e1SMichele Scuttari // TODO: Drop old pass declarations. 467a22af3e1SMichele Scuttari // Emit the old code until all the passes have switched to the new design. 468a22af3e1SMichele Scuttari os << "// Deprecated. Please use the new per-pass macros.\n"; 469a22af3e1SMichele Scuttari os << "#ifdef GEN_PASS_CLASSES\n"; 470a22af3e1SMichele Scuttari for (const Pass &pass : passes) 471a22af3e1SMichele Scuttari emitOldPassDecl(pass, os); 472a22af3e1SMichele Scuttari os << "#undef GEN_PASS_CLASSES\n"; 473a22af3e1SMichele Scuttari os << "#endif // GEN_PASS_CLASSES\n"; 47413ed6958SMichele Scuttari } 47513ed6958SMichele Scuttari 4768155e41aSRiver Riddle static mlir::GenRegistration 47732c5578bSMichele Scuttari genPassDecls("gen-pass-decls", "Generate pass declarations", 478bccd37f6SRahul Joshi [](const RecordKeeper &records, raw_ostream &os) { 47913ed6958SMichele Scuttari emitPasses(records, os); 48032c5578bSMichele Scuttari return false; 48132c5578bSMichele Scuttari }); 482