• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- TypeDefGen.cpp - MLIR typeDef definitions generator ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // TypeDefGen uses the description of typeDefs to generate C++ definitions.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "mlir/Support/LogicalResult.h"
14 #include "mlir/TableGen/CodeGenHelpers.h"
15 #include "mlir/TableGen/Format.h"
16 #include "mlir/TableGen/GenInfo.h"
17 #include "mlir/TableGen/TypeDef.h"
18 #include "llvm/ADT/SmallSet.h"
19 #include "llvm/Support/CommandLine.h"
20 #include "llvm/TableGen/Error.h"
21 #include "llvm/TableGen/TableGenBackend.h"
22 
23 #define DEBUG_TYPE "mlir-tblgen-typedefgen"
24 
25 using namespace mlir;
26 using namespace mlir::tblgen;
27 
28 static llvm::cl::OptionCategory typedefGenCat("Options for -gen-typedef-*");
29 static llvm::cl::opt<std::string>
30     selectedDialect("typedefs-dialect",
31                     llvm::cl::desc("Gen types for this dialect"),
32                     llvm::cl::cat(typedefGenCat), llvm::cl::CommaSeparated);
33 
34 /// Find all the TypeDefs for the specified dialect. If no dialect specified and
35 /// can only find one dialect's types, use that.
findAllTypeDefs(const llvm::RecordKeeper & recordKeeper,SmallVectorImpl<TypeDef> & typeDefs)36 static void findAllTypeDefs(const llvm::RecordKeeper &recordKeeper,
37                             SmallVectorImpl<TypeDef> &typeDefs) {
38   auto recDefs = recordKeeper.getAllDerivedDefinitions("TypeDef");
39   auto defs = llvm::map_range(
40       recDefs, [&](const llvm::Record *rec) { return TypeDef(rec); });
41   if (defs.empty())
42     return;
43 
44   StringRef dialectName;
45   if (selectedDialect.getNumOccurrences() == 0) {
46     if (defs.empty())
47       return;
48 
49     llvm::SmallSet<Dialect, 4> dialects;
50     for (const TypeDef &typeDef : defs)
51       dialects.insert(typeDef.getDialect());
52     if (dialects.size() != 1)
53       llvm::PrintFatalError("TypeDefs belonging to more than one dialect. Must "
54                             "select one via '--typedefs-dialect'");
55 
56     dialectName = (*dialects.begin()).getName();
57   } else if (selectedDialect.getNumOccurrences() == 1) {
58     dialectName = selectedDialect.getValue();
59   } else {
60     llvm::PrintFatalError("Cannot select multiple dialects for which to "
61                           "generate types via '--typedefs-dialect'.");
62   }
63 
64   for (const TypeDef &typeDef : defs)
65     if (typeDef.getDialect().getName().equals(dialectName))
66       typeDefs.push_back(typeDef);
67 }
68 
69 namespace {
70 
71 /// Pass an instance of this class to llvm::formatv() to emit a comma separated
72 /// list of parameters in the format by 'EmitFormat'.
73 class TypeParamCommaFormatter : public llvm::detail::format_adapter {
74 public:
75   /// Choose the output format
76   enum EmitFormat {
77     /// Emit "parameter1Type parameter1Name, parameter2Type parameter2Name,
78     /// [...]".
79     TypeNamePairs,
80 
81     /// Emit "parameter1(parameter1), parameter2(parameter2), [...]".
82     TypeNameInitializer,
83 
84     /// Emit "param1Name, param2Name, [...]".
85     JustParams,
86   };
87 
TypeParamCommaFormatter(EmitFormat emitFormat,ArrayRef<TypeParameter> params,bool prependComma=true)88   TypeParamCommaFormatter(EmitFormat emitFormat, ArrayRef<TypeParameter> params,
89                           bool prependComma = true)
90       : emitFormat(emitFormat), params(params), prependComma(prependComma) {}
91 
92   /// llvm::formatv will call this function when using an instance as a
93   /// replacement value.
format(raw_ostream & os,StringRef options)94   void format(raw_ostream &os, StringRef options) override {
95     if (params.size() && prependComma)
96       os << ", ";
97 
98     switch (emitFormat) {
99     case EmitFormat::TypeNamePairs:
100       interleaveComma(params, os,
101                       [&](const TypeParameter &p) { emitTypeNamePair(p, os); });
102       break;
103     case EmitFormat::TypeNameInitializer:
104       interleaveComma(params, os, [&](const TypeParameter &p) {
105         emitTypeNameInitializer(p, os);
106       });
107       break;
108     case EmitFormat::JustParams:
109       interleaveComma(params, os,
110                       [&](const TypeParameter &p) { os << p.getName(); });
111       break;
112     }
113   }
114 
115 private:
116   // Emit "paramType paramName".
emitTypeNamePair(const TypeParameter & param,raw_ostream & os)117   static void emitTypeNamePair(const TypeParameter &param, raw_ostream &os) {
118     os << param.getCppType() << " " << param.getName();
119   }
120   // Emit "paramName(paramName)"
emitTypeNameInitializer(const TypeParameter & param,raw_ostream & os)121   void emitTypeNameInitializer(const TypeParameter &param, raw_ostream &os) {
122     os << param.getName() << "(" << param.getName() << ")";
123   }
124 
125   EmitFormat emitFormat;
126   ArrayRef<TypeParameter> params;
127   bool prependComma;
128 };
129 
130 } // end anonymous namespace
131 
132 //===----------------------------------------------------------------------===//
133 // GEN: TypeDef declarations
134 //===----------------------------------------------------------------------===//
135 
136 /// Print this above all the other declarations. Contains type declarations used
137 /// later on.
138 static const char *const typeDefDeclHeader = R"(
139 namespace mlir {
140 class DialectAsmParser;
141 class DialectAsmPrinter;
142 } // namespace mlir
143 )";
144 
145 /// The code block for the start of a typeDef class declaration -- singleton
146 /// case.
147 ///
148 /// {0}: The name of the typeDef class.
149 static const char *const typeDefDeclSingletonBeginStr = R"(
150   class {0}: public ::mlir::Type::TypeBase<{0}, ::mlir::Type, ::mlir::TypeStorage> {{
151   public:
152     /// Inherit some necessary constructors from 'TypeBase'.
153     using Base::Base;
154 
155 )";
156 
157 /// The code block for the start of a typeDef class declaration -- parametric
158 /// case.
159 ///
160 /// {0}: The name of the typeDef class.
161 /// {1}: The typeDef storage class namespace.
162 /// {2}: The storage class name.
163 /// {3}: The list of parameters with types.
164 static const char *const typeDefDeclParametricBeginStr = R"(
165   namespace {1} {
166     struct {2};
167   }
168   class {0}: public ::mlir::Type::TypeBase<{0}, ::mlir::Type,
169                                         {1}::{2}> {{
170   public:
171     /// Inherit some necessary constructors from 'TypeBase'.
172     using Base::Base;
173 
174 )";
175 
176 /// The snippet for print/parse.
177 static const char *const typeDefParsePrint = R"(
178     static ::mlir::Type parse(::mlir::MLIRContext* ctxt, ::mlir::DialectAsmParser& parser);
179     void print(::mlir::DialectAsmPrinter& printer) const;
180 )";
181 
182 /// The code block for the verifyConstructionInvariants and getChecked.
183 ///
184 /// {0}: List of parameters, parameters style.
185 static const char *const typeDefDeclVerifyStr = R"(
186     static ::mlir::LogicalResult verifyConstructionInvariants(::mlir::Location loc{0});
187     static ::mlir::Type getChecked(::mlir::Location loc{0});
188 )";
189 
190 /// Generate the declaration for the given typeDef class.
emitTypeDefDecl(const TypeDef & typeDef,raw_ostream & os)191 static void emitTypeDefDecl(const TypeDef &typeDef, raw_ostream &os) {
192   SmallVector<TypeParameter, 4> params;
193   typeDef.getParameters(params);
194 
195   // Emit the beginning string template: either the singleton or parametric
196   // template.
197   if (typeDef.getNumParameters() == 0)
198     os << formatv(typeDefDeclSingletonBeginStr, typeDef.getCppClassName(),
199                   typeDef.getStorageNamespace(), typeDef.getStorageClassName());
200   else
201     os << formatv(typeDefDeclParametricBeginStr, typeDef.getCppClassName(),
202                   typeDef.getStorageNamespace(), typeDef.getStorageClassName());
203 
204   // Emit the extra declarations first in case there's a type definition in
205   // there.
206   if (Optional<StringRef> extraDecl = typeDef.getExtraDecls())
207     os << *extraDecl << "\n";
208 
209   TypeParamCommaFormatter emitTypeNamePairsAfterComma(
210       TypeParamCommaFormatter::EmitFormat::TypeNamePairs, params);
211   os << llvm::formatv("    static {0} get(::mlir::MLIRContext* ctxt{1});\n",
212                       typeDef.getCppClassName(), emitTypeNamePairsAfterComma);
213 
214   // Emit the verify invariants declaration.
215   if (typeDef.genVerifyInvariantsDecl())
216     os << llvm::formatv(typeDefDeclVerifyStr, emitTypeNamePairsAfterComma);
217 
218   // Emit the mnenomic, if specified.
219   if (auto mnenomic = typeDef.getMnemonic()) {
220     os << "    static ::llvm::StringRef getMnemonic() { return \"" << mnenomic
221        << "\"; }\n";
222 
223     // If mnemonic specified, emit print/parse declarations.
224     os << typeDefParsePrint;
225   }
226 
227   if (typeDef.genAccessors()) {
228     SmallVector<TypeParameter, 4> parameters;
229     typeDef.getParameters(parameters);
230 
231     for (TypeParameter &parameter : parameters) {
232       SmallString<16> name = parameter.getName();
233       name[0] = llvm::toUpper(name[0]);
234       os << formatv("    {0} get{1}() const;\n", parameter.getCppType(), name);
235     }
236   }
237 
238   // End the typeDef decl.
239   os << "  };\n";
240 }
241 
242 /// Main entry point for decls.
emitTypeDefDecls(const llvm::RecordKeeper & recordKeeper,raw_ostream & os)243 static bool emitTypeDefDecls(const llvm::RecordKeeper &recordKeeper,
244                              raw_ostream &os) {
245   emitSourceFileHeader("TypeDef Declarations", os);
246 
247   SmallVector<TypeDef, 16> typeDefs;
248   findAllTypeDefs(recordKeeper, typeDefs);
249 
250   IfDefScope scope("GET_TYPEDEF_CLASSES", os);
251 
252   // Output the common "header".
253   os << typeDefDeclHeader;
254 
255   if (typeDefs.size() > 0) {
256     NamespaceEmitter nsEmitter(os, typeDefs.begin()->getDialect());
257 
258     // Well known print/parse dispatch function declarations. These are called
259     // from Dialect::parseType() and Dialect::printType() methods.
260     os << "  ::mlir::Type generatedTypeParser(::mlir::MLIRContext* ctxt, "
261           "::mlir::DialectAsmParser& parser, ::llvm::StringRef mnenomic);\n";
262     os << "  ::mlir::LogicalResult generatedTypePrinter(::mlir::Type type, "
263           "::mlir::DialectAsmPrinter& printer);\n";
264     os << "\n";
265 
266     // Declare all the type classes first (in case they reference each other).
267     for (const TypeDef &typeDef : typeDefs)
268       os << "  class " << typeDef.getCppClassName() << ";\n";
269 
270     // Declare all the typedefs.
271     for (const TypeDef &typeDef : typeDefs)
272       emitTypeDefDecl(typeDef, os);
273   }
274 
275   return false;
276 }
277 
278 //===----------------------------------------------------------------------===//
279 // GEN: TypeDef list
280 //===----------------------------------------------------------------------===//
281 
emitTypeDefList(SmallVectorImpl<TypeDef> & typeDefs,raw_ostream & os)282 static void emitTypeDefList(SmallVectorImpl<TypeDef> &typeDefs,
283                             raw_ostream &os) {
284   IfDefScope scope("GET_TYPEDEF_LIST", os);
285   for (auto *i = typeDefs.begin(); i != typeDefs.end(); i++) {
286     os << i->getDialect().getCppNamespace() << "::" << i->getCppClassName();
287     if (i < typeDefs.end() - 1)
288       os << ",\n";
289     else
290       os << "\n";
291   }
292 }
293 
294 //===----------------------------------------------------------------------===//
295 // GEN: TypeDef definitions
296 //===----------------------------------------------------------------------===//
297 
298 /// Beginning of storage class.
299 /// {0}: Storage class namespace.
300 /// {1}: Storage class c++ name.
301 /// {2}: Parameters parameters.
302 /// {3}: Parameter initialzer string.
303 /// {4}: Parameter name list.
304 /// {5}: Parameter types.
305 static const char *const typeDefStorageClassBegin = R"(
306 namespace {0} {{
307   struct {1} : public ::mlir::TypeStorage {{
308     {1} ({2})
309       : {3} {{ }
310 
311     /// The hash key for this storage is a pair of the integer and type params.
312     using KeyTy = std::tuple<{5}>;
313 
314     /// Define the comparison function for the key type.
315     bool operator==(const KeyTy &key) const {{
316       return key == KeyTy({4});
317     }
318 )";
319 
320 /// The storage class' constructor template.
321 /// {0}: storage class name.
322 static const char *const typeDefStorageClassConstructorBegin = R"(
323     /// Define a construction method for creating a new instance of this storage.
324     static {0} *construct(::mlir::TypeStorageAllocator &allocator, const KeyTy &key) {{
325 )";
326 
327 /// The storage class' constructor return template.
328 /// {0}: storage class name.
329 /// {1}: list of parameters.
330 static const char *const typeDefStorageClassConstructorReturn = R"(
331       return new (allocator.allocate<{0}>())
332           {0}({1});
333     }
334 )";
335 
336 /// The code block for the getChecked definition.
337 ///
338 /// {0}: List of parameters, parameters style.
339 /// {1}: C++ type class name.
340 /// {2}: Comma separated list of parameter names.
341 static const char *const typeDefDefGetCheckeStr = R"(
342     ::mlir::Type {1}::getChecked(Location loc{0}) {{
343       return Base::getChecked(loc{2});
344     }
345 )";
346 
347 /// Use tgfmt to emit custom allocation code for each parameter, if necessary.
emitParameterAllocationCode(TypeDef & typeDef,raw_ostream & os)348 static void emitParameterAllocationCode(TypeDef &typeDef, raw_ostream &os) {
349   SmallVector<TypeParameter, 4> parameters;
350   typeDef.getParameters(parameters);
351   auto fmtCtxt = FmtContext().addSubst("_allocator", "allocator");
352   for (TypeParameter &parameter : parameters) {
353     auto allocCode = parameter.getAllocator();
354     if (allocCode) {
355       fmtCtxt.withSelf(parameter.getName());
356       fmtCtxt.addSubst("_dst", parameter.getName());
357       os << "      " << tgfmt(*allocCode, &fmtCtxt) << "\n";
358     }
359   }
360 }
361 
362 /// Emit the storage class code for type 'typeDef'.
363 /// This includes (in-order):
364 ///  1) typeDefStorageClassBegin, which includes:
365 ///      - The class constructor.
366 ///      - The KeyTy definition.
367 ///      - The equality (==) operator.
368 ///  2) The hashKey method.
369 ///  3) The construct method.
370 ///  4) The list of parameters as the storage class member variables.
emitStorageClass(TypeDef typeDef,raw_ostream & os)371 static void emitStorageClass(TypeDef typeDef, raw_ostream &os) {
372   SmallVector<TypeParameter, 4> parameters;
373   typeDef.getParameters(parameters);
374 
375   // Initialize a bunch of variables to be used later on.
376   auto parameterNames = map_range(
377       parameters, [](TypeParameter parameter) { return parameter.getName(); });
378   auto parameterTypes = map_range(parameters, [](TypeParameter parameter) {
379     return parameter.getCppType();
380   });
381   auto parameterList = join(parameterNames, ", ");
382   auto parameterTypeList = join(parameterTypes, ", ");
383 
384   // 1) Emit most of the storage class up until the hashKey body.
385   os << formatv(typeDefStorageClassBegin, typeDef.getStorageNamespace(),
386                 typeDef.getStorageClassName(),
387                 TypeParamCommaFormatter(
388                     TypeParamCommaFormatter::EmitFormat::TypeNamePairs,
389                     parameters, /*prependComma=*/false),
390                 TypeParamCommaFormatter(
391                     TypeParamCommaFormatter::EmitFormat::TypeNameInitializer,
392                     parameters, /*prependComma=*/false),
393                 parameterList, parameterTypeList);
394 
395   // 2) Emit the haskKey method.
396   os << "  static ::llvm::hash_code hashKey(const KeyTy &key) {\n";
397   // Extract each parameter from the key.
398   for (size_t i = 0, e = parameters.size(); i < e; ++i)
399     os << llvm::formatv("      const auto &{0} = std::get<{1}>(key);\n",
400                         parameters[i].getName(), i);
401   // Then combine them all. This requires all the parameters types to have a
402   // hash_value defined.
403   os << llvm::formatv(
404       "      return ::llvm::hash_combine({0});\n    }\n",
405       TypeParamCommaFormatter(TypeParamCommaFormatter::EmitFormat::JustParams,
406                               parameters, /* prependComma */ false));
407 
408   // 3) Emit the construct method.
409   if (typeDef.hasStorageCustomConstructor())
410     // If user wants to build the storage constructor themselves, declare it
411     // here and then they can write the definition elsewhere.
412     os << "    static " << typeDef.getStorageClassName()
413        << " *construct(::mlir::TypeStorageAllocator &allocator, const KeyTy "
414           "&key);\n";
415   else {
416     // If not, autogenerate one.
417 
418     // First, unbox the parameters.
419     os << formatv(typeDefStorageClassConstructorBegin,
420                   typeDef.getStorageClassName());
421     for (size_t i = 0; i < parameters.size(); ++i) {
422       os << formatv("      auto {0} = std::get<{1}>(key);\n",
423                     parameters[i].getName(), i);
424     }
425     // Second, reassign the parameter variables with allocation code, if it's
426     // specified.
427     emitParameterAllocationCode(typeDef, os);
428 
429     // Last, return an allocated copy.
430     os << formatv(typeDefStorageClassConstructorReturn,
431                   typeDef.getStorageClassName(), parameterList);
432   }
433 
434   // 4) Emit the parameters as storage class members.
435   for (auto parameter : parameters) {
436     os << "      " << parameter.getCppType() << " " << parameter.getName()
437        << ";\n";
438   }
439   os << "  };\n";
440 
441   os << "} // namespace " << typeDef.getStorageNamespace() << "\n";
442 }
443 
444 /// Emit the parser and printer for a particular type, if they're specified.
emitParserPrinter(TypeDef typeDef,raw_ostream & os)445 void emitParserPrinter(TypeDef typeDef, raw_ostream &os) {
446   // Emit the printer code, if specified.
447   if (auto printerCode = typeDef.getPrinterCode()) {
448     // Both the mnenomic and printerCode must be defined (for parity with
449     // parserCode).
450     os << "void " << typeDef.getCppClassName()
451        << "::print(::mlir::DialectAsmPrinter& printer) const {\n";
452     if (*printerCode == "") {
453       // If no code specified, emit error.
454       PrintFatalError(typeDef.getLoc(),
455                       typeDef.getName() +
456                           ": printer (if specified) must have non-empty code");
457     }
458     auto fmtCtxt = FmtContext().addSubst("_printer", "printer");
459     os << tgfmt(*printerCode, &fmtCtxt) << "\n}\n";
460   }
461 
462   // emit a parser, if specified.
463   if (auto parserCode = typeDef.getParserCode()) {
464     // The mnenomic must be defined so the dispatcher knows how to dispatch.
465     os << "::mlir::Type " << typeDef.getCppClassName()
466        << "::parse(::mlir::MLIRContext* ctxt, ::mlir::DialectAsmParser& "
467           "parser) "
468           "{\n";
469     if (*parserCode == "") {
470       // if no code specified, emit error.
471       PrintFatalError(typeDef.getLoc(),
472                       typeDef.getName() +
473                           ": parser (if specified) must have non-empty code");
474     }
475     auto fmtCtxt =
476         FmtContext().addSubst("_parser", "parser").addSubst("_ctxt", "ctxt");
477     os << tgfmt(*parserCode, &fmtCtxt) << "\n}\n";
478   }
479 }
480 
481 /// Print all the typedef-specific definition code.
emitTypeDefDef(TypeDef typeDef,raw_ostream & os)482 static void emitTypeDefDef(TypeDef typeDef, raw_ostream &os) {
483   NamespaceEmitter ns(os, typeDef.getDialect());
484   SmallVector<TypeParameter, 4> parameters;
485   typeDef.getParameters(parameters);
486 
487   // Emit the storage class, if requested and necessary.
488   if (typeDef.genStorageClass() && typeDef.getNumParameters() > 0)
489     emitStorageClass(typeDef, os);
490 
491   os << llvm::formatv(
492       "{0} {0}::get(::mlir::MLIRContext* ctxt{1}) {{\n"
493       "  return Base::get(ctxt{2});\n}\n",
494       typeDef.getCppClassName(),
495       TypeParamCommaFormatter(
496           TypeParamCommaFormatter::EmitFormat::TypeNamePairs, parameters),
497       TypeParamCommaFormatter(TypeParamCommaFormatter::EmitFormat::JustParams,
498                               parameters));
499 
500   // Emit the parameter accessors.
501   if (typeDef.genAccessors())
502     for (const TypeParameter &parameter : parameters) {
503       SmallString<16> name = parameter.getName();
504       name[0] = llvm::toUpper(name[0]);
505       os << formatv("{0} {3}::get{1}() const { return getImpl()->{2}; }\n",
506                     parameter.getCppType(), name, parameter.getName(),
507                     typeDef.getCppClassName());
508     }
509 
510   // Generate getChecked() method.
511   if (typeDef.genVerifyInvariantsDecl()) {
512     os << llvm::formatv(
513         typeDefDefGetCheckeStr,
514         TypeParamCommaFormatter(
515             TypeParamCommaFormatter::EmitFormat::TypeNamePairs, parameters),
516         typeDef.getCppClassName(),
517         TypeParamCommaFormatter(TypeParamCommaFormatter::EmitFormat::JustParams,
518                                 parameters));
519   }
520 
521   // If mnemonic is specified maybe print definitions for the parser and printer
522   // code, if they're specified.
523   if (typeDef.getMnemonic())
524     emitParserPrinter(typeDef, os);
525 }
526 
527 /// Emit the dialect printer/parser dispatcher. User's code should call these
528 /// functions from their dialect's print/parse methods.
emitParsePrintDispatch(SmallVectorImpl<TypeDef> & typeDefs,raw_ostream & os)529 static void emitParsePrintDispatch(SmallVectorImpl<TypeDef> &typeDefs,
530                                    raw_ostream &os) {
531   if (typeDefs.size() == 0)
532     return;
533   const Dialect &dialect = typeDefs.begin()->getDialect();
534   NamespaceEmitter ns(os, dialect);
535 
536   // The parser dispatch is just a list of if-elses, matching on the mnemonic
537   // and calling the class's parse function.
538   os << "::mlir::Type generatedTypeParser(::mlir::MLIRContext* ctxt, "
539         "::mlir::DialectAsmParser& parser, ::llvm::StringRef mnemonic) {\n";
540   for (const TypeDef &typeDef : typeDefs)
541     if (typeDef.getMnemonic())
542       os << formatv("  if (mnemonic == {0}::{1}::getMnemonic()) return "
543                     "{0}::{1}::parse(ctxt, parser);\n",
544                     typeDef.getDialect().getCppNamespace(),
545                     typeDef.getCppClassName());
546   os << "  return ::mlir::Type();\n";
547   os << "}\n\n";
548 
549   // The printer dispatch uses llvm::TypeSwitch to find and call the correct
550   // printer.
551   os << "::mlir::LogicalResult generatedTypePrinter(::mlir::Type type, "
552         "::mlir::DialectAsmPrinter& printer) {\n"
553      << "  ::mlir::LogicalResult found = ::mlir::success();\n"
554      << "  ::llvm::TypeSwitch<::mlir::Type>(type)\n";
555   for (auto typeDef : typeDefs)
556     if (typeDef.getMnemonic())
557       os << formatv("    .Case<{0}::{1}>([&](::mlir::Type t) {{ "
558                     "t.dyn_cast<{0}::{1}>().print(printer); })\n",
559                     typeDef.getDialect().getCppNamespace(),
560                     typeDef.getCppClassName());
561   os << "    .Default([&found](::mlir::Type) { found = ::mlir::failure(); "
562         "});\n"
563      << "  return found;\n"
564      << "}\n\n";
565 }
566 
567 /// Entry point for typedef definitions.
emitTypeDefDefs(const llvm::RecordKeeper & recordKeeper,raw_ostream & os)568 static bool emitTypeDefDefs(const llvm::RecordKeeper &recordKeeper,
569                             raw_ostream &os) {
570   emitSourceFileHeader("TypeDef Definitions", os);
571 
572   SmallVector<TypeDef, 16> typeDefs;
573   findAllTypeDefs(recordKeeper, typeDefs);
574   emitTypeDefList(typeDefs, os);
575 
576   IfDefScope scope("GET_TYPEDEF_CLASSES", os);
577   emitParsePrintDispatch(typeDefs, os);
578   for (auto typeDef : typeDefs)
579     emitTypeDefDef(typeDef, os);
580 
581   return false;
582 }
583 
584 //===----------------------------------------------------------------------===//
585 // GEN: TypeDef registration hooks
586 //===----------------------------------------------------------------------===//
587 
588 static mlir::GenRegistration
589     genTypeDefDefs("gen-typedef-defs", "Generate TypeDef definitions",
__anon69b900310802(const llvm::RecordKeeper &records, raw_ostream &os) 590                    [](const llvm::RecordKeeper &records, raw_ostream &os) {
591                      return emitTypeDefDefs(records, os);
592                    });
593 
594 static mlir::GenRegistration
595     genTypeDefDecls("gen-typedef-decls", "Generate TypeDef declarations",
__anon69b900310902(const llvm::RecordKeeper &records, raw_ostream &os) 596                     [](const llvm::RecordKeeper &records, raw_ostream &os) {
597                       return emitTypeDefDecls(records, os);
598                     });
599