1//===-- AttrTypeBase.td - Base Attr/Type definition file ---*- tablegen -*-===// 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// This file contains the base set of constructs for defining Attribute and 10// Type classes. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef ATTRTYPEBASE_TD 15#define ATTRTYPEBASE_TD 16 17include "mlir/IR/CommonAttrConstraints.td" 18include "mlir/IR/CommonTypeConstraints.td" 19include "mlir/IR/Constraints.td" 20include "mlir/IR/DialectBase.td" 21include "mlir/IR/Traits.td" 22 23//-------------------------------------------------------------------------===// 24// AttrTrait definitions 25//===----------------------------------------------------------------------===// 26 27// These classes are used to define attribute specific traits. 28 29// Specify attribute specific declarations and definitions in `extraAttrDeclaration` 30// and `extraAttrDefinition` template arguments. 31class NativeAttrTrait<string name, 32 code extraAttrDeclaration = [{}], 33 code extraAttrDefinition = [{}]> 34 : NativeTrait<name, "Attribute", extraAttrDeclaration, extraAttrDefinition>; 35 36class ParamNativeAttrTrait<string prop, string params> 37 : ParamNativeTrait<prop, params, "Attribute">; 38class GenInternalAttrTrait<string prop> : GenInternalTrait<prop, "Attribute">; 39class PredAttrTrait<string descr, Pred pred> : PredTrait<descr, pred>; 40 41//===----------------------------------------------------------------------===// 42// TypeTrait definitions 43//===----------------------------------------------------------------------===// 44 45// These classes are used to define type specific traits. 46 47// Specify type specific declarations and definitions in `extraTypeDeclaration` 48// and `extraTypeDefinition` template arguments. 49class NativeTypeTrait<string name, 50 code extraTypeDeclaration = [{}], 51 code extraTypeDefinition = [{}]> 52 : NativeTrait<name, "Type", extraTypeDeclaration, extraTypeDefinition>; 53 54class ParamNativeTypeTrait<string prop, string params> 55 : ParamNativeTrait<prop, params, "Type">; 56class GenInternalTypeTrait<string prop> : GenInternalTrait<prop, "Type">; 57class PredTypeTrait<string descr, Pred pred> : PredTrait<descr, pred>; 58 59// Trait required to be added to any type which is mutable. 60def MutableType : NativeTypeTrait<"IsMutable">; 61 62//===----------------------------------------------------------------------===// 63// Builders 64//===----------------------------------------------------------------------===// 65 66// Class for defining a custom getter. 67// 68// TableGen generates several generic getter methods for each attribute and type 69// by default, corresponding to the specified dag parameters. If the default 70// generated ones cannot cover some use case, custom getters can be defined 71// using instances of this class. 72// 73// The signature of the `get` is always either: 74// 75// ```c++ 76// static <ClassName> get(MLIRContext *context, <other-parameters>...) { 77// <body>... 78// } 79// ``` 80// 81// or: 82// 83// ```c++ 84// static <ClassName> get(MLIRContext *context, <parameters>...); 85// ``` 86// 87// To define a custom getter, the parameter list and body should be passed 88// in as separate template arguments to this class. The parameter list is a 89// TableGen DAG with `ins` operation with named arguments, which has either: 90// - string initializers ("Type":$name) to represent a typed parameter, or 91// - CArg-typed initializers (CArg<"Type", "default">:$name) to represent a 92// typed parameter that may have a default value. 93// The type string is used verbatim to produce code and, therefore, must be a 94// valid C++ type. It is used inside the C++ namespace of the parent Type's 95// dialect; explicit namespace qualification like `::mlir` may be necessary if 96// Types are not placed inside the `mlir` namespace. The default value string is 97// used verbatim to produce code and must be a valid C++ initializer the given 98// type. For example, the following signature specification 99// 100// ``` 101// AttrOrTypeBuilder<(ins "int":$integerArg, CArg<"float", "3.0f">:$floatArg)> 102// ``` 103// 104// has an integer parameter and a float parameter with a default value. 105// 106// If an empty string is passed in for `body`, then *only* the builder 107// declaration will be generated; this provides a way to define complicated 108// builders entirely in C++. If a `body` string is provided, the `Base::get` 109// method should be invoked using `$_get`, e.g.: 110// 111// ``` 112// AttrOrTypeBuilder<(ins "int":$integerArg, CArg<"float", "3.0f">:$floatArg), [{ 113// return $_get($_ctxt, integerArg, floatArg); 114// }]> 115// ``` 116// 117// This is necessary because the `body` is also used to generate `getChecked` 118// methods, which have a different underlying `Base::get*` call. 119// 120class AttrOrTypeBuilder<dag parameters, code bodyCode = "", 121 string returnTypeStr = ""> { 122 dag dagParams = parameters; 123 code body = bodyCode; 124 125 // Change the return type of the builder. By default, it is the type of the 126 // attribute or type. 127 string returnType = returnTypeStr; 128 129 // The context parameter can be inferred from one of the other parameters and 130 // is not implicitly added to the parameter list. 131 bit hasInferredContextParam = 0; 132} 133class AttrBuilder<dag parameters, code bodyCode = "", string returnType = ""> 134 : AttrOrTypeBuilder<parameters, bodyCode, returnType>; 135class TypeBuilder<dag parameters, code bodyCode = "", string returnType = ""> 136 : AttrOrTypeBuilder<parameters, bodyCode, returnType>; 137 138// A class of AttrOrTypeBuilder that is able to infer the MLIRContext parameter 139// from one of the other builder parameters. Instances of this builder do not 140// have `MLIRContext *` implicitly added to the parameter list. 141class AttrOrTypeBuilderWithInferredContext<dag parameters, code bodyCode = "", 142 string returnType = ""> 143 : TypeBuilder<parameters, bodyCode, returnType> { 144 let hasInferredContextParam = 1; 145} 146class AttrBuilderWithInferredContext<dag parameters, code bodyCode = "", 147 string returnType = ""> 148 : AttrOrTypeBuilderWithInferredContext<parameters, bodyCode, returnType>; 149class TypeBuilderWithInferredContext<dag parameters, code bodyCode = "", 150 string returnType = ""> 151 : AttrOrTypeBuilderWithInferredContext<parameters, bodyCode, returnType>; 152 153//===----------------------------------------------------------------------===// 154// Definitions 155//===----------------------------------------------------------------------===// 156 157// Define a new attribute or type, named `name`, that inherits from the given 158// C++ base class. 159class AttrOrTypeDef<string valueType, string name, list<Trait> defTraits, 160 string baseCppClass> { 161 // The name of the C++ base class to use for this def. 162 string cppBaseClassName = baseCppClass; 163 164 // Additional, longer human-readable description of what the def does. 165 string description = ""; 166 167 // Name of storage class to generate or use. 168 string storageClass = name # valueType # "Storage"; 169 170 // Namespace (withing dialect c++ namespace) in which the storage class 171 // resides. 172 string storageNamespace = "detail"; 173 174 // Specify if the storage class is to be generated. 175 bit genStorageClass = 1; 176 177 // Specify that the generated storage class has a constructor which is written 178 // in C++. 179 bit hasStorageCustomConstructor = 0; 180 181 // The list of parameters for this type. Parameters will become both 182 // parameters to the get() method and storage class member variables. 183 // 184 // The format of this dag is: 185 // (ins 186 // "<c++ type>":$param1Name, 187 // "<c++ type>":$param2Name, 188 // AttrOrTypeParameter<"c++ type", "param description">:$param3Name) 189 // AttrOrTypeParameters (or more likely one of their subclasses) are required 190 // to add more information about the parameter, specifically: 191 // - Documentation 192 // - Code to allocate the parameter (if allocation is needed in the storage 193 // class constructor) 194 // 195 // For example: 196 // (ins "int":$width, 197 // ArrayRefParameter<"bool", "list of bools">:$yesNoArray) 198 // 199 // (ArrayRefParameter is a subclass of AttrOrTypeParameter which has 200 // allocation code for re-allocating ArrayRefs. It is defined below.) 201 dag parameters = (ins); 202 203 // Custom builder methods. 204 // In addition to the custom builders provided here, and unless 205 // skipDefaultBuilders is set, a default builder is generated with the 206 // following signature: 207 // 208 // ```c++ 209 // static <ClassName> get(MLIRContext *, <parameters>); 210 // ``` 211 // 212 // Note that builders should only be provided when a def has parameters. 213 list<AttrOrTypeBuilder> builders = ?; 214 215 // The list of traits attached to this def. 216 list<Trait> traits = defTraits; 217 218 // Use the lowercased name as the keyword for parsing/printing. Specify only 219 // if you want tblgen to generate declarations and/or definitions of 220 // the printer/parser. If specified and the Attribute or Type contains 221 // parameters, `assemblyFormat` or `hasCustomAssemblyFormat` must also be 222 // specified. 223 string mnemonic = ?; 224 225 // Custom assembly format. Requires 'mnemonic' to be specified. Cannot be 226 // specified at the same time as 'hasCustomAssemblyFormat'. The generated 227 // printer requires 'genAccessors' to be true. 228 string assemblyFormat = ?; 229 /// This field indicates that the attribute or type has a custom assembly format 230 /// implemented in C++. When set to `1` a `parse` and `print` method are generated 231 /// on the generated class. The attribute or type should implement these methods to 232 /// support the custom format. 233 bit hasCustomAssemblyFormat = 0; 234 235 // If set, generate accessors for each parameter. 236 bit genAccessors = 1; 237 238 // Avoid generating default get/getChecked functions. Custom get methods must 239 // be provided. 240 bit skipDefaultBuilders = 0; 241 242 // Generate the verify and getChecked methods. 243 bit genVerifyDecl = 0; 244 245 // Extra code to include in the class declaration. 246 code extraClassDeclaration = [{}]; 247 248 // Additional code that will be added to the generated source file. The 249 // generated code is placed inside the class's C++ namespace. `$cppClass` is 250 // replaced by the class name. 251 code extraClassDefinition = [{}]; 252} 253 254// Define a new attribute, named `name`, belonging to `dialect` that inherits 255// from the given C++ base class. 256class AttrDef<Dialect dialect, string name, list<Trait> traits = [], 257 string baseCppClass = "::mlir::Attribute"> 258 : DialectAttr<dialect, CPred<"">, /*descr*/"">, 259 AttrOrTypeDef<"Attr", name, traits, baseCppClass> { 260 // The name of the C++ Attribute class. 261 string cppClassName = name # "Attr"; 262 let storageType = dialect.cppNamespace # "::" # cppClassName; 263 264 // The underlying C++ value type 265 let returnType = dialect.cppNamespace # "::" # cppClassName; 266 267 // Make it possible to use such attributes as parameters for other attributes. 268 string cppType = dialect.cppNamespace # "::" # cppClassName; 269 270 // The unique attribute name. 271 string attrName = dialect.name # "." # mnemonic; 272 273 // The call expression to convert from the storage type to the return 274 // type. For example, an enum can be stored as an int but returned as an 275 // enum class. 276 // 277 // Format: $_self will be expanded to the attribute. 278 // 279 // For example, `$_self.getValue().getSExtValue()` for `IntegerAttr val` will 280 // expand to `getAttrOfType<IntegerAttr>("val").getValue().getSExtValue()`. 281 let convertFromStorage = "::llvm::cast<" # cppType # ">($_self)"; 282 283 // The predicate for when this def is used as a constraint. 284 let predicate = CPred<"::llvm::isa<" # cppType # ">($_self)">; 285} 286 287// Provide a LocationAttrDef for dialects to provide their own locations 288// that subclass LocationAttr. 289class LocationAttrDef<Dialect dialect, string name, list<Trait> traits = []> 290 : AttrDef<dialect, name, traits # [NativeAttrTrait<"IsLocation">], 291 "::mlir::LocationAttr">; 292 293// Define a new type, named `name`, belonging to `dialect` that inherits from 294// the given C++ base class. 295class TypeDef<Dialect dialect, string name, list<Trait> traits = [], 296 string baseCppClass = "::mlir::Type"> 297 : DialectType<dialect, CPred<"">, /*descr*/"", name # "Type">, 298 AttrOrTypeDef<"Type", name, traits, baseCppClass> { 299 // The name of the C++ Type class. 300 string cppClassName = name # "Type"; 301 302 // Make it possible to use such type as parameters for other types. 303 string cppType = dialect.cppNamespace # "::" # cppClassName; 304 305 // The unique type name. 306 string typeName = dialect.name # "." # mnemonic; 307 308 // A constant builder provided when the type has no parameters. 309 let builderCall = !if(!empty(parameters), 310 "$_builder.getType<" # cppType # ">()", 311 ""); 312 313 // The predicate for when this def is used as a constraint. 314 let predicate = CPred<"::llvm::isa<" # cppType # ">($_self)">; 315} 316 317//===----------------------------------------------------------------------===// 318// Parameters 319//===----------------------------------------------------------------------===// 320 321// 'Parameters' should be subclasses of this or simple strings (which is a 322// shorthand for AttrOrTypeParameter<"C++Type">). 323class AttrOrTypeParameter<string type, string desc, string accessorType = ""> { 324 // Custom memory allocation code for storage constructor. 325 code allocator = ?; 326 // Comparator used to compare two instances for equality. By default, it uses 327 // the C++ equality operator. 328 code comparator = ?; 329 // The C++ type of this parameter. 330 string cppType = type; 331 // The C++ type of the accessor for this parameter. 332 string cppAccessorType = !if(!empty(accessorType), type, accessorType); 333 // The C++ storage type of this parameter if it is a reference, e.g. 334 // `std::string` for `StringRef` or `SmallVector` for `ArrayRef`. 335 string cppStorageType = cppType; 336 // The C++ code to convert from the storage type to the parameter type. 337 string convertFromStorage = "$_self"; 338 // One-line human-readable description of the argument. 339 string summary = desc; 340 // The format string for the asm syntax (documentation only). 341 string syntax = ?; 342 // The default parameter parser is `::mlir::FieldParser<T>::parse($_parser)`, 343 // which returns `FailureOr<T>`. Specialize `FieldParser` to support parsing 344 // for your type. Or you can provide a customer printer. For attributes, 345 // "$_type" will be replaced with the required attribute type. 346 string parser = ?; 347 // The default parameter printer is `$_printer << $_self`. Overload the stream 348 // operator of `AsmPrinter` as necessary to print your type. Or you can 349 // provide a custom printer. 350 string printer = ?; 351 // Provide a default value for the parameter. Parameters with default values 352 // are considered optional. If a value was not parsed for the parameter, it 353 // will be set to the default value. Parameters equal to their default values 354 // are elided when printing. Equality is checked using the `comparator` field, 355 // which by default is the C++ equality operator. The current MLIR context is 356 // made available through `$_ctxt`, e.g., for constructing default values for 357 // attributes and types. 358 string defaultValue = ""; 359} 360class AttrParameter<string type, string desc, string accessorType = ""> 361 : AttrOrTypeParameter<type, desc, accessorType>; 362class TypeParameter<string type, string desc, string accessorType = ""> 363 : AttrOrTypeParameter<type, desc, accessorType>; 364 365// An optional parameter. 366class OptionalParameter<string type, string desc = ""> : 367 AttrOrTypeParameter<type, desc> { 368 let defaultValue = cppStorageType # "()"; 369} 370 371// A parameter with a default value. 372class DefaultValuedParameter<string type, string value, string desc = ""> : 373 AttrOrTypeParameter<type, desc> { 374 let defaultValue = value; 375} 376 377// For StringRefs, which require allocation. 378class StringRefParameter<string desc = "", string value = ""> : 379 AttrOrTypeParameter<"::llvm::StringRef", desc> { 380 let allocator = [{$_dst = $_allocator.copyInto($_self);}]; 381 let printer = [{$_printer.printString($_self);}]; 382 let cppStorageType = "std::string"; 383 let defaultValue = value; 384} 385 386// For APFloats, which require comparison. 387class APFloatParameter<string desc> : 388 AttrOrTypeParameter<"::llvm::APFloat", desc> { 389 let comparator = "$_lhs.bitwiseIsEqual($_rhs)"; 390} 391 392// For standard ArrayRefs, which require allocation. 393class ArrayRefParameter<string arrayOf, string desc = ""> : 394 AttrOrTypeParameter<"::llvm::ArrayRef<" # arrayOf # ">", desc> { 395 let allocator = [{$_dst = $_allocator.copyInto($_self);}]; 396 let cppStorageType = "::llvm::SmallVector<" # arrayOf # ">"; 397} 398 399// Regular array parameters cannot be parsed when empty. This optional array 400// parameter can be used with optional groups to be parsed when empty. 401class OptionalArrayRefParameter<string arrayOf, string desc = ""> : 402 OptionalParameter<"::llvm::ArrayRef<" # arrayOf # ">", desc> { 403 let allocator = [{$_dst = $_allocator.copyInto($_self);}]; 404 let cppStorageType = "::llvm::SmallVector<" # arrayOf # ">"; 405 let comparator = cppType # "($_lhs) == " # cppType # "($_rhs)"; 406} 407 408// For classes which require allocation and have their own allocateInto method. 409class SelfAllocationParameter<string type, string desc> : 410 AttrOrTypeParameter<type, desc> { 411 let allocator = [{$_dst = $_self.allocateInto($_allocator);}]; 412} 413 414// For ArrayRefs which contain things which allocate themselves. 415class ArrayRefOfSelfAllocationParameter<string arrayOf, string desc> : 416 AttrOrTypeParameter<"::llvm::ArrayRef<" # arrayOf # ">", desc> { 417 let allocator = [{ 418 llvm::SmallVector<}] # arrayOf # [{, 4> tmpFields; 419 for (size_t i = 0, e = $_self.size(); i < e; ++i) 420 tmpFields.push_back($_self[i].allocateInto($_allocator)); 421 $_dst = $_allocator.copyInto(ArrayRef<}] # arrayOf # [{>(tmpFields)); 422 }]; 423} 424 425// This is a special attribute parameter that represents the "self" type of the 426// attribute. It is specially handled by the assembly format generator to derive 427// its value from the optional trailing type after each attribute. 428// 429// By default, the self type parameter is optional and has a default value of 430// `none`. If a derived type other than `::mlir::Type` is specified, the 431// parameter loses its default value unless another one is specified by 432// `typeBuilder`. 433class AttributeSelfTypeParameter<string desc, 434 string derivedType = "::mlir::Type", 435 string typeBuilder = ""> : 436 AttrOrTypeParameter<derivedType, desc> { 437 let defaultValue = !if(!and(!empty(typeBuilder), 438 !eq(derivedType, "::mlir::Type")), 439 "::mlir::NoneType::get($_ctxt)", typeBuilder); 440} 441 442//===----------------------------------------------------------------------===// 443// ArrayOfAttr 444//===----------------------------------------------------------------------===// 445 446/// This class defines an attribute that contains an array of elements. The 447/// elements can be any type, but if they are attributes, the nested elements 448/// are parsed and printed using the custom attribute syntax. 449class ArrayOfAttr<Dialect dialect, string name, string attrMnemonic, 450 string eltName, list<Trait> traits = []> 451 : AttrDef<dialect, name, traits> { 452 let parameters = (ins OptionalArrayRefParameter<eltName>:$value); 453 let mnemonic = attrMnemonic; 454 let assemblyFormat = "`[` (`]`) : ($value^ `]`)?"; 455 456 let returnType = "::llvm::ArrayRef<" # eltName # ">"; 457 let constBuilderCall = "$_builder.getAttr<" # name # "Attr>($0)"; 458 let convertFromStorage = "$_self.getValue()"; 459 460 let extraClassDeclaration = [{ 461 auto begin() const { return getValue().begin(); } 462 auto end() const { return getValue().end(); } 463 bool empty() const { return getValue().empty(); } 464 size_t size() const { return getValue().size(); } 465 auto &front() const { return getValue().front(); } 466 auto &back() const { return getValue().back(); } 467 auto &operator[](size_t index) { return getValue()[index]; } 468 operator }] # returnType # [{() const { return getValue(); } 469 }]; 470} 471 472#endif // ATTRTYPEBASE_TD 473