xref: /llvm-project/mlir/tools/tblgen-to-irdl/OpDefinitionsGen.cpp (revision 69d3ba3db922fca8cfc47b5f115b6bea6a737aab)
1ec7c1a47SKunwar Grover //===- OpDefinitionsGen.cpp - IRDL op definitions generator ---------------===//
2ec7c1a47SKunwar Grover //
3ec7c1a47SKunwar Grover // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ec7c1a47SKunwar Grover // See https://llvm.org/LICENSE.txt for license information.
5ec7c1a47SKunwar Grover // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ec7c1a47SKunwar Grover //
7ec7c1a47SKunwar Grover //===----------------------------------------------------------------------===//
8ec7c1a47SKunwar Grover //
9ec7c1a47SKunwar Grover // OpDefinitionsGen uses the description of operations to generate IRDL
10ec7c1a47SKunwar Grover // definitions for ops.
11ec7c1a47SKunwar Grover //
12ec7c1a47SKunwar Grover //===----------------------------------------------------------------------===//
13ec7c1a47SKunwar Grover 
14ec7c1a47SKunwar Grover #include "mlir/Dialect/IRDL/IR/IRDL.h"
15ec7c1a47SKunwar Grover #include "mlir/IR/Attributes.h"
16ec7c1a47SKunwar Grover #include "mlir/IR/Builders.h"
17ec7c1a47SKunwar Grover #include "mlir/IR/BuiltinOps.h"
18ec7c1a47SKunwar Grover #include "mlir/IR/Diagnostics.h"
19ec7c1a47SKunwar Grover #include "mlir/IR/Dialect.h"
20ec7c1a47SKunwar Grover #include "mlir/IR/MLIRContext.h"
21ec7c1a47SKunwar Grover #include "mlir/TableGen/AttrOrTypeDef.h"
22ec7c1a47SKunwar Grover #include "mlir/TableGen/GenInfo.h"
23ec7c1a47SKunwar Grover #include "mlir/TableGen/GenNameParser.h"
24ec7c1a47SKunwar Grover #include "mlir/TableGen/Interfaces.h"
25ec7c1a47SKunwar Grover #include "mlir/TableGen/Operator.h"
26*69d3ba3dSThéo Degioanni #include "llvm/ADT/StringExtras.h"
27ec7c1a47SKunwar Grover #include "llvm/Support/CommandLine.h"
28ec7c1a47SKunwar Grover #include "llvm/Support/InitLLVM.h"
29ec7c1a47SKunwar Grover #include "llvm/Support/raw_ostream.h"
30ec7c1a47SKunwar Grover #include "llvm/TableGen/Main.h"
31ec7c1a47SKunwar Grover #include "llvm/TableGen/Record.h"
32ec7c1a47SKunwar Grover #include "llvm/TableGen/TableGenBackend.h"
33ec7c1a47SKunwar Grover 
34ec7c1a47SKunwar Grover using namespace llvm;
35ec7c1a47SKunwar Grover using namespace mlir;
36ec7c1a47SKunwar Grover using tblgen::NamedTypeConstraint;
37ec7c1a47SKunwar Grover 
38ec7c1a47SKunwar Grover static llvm::cl::OptionCategory dialectGenCat("Options for -gen-irdl-dialect");
39ec7c1a47SKunwar Grover llvm::cl::opt<std::string>
40ec7c1a47SKunwar Grover     selectedDialect("dialect", llvm::cl::desc("The dialect to gen for"),
41ec7c1a47SKunwar Grover                     llvm::cl::cat(dialectGenCat), llvm::cl::Required);
42ec7c1a47SKunwar Grover 
43135bd319SAlex Rice Value createPredicate(OpBuilder &builder, tblgen::Pred pred) {
44135bd319SAlex Rice   MLIRContext *ctx = builder.getContext();
45135bd319SAlex Rice 
46135bd319SAlex Rice   if (pred.isCombined()) {
47135bd319SAlex Rice     auto combiner = pred.getDef().getValueAsDef("kind")->getName();
48135bd319SAlex Rice     if (combiner == "PredCombinerAnd" || combiner == "PredCombinerOr") {
49135bd319SAlex Rice       std::vector<Value> constraints;
50135bd319SAlex Rice       for (auto *child : pred.getDef().getValueAsListOfDefs("children")) {
51135bd319SAlex Rice         constraints.push_back(createPredicate(builder, tblgen::Pred(child)));
52135bd319SAlex Rice       }
53135bd319SAlex Rice       if (combiner == "PredCombinerAnd") {
54135bd319SAlex Rice         auto op =
55135bd319SAlex Rice             builder.create<irdl::AllOfOp>(UnknownLoc::get(ctx), constraints);
56135bd319SAlex Rice         return op.getOutput();
57135bd319SAlex Rice       }
58135bd319SAlex Rice       auto op =
59135bd319SAlex Rice           builder.create<irdl::AnyOfOp>(UnknownLoc::get(ctx), constraints);
60135bd319SAlex Rice       return op.getOutput();
61135bd319SAlex Rice     }
62135bd319SAlex Rice   }
63135bd319SAlex Rice 
64135bd319SAlex Rice   std::string condition = pred.getCondition();
65135bd319SAlex Rice   // Build a CPredOp to match the C constraint built.
66135bd319SAlex Rice   irdl::CPredOp op = builder.create<irdl::CPredOp>(
67135bd319SAlex Rice       UnknownLoc::get(ctx), StringAttr::get(ctx, condition));
68135bd319SAlex Rice   return op;
69135bd319SAlex Rice }
70135bd319SAlex Rice 
71135bd319SAlex Rice Value typeToConstraint(OpBuilder &builder, Type type) {
72135bd319SAlex Rice   MLIRContext *ctx = builder.getContext();
73135bd319SAlex Rice   auto op =
74135bd319SAlex Rice       builder.create<irdl::IsOp>(UnknownLoc::get(ctx), TypeAttr::get(type));
75135bd319SAlex Rice   return op.getOutput();
76135bd319SAlex Rice }
77135bd319SAlex Rice 
78159470deSAlex Rice Value baseToConstraint(OpBuilder &builder, StringRef baseClass) {
79159470deSAlex Rice   MLIRContext *ctx = builder.getContext();
80159470deSAlex Rice   auto op = builder.create<irdl::BaseOp>(UnknownLoc::get(ctx),
81159470deSAlex Rice                                          StringAttr::get(ctx, baseClass));
82159470deSAlex Rice   return op.getOutput();
83159470deSAlex Rice }
84135bd319SAlex Rice 
85159470deSAlex Rice std::optional<Type> recordToType(MLIRContext *ctx, const Record &predRec) {
86135bd319SAlex Rice   if (predRec.isSubClassOf("I")) {
87135bd319SAlex Rice     auto width = predRec.getValueAsInt("bitwidth");
88135bd319SAlex Rice     return IntegerType::get(ctx, width, IntegerType::Signless);
89135bd319SAlex Rice   }
90135bd319SAlex Rice 
91135bd319SAlex Rice   if (predRec.isSubClassOf("SI")) {
92135bd319SAlex Rice     auto width = predRec.getValueAsInt("bitwidth");
93135bd319SAlex Rice     return IntegerType::get(ctx, width, IntegerType::Signed);
94135bd319SAlex Rice   }
95135bd319SAlex Rice 
96135bd319SAlex Rice   if (predRec.isSubClassOf("UI")) {
97135bd319SAlex Rice     auto width = predRec.getValueAsInt("bitwidth");
98135bd319SAlex Rice     return IntegerType::get(ctx, width, IntegerType::Unsigned);
99135bd319SAlex Rice   }
100135bd319SAlex Rice 
101135bd319SAlex Rice   // Index type
102135bd319SAlex Rice   if (predRec.getName() == "Index") {
103135bd319SAlex Rice     return IndexType::get(ctx);
104135bd319SAlex Rice   }
105135bd319SAlex Rice 
106135bd319SAlex Rice   // Float types
107135bd319SAlex Rice   if (predRec.isSubClassOf("F")) {
108135bd319SAlex Rice     auto width = predRec.getValueAsInt("bitwidth");
109135bd319SAlex Rice     switch (width) {
110135bd319SAlex Rice     case 16:
111f023da12SMatthias Springer       return Float16Type::get(ctx);
112135bd319SAlex Rice     case 32:
113f023da12SMatthias Springer       return Float32Type::get(ctx);
114135bd319SAlex Rice     case 64:
115f023da12SMatthias Springer       return Float64Type::get(ctx);
116135bd319SAlex Rice     case 80:
117f023da12SMatthias Springer       return Float80Type::get(ctx);
118135bd319SAlex Rice     case 128:
119f023da12SMatthias Springer       return Float128Type::get(ctx);
120135bd319SAlex Rice     }
121135bd319SAlex Rice   }
122135bd319SAlex Rice 
123135bd319SAlex Rice   if (predRec.getName() == "NoneType") {
124135bd319SAlex Rice     return NoneType::get(ctx);
125135bd319SAlex Rice   }
126135bd319SAlex Rice 
127135bd319SAlex Rice   if (predRec.getName() == "BF16") {
128f023da12SMatthias Springer     return BFloat16Type::get(ctx);
129135bd319SAlex Rice   }
130135bd319SAlex Rice 
131135bd319SAlex Rice   if (predRec.getName() == "TF32") {
132f023da12SMatthias Springer     return FloatTF32Type::get(ctx);
133135bd319SAlex Rice   }
134135bd319SAlex Rice 
135135bd319SAlex Rice   if (predRec.getName() == "F8E4M3FN") {
136f023da12SMatthias Springer     return Float8E4M3FNType::get(ctx);
137135bd319SAlex Rice   }
138135bd319SAlex Rice 
139135bd319SAlex Rice   if (predRec.getName() == "F8E5M2") {
140f023da12SMatthias Springer     return Float8E5M2Type::get(ctx);
141135bd319SAlex Rice   }
142135bd319SAlex Rice 
143135bd319SAlex Rice   if (predRec.getName() == "F8E4M3") {
144f023da12SMatthias Springer     return Float8E4M3Type::get(ctx);
145135bd319SAlex Rice   }
146135bd319SAlex Rice 
147135bd319SAlex Rice   if (predRec.getName() == "F8E4M3FNUZ") {
148f023da12SMatthias Springer     return Float8E4M3FNUZType::get(ctx);
149135bd319SAlex Rice   }
150135bd319SAlex Rice 
151135bd319SAlex Rice   if (predRec.getName() == "F8E4M3B11FNUZ") {
152f023da12SMatthias Springer     return Float8E4M3B11FNUZType::get(ctx);
153135bd319SAlex Rice   }
154135bd319SAlex Rice 
155135bd319SAlex Rice   if (predRec.getName() == "F8E5M2FNUZ") {
156f023da12SMatthias Springer     return Float8E5M2FNUZType::get(ctx);
157135bd319SAlex Rice   }
158135bd319SAlex Rice 
159135bd319SAlex Rice   if (predRec.getName() == "F8E3M4") {
160f023da12SMatthias Springer     return Float8E3M4Type::get(ctx);
161135bd319SAlex Rice   }
162135bd319SAlex Rice 
163135bd319SAlex Rice   if (predRec.isSubClassOf("Complex")) {
164135bd319SAlex Rice     const Record *elementRec = predRec.getValueAsDef("elementType");
165135bd319SAlex Rice     auto elementType = recordToType(ctx, *elementRec);
166135bd319SAlex Rice     if (elementType.has_value()) {
167135bd319SAlex Rice       return ComplexType::get(elementType.value());
168135bd319SAlex Rice     }
169135bd319SAlex Rice   }
170135bd319SAlex Rice 
171135bd319SAlex Rice   return std::nullopt;
172135bd319SAlex Rice }
173135bd319SAlex Rice 
174159470deSAlex Rice Value createTypeConstraint(OpBuilder &builder, tblgen::Constraint constraint) {
175ec7c1a47SKunwar Grover   MLIRContext *ctx = builder.getContext();
176a64975f9SFehr Mathieu   const Record &predRec = constraint.getDef();
177a64975f9SFehr Mathieu 
178a64975f9SFehr Mathieu   if (predRec.isSubClassOf("Variadic") || predRec.isSubClassOf("Optional"))
179159470deSAlex Rice     return createTypeConstraint(builder, predRec.getValueAsDef("baseType"));
180a64975f9SFehr Mathieu 
181a64975f9SFehr Mathieu   if (predRec.getName() == "AnyType") {
182a64975f9SFehr Mathieu     auto op = builder.create<irdl::AnyOp>(UnknownLoc::get(ctx));
183a64975f9SFehr Mathieu     return op.getOutput();
184a64975f9SFehr Mathieu   }
185a64975f9SFehr Mathieu 
186a64975f9SFehr Mathieu   if (predRec.isSubClassOf("TypeDef")) {
18704575dceSAlex Rice     auto dialect = predRec.getValueAsDef("dialect")->getValueAsString("name");
18804575dceSAlex Rice     if (dialect == selectedDialect) {
18904575dceSAlex Rice       std::string combined = ("!" + predRec.getValueAsString("mnemonic")).str();
19004575dceSAlex Rice       SmallVector<FlatSymbolRefAttr> nested = {
19104575dceSAlex Rice           SymbolRefAttr::get(ctx, combined)};
19204575dceSAlex Rice       auto typeSymbol = SymbolRefAttr::get(ctx, dialect, nested);
19304575dceSAlex Rice       auto op = builder.create<irdl::BaseOp>(UnknownLoc::get(ctx), typeSymbol);
19404575dceSAlex Rice       return op.getOutput();
19504575dceSAlex Rice     }
196a64975f9SFehr Mathieu     std::string typeName = ("!" + predRec.getValueAsString("typeName")).str();
197a64975f9SFehr Mathieu     auto op = builder.create<irdl::BaseOp>(UnknownLoc::get(ctx),
198a64975f9SFehr Mathieu                                            StringAttr::get(ctx, typeName));
199a64975f9SFehr Mathieu     return op.getOutput();
200a64975f9SFehr Mathieu   }
201a64975f9SFehr Mathieu 
202a64975f9SFehr Mathieu   if (predRec.isSubClassOf("AnyTypeOf")) {
203a64975f9SFehr Mathieu     std::vector<Value> constraints;
204b60c6cbcSRahul Joshi     for (const Record *child : predRec.getValueAsListOfDefs("allowedTypes")) {
205a64975f9SFehr Mathieu       constraints.push_back(
206159470deSAlex Rice           createTypeConstraint(builder, tblgen::Constraint(child)));
207a64975f9SFehr Mathieu     }
208a64975f9SFehr Mathieu     auto op = builder.create<irdl::AnyOfOp>(UnknownLoc::get(ctx), constraints);
209a64975f9SFehr Mathieu     return op.getOutput();
210a64975f9SFehr Mathieu   }
211a64975f9SFehr Mathieu 
212a64975f9SFehr Mathieu   if (predRec.isSubClassOf("AllOfType")) {
213a64975f9SFehr Mathieu     std::vector<Value> constraints;
214b60c6cbcSRahul Joshi     for (const Record *child : predRec.getValueAsListOfDefs("allowedTypes")) {
215a64975f9SFehr Mathieu       constraints.push_back(
216159470deSAlex Rice           createTypeConstraint(builder, tblgen::Constraint(child)));
217a64975f9SFehr Mathieu     }
218a64975f9SFehr Mathieu     auto op = builder.create<irdl::AllOfOp>(UnknownLoc::get(ctx), constraints);
219a64975f9SFehr Mathieu     return op.getOutput();
220a64975f9SFehr Mathieu   }
221a64975f9SFehr Mathieu 
222135bd319SAlex Rice   // Integer types
223135bd319SAlex Rice   if (predRec.getName() == "AnyInteger") {
224135bd319SAlex Rice     auto op = builder.create<irdl::BaseOp>(
225135bd319SAlex Rice         UnknownLoc::get(ctx), StringAttr::get(ctx, "!builtin.integer"));
226135bd319SAlex Rice     return op.getOutput();
227135bd319SAlex Rice   }
228135bd319SAlex Rice 
229135bd319SAlex Rice   if (predRec.isSubClassOf("AnyI")) {
230135bd319SAlex Rice     auto width = predRec.getValueAsInt("bitwidth");
231135bd319SAlex Rice     std::vector<Value> types = {
232135bd319SAlex Rice         typeToConstraint(builder,
233135bd319SAlex Rice                          IntegerType::get(ctx, width, IntegerType::Signless)),
234135bd319SAlex Rice         typeToConstraint(builder,
235135bd319SAlex Rice                          IntegerType::get(ctx, width, IntegerType::Signed)),
236135bd319SAlex Rice         typeToConstraint(builder,
237135bd319SAlex Rice                          IntegerType::get(ctx, width, IntegerType::Unsigned))};
238135bd319SAlex Rice     auto op = builder.create<irdl::AnyOfOp>(UnknownLoc::get(ctx), types);
239135bd319SAlex Rice     return op.getOutput();
240135bd319SAlex Rice   }
241135bd319SAlex Rice 
242135bd319SAlex Rice   auto type = recordToType(ctx, predRec);
243135bd319SAlex Rice 
244135bd319SAlex Rice   if (type.has_value()) {
245135bd319SAlex Rice     return typeToConstraint(builder, type.value());
246135bd319SAlex Rice   }
247135bd319SAlex Rice 
248135bd319SAlex Rice   // Confined type
249135bd319SAlex Rice   if (predRec.isSubClassOf("ConfinedType")) {
250135bd319SAlex Rice     std::vector<Value> constraints;
251159470deSAlex Rice     constraints.push_back(createTypeConstraint(
252135bd319SAlex Rice         builder, tblgen::Constraint(predRec.getValueAsDef("baseType"))));
253a5dfcccdSRahul Joshi     for (const Record *child : predRec.getValueAsListOfDefs("predicateList")) {
254135bd319SAlex Rice       constraints.push_back(createPredicate(builder, tblgen::Pred(child)));
255135bd319SAlex Rice     }
256135bd319SAlex Rice     auto op = builder.create<irdl::AllOfOp>(UnknownLoc::get(ctx), constraints);
257135bd319SAlex Rice     return op.getOutput();
258135bd319SAlex Rice   }
259135bd319SAlex Rice 
260135bd319SAlex Rice   return createPredicate(builder, constraint.getPredicate());
261ec7c1a47SKunwar Grover }
262ec7c1a47SKunwar Grover 
263159470deSAlex Rice Value createAttrConstraint(OpBuilder &builder, tblgen::Constraint constraint) {
264159470deSAlex Rice   MLIRContext *ctx = builder.getContext();
265159470deSAlex Rice   const Record &predRec = constraint.getDef();
266159470deSAlex Rice 
267159470deSAlex Rice   if (predRec.isSubClassOf("DefaultValuedAttr") ||
268159470deSAlex Rice       predRec.isSubClassOf("DefaultValuedOptionalAttr") ||
269159470deSAlex Rice       predRec.isSubClassOf("OptionalAttr")) {
270159470deSAlex Rice     return createAttrConstraint(builder, predRec.getValueAsDef("baseAttr"));
271159470deSAlex Rice   }
272159470deSAlex Rice 
273159470deSAlex Rice   if (predRec.isSubClassOf("ConfinedAttr")) {
274159470deSAlex Rice     std::vector<Value> constraints;
275159470deSAlex Rice     constraints.push_back(createAttrConstraint(
276159470deSAlex Rice         builder, tblgen::Constraint(predRec.getValueAsDef("baseAttr"))));
277a5dfcccdSRahul Joshi     for (const Record *child :
278a5dfcccdSRahul Joshi          predRec.getValueAsListOfDefs("attrConstraints")) {
279159470deSAlex Rice       constraints.push_back(createPredicate(
280159470deSAlex Rice           builder, tblgen::Pred(child->getValueAsDef("predicate"))));
281159470deSAlex Rice     }
282159470deSAlex Rice     auto op = builder.create<irdl::AllOfOp>(UnknownLoc::get(ctx), constraints);
283159470deSAlex Rice     return op.getOutput();
284159470deSAlex Rice   }
285159470deSAlex Rice 
286159470deSAlex Rice   if (predRec.isSubClassOf("AnyAttrOf")) {
287159470deSAlex Rice     std::vector<Value> constraints;
288a5dfcccdSRahul Joshi     for (const Record *child :
289a5dfcccdSRahul Joshi          predRec.getValueAsListOfDefs("allowedAttributes")) {
290159470deSAlex Rice       constraints.push_back(
291159470deSAlex Rice           createAttrConstraint(builder, tblgen::Constraint(child)));
292159470deSAlex Rice     }
293159470deSAlex Rice     auto op = builder.create<irdl::AnyOfOp>(UnknownLoc::get(ctx), constraints);
294159470deSAlex Rice     return op.getOutput();
295159470deSAlex Rice   }
296159470deSAlex Rice 
297159470deSAlex Rice   if (predRec.getName() == "AnyAttr") {
298159470deSAlex Rice     auto op = builder.create<irdl::AnyOp>(UnknownLoc::get(ctx));
299159470deSAlex Rice     return op.getOutput();
300159470deSAlex Rice   }
301159470deSAlex Rice 
302159470deSAlex Rice   if (predRec.isSubClassOf("AnyIntegerAttrBase") ||
303159470deSAlex Rice       predRec.isSubClassOf("SignlessIntegerAttrBase") ||
304159470deSAlex Rice       predRec.isSubClassOf("SignedIntegerAttrBase") ||
305159470deSAlex Rice       predRec.isSubClassOf("UnsignedIntegerAttrBase") ||
306159470deSAlex Rice       predRec.isSubClassOf("BoolAttr")) {
307159470deSAlex Rice     return baseToConstraint(builder, "!builtin.integer");
308159470deSAlex Rice   }
309159470deSAlex Rice 
310159470deSAlex Rice   if (predRec.isSubClassOf("FloatAttrBase")) {
311159470deSAlex Rice     return baseToConstraint(builder, "!builtin.float");
312159470deSAlex Rice   }
313159470deSAlex Rice 
314159470deSAlex Rice   if (predRec.isSubClassOf("StringBasedAttr")) {
315159470deSAlex Rice     return baseToConstraint(builder, "!builtin.string");
316159470deSAlex Rice   }
317159470deSAlex Rice 
318159470deSAlex Rice   if (predRec.getName() == "UnitAttr") {
319159470deSAlex Rice     auto op =
320159470deSAlex Rice         builder.create<irdl::IsOp>(UnknownLoc::get(ctx), UnitAttr::get(ctx));
321159470deSAlex Rice     return op.getOutput();
322159470deSAlex Rice   }
323159470deSAlex Rice 
324159470deSAlex Rice   if (predRec.isSubClassOf("AttrDef")) {
325159470deSAlex Rice     auto dialect = predRec.getValueAsDef("dialect")->getValueAsString("name");
326159470deSAlex Rice     if (dialect == selectedDialect) {
327159470deSAlex Rice       std::string combined = ("#" + predRec.getValueAsString("mnemonic")).str();
328159470deSAlex Rice       SmallVector<FlatSymbolRefAttr> nested = {SymbolRefAttr::get(ctx, combined)
329159470deSAlex Rice 
330159470deSAlex Rice       };
331159470deSAlex Rice       auto typeSymbol = SymbolRefAttr::get(ctx, dialect, nested);
332159470deSAlex Rice       auto op = builder.create<irdl::BaseOp>(UnknownLoc::get(ctx), typeSymbol);
333159470deSAlex Rice       return op.getOutput();
334159470deSAlex Rice     }
335159470deSAlex Rice     std::string typeName = ("#" + predRec.getValueAsString("attrName")).str();
336159470deSAlex Rice     auto op = builder.create<irdl::BaseOp>(UnknownLoc::get(ctx),
337159470deSAlex Rice                                            StringAttr::get(ctx, typeName));
338159470deSAlex Rice     return op.getOutput();
339159470deSAlex Rice   }
340159470deSAlex Rice 
341159470deSAlex Rice   return createPredicate(builder, constraint.getPredicate());
342159470deSAlex Rice }
343159470deSAlex Rice 
3445762bd60SAlex Rice Value createRegionConstraint(OpBuilder &builder, tblgen::Region constraint) {
3455762bd60SAlex Rice   MLIRContext *ctx = builder.getContext();
3465762bd60SAlex Rice   const Record &predRec = constraint.getDef();
3475762bd60SAlex Rice 
3485762bd60SAlex Rice   if (predRec.getName() == "AnyRegion") {
3495762bd60SAlex Rice     ValueRange entryBlockArgs = {};
3505762bd60SAlex Rice     auto op =
3515762bd60SAlex Rice         builder.create<irdl::RegionOp>(UnknownLoc::get(ctx), entryBlockArgs);
3525762bd60SAlex Rice     return op.getResult();
3535762bd60SAlex Rice   }
3545762bd60SAlex Rice 
3555762bd60SAlex Rice   if (predRec.isSubClassOf("SizedRegion")) {
3565762bd60SAlex Rice     ValueRange entryBlockArgs = {};
3575762bd60SAlex Rice     auto ty = IntegerType::get(ctx, 32);
3585762bd60SAlex Rice     auto op = builder.create<irdl::RegionOp>(
3595762bd60SAlex Rice         UnknownLoc::get(ctx), entryBlockArgs,
3605762bd60SAlex Rice         IntegerAttr::get(ty, predRec.getValueAsInt("blocks")));
3615762bd60SAlex Rice     return op.getResult();
3625762bd60SAlex Rice   }
3635762bd60SAlex Rice 
3645762bd60SAlex Rice   return createPredicate(builder, constraint.getPredicate());
3655762bd60SAlex Rice }
3665762bd60SAlex Rice 
367ec7c1a47SKunwar Grover /// Returns the name of the operation without the dialect prefix.
368ec7c1a47SKunwar Grover static StringRef getOperatorName(tblgen::Operator &tblgenOp) {
369ec7c1a47SKunwar Grover   StringRef opName = tblgenOp.getDef().getValueAsString("opName");
370ec7c1a47SKunwar Grover   return opName;
371ec7c1a47SKunwar Grover }
372ec7c1a47SKunwar Grover 
37304575dceSAlex Rice /// Returns the name of the type without the dialect prefix.
37404575dceSAlex Rice static StringRef getTypeName(tblgen::TypeDef &tblgenType) {
37504575dceSAlex Rice   StringRef opName = tblgenType.getDef()->getValueAsString("mnemonic");
37604575dceSAlex Rice   return opName;
37704575dceSAlex Rice }
37804575dceSAlex Rice 
379159470deSAlex Rice /// Returns the name of the attr without the dialect prefix.
380159470deSAlex Rice static StringRef getAttrName(tblgen::AttrDef &tblgenType) {
381159470deSAlex Rice   StringRef opName = tblgenType.getDef()->getValueAsString("mnemonic");
382159470deSAlex Rice   return opName;
383159470deSAlex Rice }
384159470deSAlex Rice 
385ec7c1a47SKunwar Grover /// Extract an operation to IRDL.
386ec7c1a47SKunwar Grover irdl::OperationOp createIRDLOperation(OpBuilder &builder,
387ec7c1a47SKunwar Grover                                       tblgen::Operator &tblgenOp) {
388ec7c1a47SKunwar Grover   MLIRContext *ctx = builder.getContext();
389ec7c1a47SKunwar Grover   StringRef opName = getOperatorName(tblgenOp);
390ec7c1a47SKunwar Grover 
391ec7c1a47SKunwar Grover   irdl::OperationOp op = builder.create<irdl::OperationOp>(
392ec7c1a47SKunwar Grover       UnknownLoc::get(ctx), StringAttr::get(ctx, opName));
393ec7c1a47SKunwar Grover 
394ec7c1a47SKunwar Grover   // Add the block in the region.
395ec7c1a47SKunwar Grover   Block &opBlock = op.getBody().emplaceBlock();
396ec7c1a47SKunwar Grover   OpBuilder consBuilder = OpBuilder::atBlockBegin(&opBlock);
397ec7c1a47SKunwar Grover 
398*69d3ba3dSThéo Degioanni   SmallDenseSet<StringRef> usedNames;
399*69d3ba3dSThéo Degioanni   for (auto &namedCons : tblgenOp.getOperands())
400*69d3ba3dSThéo Degioanni     usedNames.insert(namedCons.name);
401*69d3ba3dSThéo Degioanni   for (auto &namedCons : tblgenOp.getResults())
402*69d3ba3dSThéo Degioanni     usedNames.insert(namedCons.name);
403*69d3ba3dSThéo Degioanni   for (auto &namedReg : tblgenOp.getRegions())
404*69d3ba3dSThéo Degioanni     usedNames.insert(namedReg.name);
405*69d3ba3dSThéo Degioanni 
406*69d3ba3dSThéo Degioanni   size_t generateCounter = 0;
407*69d3ba3dSThéo Degioanni   auto generateName = [&](StringRef prefix) -> StringAttr {
408*69d3ba3dSThéo Degioanni     SmallString<16> candidate;
409*69d3ba3dSThéo Degioanni     do {
410*69d3ba3dSThéo Degioanni       candidate.clear();
411*69d3ba3dSThéo Degioanni       raw_svector_ostream candidateStream(candidate);
412*69d3ba3dSThéo Degioanni       candidateStream << prefix << generateCounter;
413*69d3ba3dSThéo Degioanni       generateCounter++;
414*69d3ba3dSThéo Degioanni     } while (usedNames.contains(candidate));
415*69d3ba3dSThéo Degioanni     return StringAttr::get(ctx, candidate);
416*69d3ba3dSThéo Degioanni   };
417*69d3ba3dSThéo Degioanni   auto normalizeName = [&](StringRef name) -> StringAttr {
418*69d3ba3dSThéo Degioanni     if (name == "")
419*69d3ba3dSThéo Degioanni       return generateName("unnamed");
420*69d3ba3dSThéo Degioanni     return StringAttr::get(ctx, name);
421*69d3ba3dSThéo Degioanni   };
422*69d3ba3dSThéo Degioanni 
423ec7c1a47SKunwar Grover   auto getValues = [&](tblgen::Operator::const_value_range namedCons) {
424ec7c1a47SKunwar Grover     SmallVector<Value> operands;
425*69d3ba3dSThéo Degioanni     SmallVector<Attribute> names;
426ec7c1a47SKunwar Grover     SmallVector<irdl::VariadicityAttr> variadicity;
427*69d3ba3dSThéo Degioanni 
428ec7c1a47SKunwar Grover     for (const NamedTypeConstraint &namedCons : namedCons) {
429159470deSAlex Rice       auto operand = createTypeConstraint(consBuilder, namedCons.constraint);
430ec7c1a47SKunwar Grover       operands.push_back(operand);
431ec7c1a47SKunwar Grover 
432*69d3ba3dSThéo Degioanni       names.push_back(normalizeName(namedCons.name));
433*69d3ba3dSThéo Degioanni 
434ec7c1a47SKunwar Grover       irdl::VariadicityAttr var;
435ec7c1a47SKunwar Grover       if (namedCons.isOptional())
436ec7c1a47SKunwar Grover         var = consBuilder.getAttr<irdl::VariadicityAttr>(
437ec7c1a47SKunwar Grover             irdl::Variadicity::optional);
438ec7c1a47SKunwar Grover       else if (namedCons.isVariadic())
439ec7c1a47SKunwar Grover         var = consBuilder.getAttr<irdl::VariadicityAttr>(
440ec7c1a47SKunwar Grover             irdl::Variadicity::variadic);
441ec7c1a47SKunwar Grover       else
442ec7c1a47SKunwar Grover         var = consBuilder.getAttr<irdl::VariadicityAttr>(
443ec7c1a47SKunwar Grover             irdl::Variadicity::single);
444ec7c1a47SKunwar Grover 
445ec7c1a47SKunwar Grover       variadicity.push_back(var);
446ec7c1a47SKunwar Grover     }
447*69d3ba3dSThéo Degioanni     return std::make_tuple(operands, names, variadicity);
448ec7c1a47SKunwar Grover   };
449ec7c1a47SKunwar Grover 
450*69d3ba3dSThéo Degioanni   auto [operands, operandNames, operandVariadicity] =
451*69d3ba3dSThéo Degioanni       getValues(tblgenOp.getOperands());
452*69d3ba3dSThéo Degioanni   auto [results, resultNames, resultVariadicity] =
453*69d3ba3dSThéo Degioanni       getValues(tblgenOp.getResults());
454ec7c1a47SKunwar Grover 
455159470deSAlex Rice   SmallVector<Value> attributes;
456159470deSAlex Rice   SmallVector<Attribute> attrNames;
457159470deSAlex Rice   for (auto namedAttr : tblgenOp.getAttributes()) {
458159470deSAlex Rice     if (namedAttr.attr.isOptional())
459159470deSAlex Rice       continue;
460159470deSAlex Rice     attributes.push_back(createAttrConstraint(consBuilder, namedAttr.attr));
461159470deSAlex Rice     attrNames.push_back(StringAttr::get(ctx, namedAttr.name));
462159470deSAlex Rice   }
463159470deSAlex Rice 
4645762bd60SAlex Rice   SmallVector<Value> regions;
465*69d3ba3dSThéo Degioanni   SmallVector<Attribute> regionNames;
4665762bd60SAlex Rice   for (auto namedRegion : tblgenOp.getRegions()) {
4675762bd60SAlex Rice     regions.push_back(
4685762bd60SAlex Rice         createRegionConstraint(consBuilder, namedRegion.constraint));
469*69d3ba3dSThéo Degioanni     regionNames.push_back(normalizeName(namedRegion.name));
4705762bd60SAlex Rice   }
4715762bd60SAlex Rice 
472ec7c1a47SKunwar Grover   // Create the operands and results operations.
473135bd319SAlex Rice   if (!operands.empty())
474ec7c1a47SKunwar Grover     consBuilder.create<irdl::OperandsOp>(UnknownLoc::get(ctx), operands,
475*69d3ba3dSThéo Degioanni                                          ArrayAttr::get(ctx, operandNames),
476ec7c1a47SKunwar Grover                                          operandVariadicity);
477135bd319SAlex Rice   if (!results.empty())
478ec7c1a47SKunwar Grover     consBuilder.create<irdl::ResultsOp>(UnknownLoc::get(ctx), results,
479*69d3ba3dSThéo Degioanni                                         ArrayAttr::get(ctx, resultNames),
480ec7c1a47SKunwar Grover                                         resultVariadicity);
481159470deSAlex Rice   if (!attributes.empty())
482159470deSAlex Rice     consBuilder.create<irdl::AttributesOp>(UnknownLoc::get(ctx), attributes,
483159470deSAlex Rice                                            ArrayAttr::get(ctx, attrNames));
4845762bd60SAlex Rice   if (!regions.empty())
485*69d3ba3dSThéo Degioanni     consBuilder.create<irdl::RegionsOp>(UnknownLoc::get(ctx), regions,
486*69d3ba3dSThéo Degioanni                                         ArrayAttr::get(ctx, regionNames));
487ec7c1a47SKunwar Grover 
488ec7c1a47SKunwar Grover   return op;
489ec7c1a47SKunwar Grover }
490ec7c1a47SKunwar Grover 
49104575dceSAlex Rice irdl::TypeOp createIRDLType(OpBuilder &builder, tblgen::TypeDef &tblgenType) {
49204575dceSAlex Rice   MLIRContext *ctx = builder.getContext();
49304575dceSAlex Rice   StringRef typeName = getTypeName(tblgenType);
49404575dceSAlex Rice   std::string combined = ("!" + typeName).str();
49504575dceSAlex Rice 
49604575dceSAlex Rice   irdl::TypeOp op = builder.create<irdl::TypeOp>(
49704575dceSAlex Rice       UnknownLoc::get(ctx), StringAttr::get(ctx, combined));
49804575dceSAlex Rice 
49904575dceSAlex Rice   op.getBody().emplaceBlock();
50004575dceSAlex Rice 
50104575dceSAlex Rice   return op;
50204575dceSAlex Rice }
50304575dceSAlex Rice 
504159470deSAlex Rice irdl::AttributeOp createIRDLAttr(OpBuilder &builder,
505159470deSAlex Rice                                  tblgen::AttrDef &tblgenAttr) {
506159470deSAlex Rice   MLIRContext *ctx = builder.getContext();
507159470deSAlex Rice   StringRef attrName = getAttrName(tblgenAttr);
508159470deSAlex Rice   std::string combined = ("#" + attrName).str();
509159470deSAlex Rice 
510159470deSAlex Rice   irdl::AttributeOp op = builder.create<irdl::AttributeOp>(
511159470deSAlex Rice       UnknownLoc::get(ctx), StringAttr::get(ctx, combined));
512159470deSAlex Rice 
513159470deSAlex Rice   op.getBody().emplaceBlock();
514159470deSAlex Rice 
515159470deSAlex Rice   return op;
516159470deSAlex Rice }
517159470deSAlex Rice 
518ec7c1a47SKunwar Grover static irdl::DialectOp createIRDLDialect(OpBuilder &builder) {
519ec7c1a47SKunwar Grover   MLIRContext *ctx = builder.getContext();
520ec7c1a47SKunwar Grover   return builder.create<irdl::DialectOp>(UnknownLoc::get(ctx),
521ec7c1a47SKunwar Grover                                          StringAttr::get(ctx, selectedDialect));
522ec7c1a47SKunwar Grover }
523ec7c1a47SKunwar Grover 
524e8137503SRahul Joshi static bool emitDialectIRDLDefs(const RecordKeeper &records, raw_ostream &os) {
525ec7c1a47SKunwar Grover   // Initialize.
526ec7c1a47SKunwar Grover   MLIRContext ctx;
527ec7c1a47SKunwar Grover   ctx.getOrLoadDialect<irdl::IRDLDialect>();
528ec7c1a47SKunwar Grover   OpBuilder builder(&ctx);
529ec7c1a47SKunwar Grover 
530ec7c1a47SKunwar Grover   // Create a module op and set it as the insertion point.
531ec7c1a47SKunwar Grover   OwningOpRef<ModuleOp> module =
532ec7c1a47SKunwar Grover       builder.create<ModuleOp>(UnknownLoc::get(&ctx));
533ec7c1a47SKunwar Grover   builder = builder.atBlockBegin(module->getBody());
534ec7c1a47SKunwar Grover   // Create the dialect and insert it.
535ec7c1a47SKunwar Grover   irdl::DialectOp dialect = createIRDLDialect(builder);
536ec7c1a47SKunwar Grover   // Set insertion point to start of DialectOp.
537ec7c1a47SKunwar Grover   builder = builder.atBlockBegin(&dialect.getBody().emplaceBlock());
538ec7c1a47SKunwar Grover 
53904575dceSAlex Rice   for (const Record *type :
540e8137503SRahul Joshi        records.getAllDerivedDefinitionsIfDefined("TypeDef")) {
54104575dceSAlex Rice     tblgen::TypeDef tblgenType(type);
54204575dceSAlex Rice     if (tblgenType.getDialect().getName() != selectedDialect)
54304575dceSAlex Rice       continue;
54404575dceSAlex Rice     createIRDLType(builder, tblgenType);
54504575dceSAlex Rice   }
54604575dceSAlex Rice 
547159470deSAlex Rice   for (const Record *attr :
548e8137503SRahul Joshi        records.getAllDerivedDefinitionsIfDefined("AttrDef")) {
549159470deSAlex Rice     tblgen::AttrDef tblgenAttr(attr);
550159470deSAlex Rice     if (tblgenAttr.getDialect().getName() != selectedDialect)
551159470deSAlex Rice       continue;
552159470deSAlex Rice     createIRDLAttr(builder, tblgenAttr);
553159470deSAlex Rice   }
554159470deSAlex Rice 
555e8137503SRahul Joshi   for (const Record *def : records.getAllDerivedDefinitionsIfDefined("Op")) {
556ec7c1a47SKunwar Grover     tblgen::Operator tblgenOp(def);
557ec7c1a47SKunwar Grover     if (tblgenOp.getDialectName() != selectedDialect)
558ec7c1a47SKunwar Grover       continue;
559ec7c1a47SKunwar Grover 
560ec7c1a47SKunwar Grover     createIRDLOperation(builder, tblgenOp);
561ec7c1a47SKunwar Grover   }
562ec7c1a47SKunwar Grover 
563ec7c1a47SKunwar Grover   // Print the module.
564ec7c1a47SKunwar Grover   module->print(os);
565ec7c1a47SKunwar Grover 
566ec7c1a47SKunwar Grover   return false;
567ec7c1a47SKunwar Grover }
568ec7c1a47SKunwar Grover 
569ec7c1a47SKunwar Grover static mlir::GenRegistration
570ec7c1a47SKunwar Grover     genOpDefs("gen-dialect-irdl-defs", "Generate IRDL dialect definitions",
571b60c6cbcSRahul Joshi               [](const RecordKeeper &records, raw_ostream &os) {
572ec7c1a47SKunwar Grover                 return emitDialectIRDLDefs(records, os);
573ec7c1a47SKunwar Grover               });
574