xref: /llvm-project/mlir/tools/mlir-tblgen/PassGen.cpp (revision e813750354bbc08551cf23ff559a54b4a9ea1f29)
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 &registry) 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 &registry) 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