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