1//===- BuiltinAttributes.td - Builtin attr definitions -----*- 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// Defines the set of builtin MLIR types, or the set of types necessary for the 10// validity of and defining the IR. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef BUILTIN_ATTRIBUTES 15#define BUILTIN_ATTRIBUTES 16 17include "mlir/IR/BuiltinDialect.td" 18include "mlir/IR/SubElementInterfaces.td" 19 20// TODO: Currently the attributes defined in this file are prefixed with 21// `Builtin_`. This is to differentiate the attributes here with the ones in 22// OpBase.td. We should remove the definitions in OpBase.td, and repoint users 23// to this file instead. 24 25// Base class for Builtin dialect attributes. 26class Builtin_Attr<string name, list<Trait> traits = [], 27 string baseCppClass = "::mlir::Attribute"> 28 : AttrDef<Builtin_Dialect, name, traits, baseCppClass> { 29 let mnemonic = ?; 30} 31 32//===----------------------------------------------------------------------===// 33// AffineMapAttr 34//===----------------------------------------------------------------------===// 35 36def Builtin_AffineMapAttr : Builtin_Attr<"AffineMap"> { 37 let summary = "An Attribute containing an AffineMap object"; 38 let description = [{ 39 Syntax: 40 41 ``` 42 affine-map-attribute ::= `affine_map` `<` affine-map `>` 43 ``` 44 45 Examples: 46 47 ```mlir 48 affine_map<(d0) -> (d0)> 49 affine_map<(d0, d1, d2) -> (d0, d1)> 50 ``` 51 }]; 52 let parameters = (ins "AffineMap":$value); 53 let builders = [ 54 AttrBuilderWithInferredContext<(ins "AffineMap":$value), [{ 55 return $_get(value.getContext(), value); 56 }]> 57 ]; 58 let extraClassDeclaration = "using ValueType = AffineMap;"; 59 let skipDefaultBuilders = 1; 60 let typeBuilder = "IndexType::get($_value.getContext())"; 61} 62 63//===----------------------------------------------------------------------===// 64// ArrayAttr 65//===----------------------------------------------------------------------===// 66 67def Builtin_ArrayAttr : Builtin_Attr<"Array", [ 68 DeclareAttrInterfaceMethods<SubElementAttrInterface> 69 ]> { 70 let summary = "A collection of other Attribute values"; 71 let description = [{ 72 Syntax: 73 74 ``` 75 array-attribute ::= `[` (attribute-value (`,` attribute-value)*)? `]` 76 ``` 77 78 An array attribute is an attribute that represents a collection of attribute 79 values. 80 81 Examples: 82 83 ```mlir 84 [] 85 [10, i32] 86 [affine_map<(d0, d1, d2) -> (d0, d1)>, i32, "string attribute"] 87 ``` 88 }]; 89 let parameters = (ins ArrayRefParameter<"Attribute", "">:$value); 90 let extraClassDeclaration = [{ 91 using ValueType = ArrayRef<Attribute>; 92 93 /// Return the element at the given index. 94 Attribute operator[](unsigned idx) const { 95 assert(idx < size() && "index out of bounds"); 96 return getValue()[idx]; 97 } 98 99 /// Support range iteration. 100 using iterator = llvm::ArrayRef<Attribute>::iterator; 101 iterator begin() const { return getValue().begin(); } 102 iterator end() const { return getValue().end(); } 103 size_t size() const { return getValue().size(); } 104 bool empty() const { return size() == 0; } 105 106 private: 107 /// Class for underlying value iterator support. 108 template <typename AttrTy> 109 class attr_value_iterator final 110 : public llvm::mapped_iterator<ArrayAttr::iterator, 111 AttrTy (*)(Attribute)> { 112 public: 113 explicit attr_value_iterator(ArrayAttr::iterator it) 114 : llvm::mapped_iterator<ArrayAttr::iterator, AttrTy (*)(Attribute)>( 115 it, [](Attribute attr) { return attr.cast<AttrTy>(); }) {} 116 AttrTy operator*() const { return (*this->I).template cast<AttrTy>(); } 117 }; 118 119 public: 120 template <typename AttrTy> 121 iterator_range<attr_value_iterator<AttrTy>> getAsRange() const { 122 return llvm::make_range(attr_value_iterator<AttrTy>(begin()), 123 attr_value_iterator<AttrTy>(end())); 124 } 125 template <typename AttrTy, 126 typename UnderlyingTy = typename AttrTy::ValueType> 127 auto getAsValueRange() const { 128 return llvm::map_range(getAsRange<AttrTy>(), [](AttrTy attr) { 129 return static_cast<UnderlyingTy>(attr.getValue()); 130 }); 131 } 132 }]; 133} 134 135//===----------------------------------------------------------------------===// 136// DenseIntOrFPElementsAttr 137//===----------------------------------------------------------------------===// 138 139def Builtin_DenseIntOrFPElementsAttr 140 : Builtin_Attr<"DenseIntOrFPElements", /*traits=*/[], "DenseElementsAttr"> { 141 let summary = "An Attribute containing a dense multi-dimensional array of " 142 "integer or floating-point values"; 143 let description = [{ 144 Syntax: 145 146 ``` 147 dense-intorfloat-elements-attribute ::= `dense` `<` attribute-value `>` `:` 148 ( tensor-type | vector-type ) 149 ``` 150 151 A dense int-or-float elements attribute is an elements attribute containing 152 a densely packed vector or tensor of integer or floating-point values. The 153 element type of this attribute is required to be either an `IntegerType` or 154 a `FloatType`. 155 156 Examples: 157 158 ``` 159 // A splat tensor of integer values. 160 dense<10> : tensor<2xi32> 161 // A tensor of 2 float32 elements. 162 dense<[10.0, 11.0]> : tensor<2xf32> 163 ``` 164 }]; 165 let parameters = (ins AttributeSelfTypeParameter<"", "ShapedType">:$type, 166 "ArrayRef<char>":$rawData); 167 let extraClassDeclaration = [{ 168 /// Convert endianess of input ArrayRef for big-endian(BE) machines. All of 169 /// the elements of `inRawData` has `type`. If `inRawData` is little endian 170 /// (LE), it is converted to big endian (BE). Conversely, if `inRawData` is 171 /// BE, converted to LE. 172 static void 173 convertEndianOfArrayRefForBEmachine(ArrayRef<char> inRawData, 174 MutableArrayRef<char> outRawData, 175 ShapedType type); 176 177 /// Convert endianess of input for big-endian(BE) machines. The number of 178 /// elements of `inRawData` is `numElements`, and each element has 179 /// `elementBitWidth` bits. If `inRawData` is little endian (LE), it is 180 /// converted to big endian (BE) and saved in `outRawData`. Conversely, if 181 /// `inRawData` is BE, converted to LE. 182 static void convertEndianOfCharForBEmachine(const char *inRawData, 183 char *outRawData, 184 size_t elementBitWidth, 185 size_t numElements); 186 187 protected: 188 friend DenseElementsAttr; 189 190 /// Constructs a dense elements attribute from an array of raw APFloat 191 /// values. Each APFloat value is expected to have the same bitwidth as the 192 /// element type of 'type'. 'type' must be a vector or tensor with static 193 /// shape. 194 static DenseElementsAttr getRaw(ShapedType type, size_t storageWidth, 195 ArrayRef<APFloat> values, bool isSplat); 196 197 /// Constructs a dense elements attribute from an array of raw APInt values. 198 /// Each APInt value is expected to have the same bitwidth as the element 199 /// type of 'type'. 'type' must be a vector or tensor with static shape. 200 static DenseElementsAttr getRaw(ShapedType type, size_t storageWidth, 201 ArrayRef<APInt> values, bool isSplat); 202 203 /// Get or create a new dense elements attribute instance with the given raw 204 /// data buffer. 'type' must be a vector or tensor with static shape. 205 static DenseElementsAttr getRaw(ShapedType type, ArrayRef<char> data, 206 bool isSplat); 207 208 /// Overload of the raw 'get' method that asserts that the given type is of 209 /// complex type. This method is used to verify type invariants that the 210 /// templatized 'get' method cannot. 211 static DenseElementsAttr getRawComplex(ShapedType type, ArrayRef<char> data, 212 int64_t dataEltSize, bool isInt, 213 bool isSigned); 214 215 /// Overload of the raw 'get' method that asserts that the given type is of 216 /// integer or floating-point type. This method is used to verify type 217 /// invariants that the templatized 'get' method cannot. 218 static DenseElementsAttr getRawIntOrFloat(ShapedType type, 219 ArrayRef<char> data, 220 int64_t dataEltSize, bool isInt, 221 bool isSigned); 222 223 public: 224 }]; 225 let genAccessors = 0; 226 let genStorageClass = 0; 227 let skipDefaultBuilders = 1; 228} 229 230//===----------------------------------------------------------------------===// 231// DenseStringElementsAttr 232//===----------------------------------------------------------------------===// 233 234def Builtin_DenseStringElementsAttr 235 : Builtin_Attr<"DenseStringElements", /*traits=*/[], "DenseElementsAttr"> { 236 let summary = "An Attribute containing a dense multi-dimensional array of " 237 "strings"; 238 let description = [{ 239 Syntax: 240 241 ``` 242 dense-string-elements-attribute ::= `dense` `<` attribute-value `>` `:` 243 ( tensor-type | vector-type ) 244 ``` 245 246 A dense string elements attribute is an elements attribute containing a 247 densely packed vector or tensor of string values. There are no restrictions 248 placed on the element type of this attribute, enabling the use of dialect 249 specific string types. 250 251 Examples: 252 253 ``` 254 // A splat tensor of strings. 255 dense<"example"> : tensor<2x!foo.string> 256 // A tensor of 2 string elements. 257 dense<["example1", "example2"]> : tensor<2x!foo.string> 258 ``` 259 }]; 260 let parameters = (ins AttributeSelfTypeParameter<"", "ShapedType">:$type, 261 "ArrayRef<StringRef>":$value); 262 let builders = [ 263 AttrBuilderWithInferredContext<(ins "ShapedType":$type, 264 "ArrayRef<StringRef>":$values), [{ 265 return $_get(type.getContext(), type, values, 266 /* isSplat */(values.size() == 1)); 267 }]>, 268 ]; 269 let extraClassDeclaration = [{ 270 protected: 271 friend DenseElementsAttr; 272 273 public: 274 }]; 275 let genAccessors = 0; 276 let genStorageClass = 0; 277 let skipDefaultBuilders = 1; 278} 279 280//===----------------------------------------------------------------------===// 281// DictionaryAttr 282//===----------------------------------------------------------------------===// 283 284def Builtin_DictionaryAttr : Builtin_Attr<"Dictionary", [ 285 DeclareAttrInterfaceMethods<SubElementAttrInterface> 286 ]> { 287 let summary = "An dictionary of named Attribute values"; 288 let description = [{ 289 Syntax: 290 291 ``` 292 dictionary-attribute ::= `{` (attribute-entry (`,` attribute-entry)*)? `}` 293 ``` 294 295 A dictionary attribute is an attribute that represents a sorted collection of 296 named attribute values. The elements are sorted by name, and each name must be 297 unique within the collection. 298 299 Examples: 300 301 ```mlir 302 {} 303 {attr_name = "string attribute"} 304 {int_attr = 10, "string attr name" = "string attribute"} 305 ``` 306 }]; 307 let parameters = (ins ArrayRefParameter<"NamedAttribute", "">:$value); 308 let builders = [ 309 AttrBuilder<(ins CArg<"ArrayRef<NamedAttribute>", "llvm::None">:$value)> 310 ]; 311 let extraClassDeclaration = [{ 312 using ValueType = ArrayRef<NamedAttribute>; 313 314 /// Construct a dictionary with an array of values that is known to already 315 /// be sorted by name and uniqued. 316 static DictionaryAttr getWithSorted(MLIRContext *context, 317 ArrayRef<NamedAttribute> value); 318 319 /// Return the specified attribute if present, null otherwise. 320 Attribute get(StringRef name) const; 321 Attribute get(Identifier name) const; 322 323 /// Return the specified named attribute if present, None otherwise. 324 Optional<NamedAttribute> getNamed(StringRef name) const; 325 Optional<NamedAttribute> getNamed(Identifier name) const; 326 327 /// Support range iteration. 328 using iterator = llvm::ArrayRef<NamedAttribute>::iterator; 329 iterator begin() const; 330 iterator end() const; 331 bool empty() const { return size() == 0; } 332 size_t size() const; 333 334 /// Sorts the NamedAttributes in the array ordered by name as expected by 335 /// getWithSorted and returns whether the values were sorted. 336 /// Requires: uniquely named attributes. 337 static bool sort(ArrayRef<NamedAttribute> values, 338 SmallVectorImpl<NamedAttribute> &storage); 339 340 /// Sorts the NamedAttributes in the array ordered by name as expected by 341 /// getWithSorted in place on an array and returns whether the values needed 342 /// to be sorted. 343 /// Requires: uniquely named attributes. 344 static bool sortInPlace(SmallVectorImpl<NamedAttribute> &array); 345 346 /// Returns an entry with a duplicate name in `array`, if it exists, else 347 /// returns llvm::None. If `isSorted` is true, the array is assumed to be 348 /// sorted else it will be sorted in place before finding the duplicate entry. 349 static Optional<NamedAttribute> 350 findDuplicate(SmallVectorImpl<NamedAttribute> &array, bool isSorted); 351 352 /// Return the specified attribute if present and is an instance of 353 /// `AttrClass`, null otherwise. 354 template<typename AttrClass, typename NameClass> 355 AttrClass getAs(NameClass &&name) const { 356 return get(std::forward<NameClass>(name)) 357 .template dyn_cast_or_null<AttrClass>(); 358 } 359 360 private: 361 /// Return empty dictionary. 362 static DictionaryAttr getEmpty(MLIRContext *context); 363 364 /// Return empty dictionary. This is a special variant of the above method 365 /// that is used by the MLIRContext to cache the empty dictionary instance. 366 static DictionaryAttr getEmptyUnchecked(MLIRContext *context); 367 368 /// Allow access to `getEmptyUnchecked`. 369 friend MLIRContext; 370 371 public: 372 }]; 373 let skipDefaultBuilders = 1; 374} 375 376//===----------------------------------------------------------------------===// 377// FloatAttr 378//===----------------------------------------------------------------------===// 379 380def Builtin_FloatAttr : Builtin_Attr<"Float"> { 381 let summary = "An Attribute containing a floating-point value"; 382 let description = [{ 383 Syntax: 384 385 ``` 386 float-attribute ::= (float-literal (`:` float-type)?) 387 | (hexadecimal-literal `:` float-type) 388 ``` 389 390 A float attribute is a literal attribute that represents a floating point 391 value of the specified [float type](#floating-point-types). It can be 392 represented in the hexadecimal form where the hexadecimal value is 393 interpreted as bits of the underlying binary representation. This form is 394 useful for representing infinity and NaN floating point values. To avoid 395 confusion with integer attributes, hexadecimal literals _must_ be followed 396 by a float type to define a float attribute. 397 398 Examples: 399 400 ``` 401 42.0 // float attribute defaults to f64 type 402 42.0 : f32 // float attribute of f32 type 403 0x7C00 : f16 // positive infinity 404 0x7CFF : f16 // NaN (one of possible values) 405 42 : f32 // Error: expected integer type 406 ``` 407 }]; 408 let parameters = (ins AttributeSelfTypeParameter<"">:$type, 409 APFloatParameter<"">:$value); 410 let builders = [ 411 AttrBuilderWithInferredContext<(ins "Type":$type, 412 "const APFloat &":$value), [{ 413 return $_get(type.getContext(), type, value); 414 }]>, 415 AttrBuilderWithInferredContext<(ins "Type":$type, "double":$value), [{ 416 if (type.isF64() || !type.isa<FloatType>()) 417 return $_get(type.getContext(), type, APFloat(value)); 418 419 // This handles, e.g., F16 because there is no APFloat constructor for it. 420 bool unused; 421 APFloat val(value); 422 val.convert(type.cast<FloatType>().getFloatSemantics(), 423 APFloat::rmNearestTiesToEven, &unused); 424 return $_get(type.getContext(), type, val); 425 }]> 426 ]; 427 let extraClassDeclaration = [{ 428 using ValueType = APFloat; 429 430 /// This function is used to convert the value to a double, even if it loses 431 /// precision. 432 double getValueAsDouble() const; 433 static double getValueAsDouble(APFloat val); 434 }]; 435 let genVerifyDecl = 1; 436 let skipDefaultBuilders = 1; 437} 438 439//===----------------------------------------------------------------------===// 440// IntegerAttr 441//===----------------------------------------------------------------------===// 442 443def Builtin_IntegerAttr : Builtin_Attr<"Integer"> { 444 let summary = "An Attribute containing a integer value"; 445 let description = [{ 446 Syntax: 447 448 ``` 449 integer-attribute ::= (integer-literal ( `:` (index-type | integer-type) )?) 450 | `true` | `false` 451 ``` 452 453 An integer attribute is a literal attribute that represents an integral 454 value of the specified integer or index type. `i1` integer attributes are 455 treated as `boolean` attributes, and use a unique assembly format of either 456 `true` or `false` depending on the value. The default type for non-boolean 457 integer attributes, if a type is not specified, is signless 64-bit integer. 458 459 Examples: 460 461 ```mlir 462 10 : i32 463 10 // : i64 is implied here. 464 true // A bool, i.e. i1, value. 465 false // A bool, i.e. i1, value. 466 ``` 467 }]; 468 let parameters = (ins AttributeSelfTypeParameter<"">:$type, "APInt":$value); 469 let builders = [ 470 AttrBuilderWithInferredContext<(ins "Type":$type, 471 "const APInt &":$value), [{ 472 if (type.isSignlessInteger(1)) 473 return BoolAttr::get(type.getContext(), value.getBoolValue()); 474 return $_get(type.getContext(), type, value); 475 }]>, 476 AttrBuilder<(ins "const APSInt &":$value), [{ 477 auto signedness = value.isSigned() ? 478 IntegerType::Signed : IntegerType::Unsigned; 479 auto type = IntegerType::get($_ctxt, value.getBitWidth(), signedness); 480 return $_get(type.getContext(), type, value); 481 }]>, 482 AttrBuilderWithInferredContext<(ins "Type":$type, "int64_t":$value), [{ 483 // `index` has a defined internal storage width. 484 if (type.isIndex()) { 485 APInt apValue(IndexType::kInternalStorageBitWidth, value); 486 return $_get(type.getContext(), type, apValue); 487 } 488 489 IntegerType intTy = type.cast<IntegerType>(); 490 APInt apValue(intTy.getWidth(), value, intTy.isSignedInteger()); 491 return $_get(type.getContext(), type, apValue); 492 }]> 493 ]; 494 let extraClassDeclaration = [{ 495 using ValueType = APInt; 496 497 /// Return the integer value as a 64-bit int. The attribute must be a 498 /// signless integer. 499 // TODO: Change callers to use getValue instead. 500 int64_t getInt() const; 501 /// Return the integer value as a signed 64-bit int. The attribute must be 502 /// a signed integer. 503 int64_t getSInt() const; 504 /// Return the integer value as a unsigned 64-bit int. The attribute must be 505 /// an unsigned integer. 506 uint64_t getUInt() const; 507 508 /// Return the value as an APSInt which carries the signed from the type of 509 /// the attribute. This traps on signless integers types! 510 APSInt getAPSInt() const; 511 512 private: 513 /// Return a boolean attribute. This is a special variant of the `get` 514 /// method that is used by the MLIRContext to cache the boolean IntegerAttr 515 /// instances. 516 static BoolAttr getBoolAttrUnchecked(IntegerType type, bool value); 517 518 /// Allow access to `getBoolAttrUnchecked`. 519 friend MLIRContext; 520 521 public: 522 }]; 523 let genVerifyDecl = 1; 524 let skipDefaultBuilders = 1; 525} 526 527//===----------------------------------------------------------------------===// 528// IntegerSetAttr 529//===----------------------------------------------------------------------===// 530 531def Builtin_IntegerSetAttr : Builtin_Attr<"IntegerSet"> { 532 let summary = "An Attribute containing an IntegerSet object"; 533 let description = [{ 534 Syntax: 535 536 ``` 537 integer-set-attribute ::= `affine_set` `<` integer-set `>` 538 ``` 539 540 Examples: 541 542 ```mlir 543 affine_set<(d0) : (d0 - 2 >= 0)> 544 ``` 545 }]; 546 let parameters = (ins "IntegerSet":$value); 547 let builders = [ 548 AttrBuilderWithInferredContext<(ins "IntegerSet":$value), [{ 549 return $_get(value.getContext(), value); 550 }]> 551 ]; 552 let extraClassDeclaration = "using ValueType = IntegerSet;"; 553 let skipDefaultBuilders = 1; 554} 555 556//===----------------------------------------------------------------------===// 557// OpaqueAttr 558//===----------------------------------------------------------------------===// 559 560def Builtin_OpaqueAttr : Builtin_Attr<"Opaque"> { 561 let summary = "An opaque representation of another Attribute"; 562 let description = [{ 563 Syntax: 564 565 ``` 566 opaque-attribute ::= dialect-namespace `<` attr-data `>` 567 ``` 568 569 Opaque attributes represent attributes of non-registered dialects. These are 570 attribute represented in their raw string form, and can only usefully be 571 tested for attribute equality. 572 573 Examples: 574 575 ```mlir 576 #dialect<"opaque attribute data"> 577 ``` 578 }]; 579 let parameters = (ins "Identifier":$dialectNamespace, 580 StringRefParameter<"">:$attrData, 581 AttributeSelfTypeParameter<"">:$type); 582 let builders = [ 583 AttrBuilderWithInferredContext<(ins "Identifier":$dialect, 584 "StringRef":$attrData, 585 "Type":$type), [{ 586 return $_get(dialect.getContext(), dialect, attrData, type); 587 }]> 588 ]; 589 let genVerifyDecl = 1; 590 let skipDefaultBuilders = 1; 591} 592 593//===----------------------------------------------------------------------===// 594// OpaqueElementsAttr 595//===----------------------------------------------------------------------===// 596 597def Builtin_OpaqueElementsAttr 598 : Builtin_Attr<"OpaqueElements", /*traits=*/[], "ElementsAttr"> { 599 let summary = "An opaque representation of a multi-dimensional array"; 600 let description = [{ 601 Syntax: 602 603 ``` 604 opaque-elements-attribute ::= `opaque` `<` dialect-namespace `,` 605 hex-string-literal `>` `:` 606 ( tensor-type | vector-type ) 607 ``` 608 609 An opaque elements attribute is an elements attribute where the content of 610 the value is opaque. The representation of the constant stored by this 611 elements attribute is only understood, and thus decodable, by the dialect 612 that created it. 613 614 Note: The parsed string literal must be in hexadecimal form. 615 616 Examples: 617 618 ```mlir 619 opaque<"foo_dialect", "0xDEADBEEF"> : tensor<10xi32> 620 ``` 621 }]; 622 623 // TODO: Provide a way to avoid copying content of large opaque 624 // tensors This will likely require a new reference attribute kind. 625 let parameters = (ins "Identifier":$dialect, 626 StringRefParameter<"">:$value, 627 AttributeSelfTypeParameter<"", "ShapedType">:$type); 628 let builders = [ 629 AttrBuilderWithInferredContext<(ins "Identifier":$dialect, 630 "ShapedType":$type, 631 "StringRef":$value), [{ 632 return $_get(dialect.getContext(), dialect, value, type); 633 }]>, 634 AttrBuilderWithInferredContext<(ins "Dialect *":$dialect, 635 "ShapedType":$type, 636 "StringRef":$value), [{ 637 MLIRContext *ctxt = dialect->getContext(); 638 Identifier dialectName = Identifier::get(dialect->getNamespace(), ctxt); 639 return $_get(ctxt, dialectName, value, type); 640 }]> 641 ]; 642 let extraClassDeclaration = [{ 643 using ValueType = StringRef; 644 645 /// Return the value at the given index. The 'index' is expected to refer to 646 /// a valid element. 647 Attribute getValue(ArrayRef<uint64_t> index) const; 648 649 /// Decodes the attribute value using dialect-specific decoding hook. 650 /// Returns false if decoding is successful. If not, returns true and leaves 651 /// 'result' argument unspecified. 652 bool decode(ElementsAttr &result); 653 654 }]; 655 let genVerifyDecl = 1; 656 let skipDefaultBuilders = 1; 657} 658 659//===----------------------------------------------------------------------===// 660// SparseElementsAttr 661//===----------------------------------------------------------------------===// 662 663def Builtin_SparseElementsAttr 664 : Builtin_Attr<"SparseElements", /*traits=*/[], "ElementsAttr"> { 665 let summary = "An opaque representation of a multi-dimensional array"; 666 let description = [{ 667 Syntax: 668 669 ``` 670 sparse-elements-attribute ::= `sparse` `<` attribute-value `,` 671 attribute-value `>` `:` 672 ( tensor-type | vector-type ) 673 ``` 674 675 A sparse elements attribute is an elements attribute that represents a 676 sparse vector or tensor object. This is where very few of the elements are 677 non-zero. 678 679 The attribute uses COO (coordinate list) encoding to represent the sparse 680 elements of the elements attribute. The indices are stored via a 2-D tensor 681 of 64-bit integer elements with shape [N, ndims], which specifies the 682 indices of the elements in the sparse tensor that contains non-zero values. 683 The element values are stored via a 1-D tensor with shape [N], that supplies 684 the corresponding values for the indices. 685 686 Example: 687 688 ```mlir 689 sparse<[[0, 0], [1, 2]], [1, 5]> : tensor<3x4xi32> 690 691 // This represents the following tensor: 692 /// [[1, 0, 0, 0], 693 /// [0, 0, 5, 0], 694 /// [0, 0, 0, 0]] 695 ``` 696 }]; 697 698 let parameters = (ins AttributeSelfTypeParameter<"", "ShapedType">:$type, 699 "DenseIntElementsAttr":$indices, 700 "DenseElementsAttr":$values); 701 let builders = [ 702 AttrBuilderWithInferredContext<(ins "ShapedType":$type, 703 "DenseElementsAttr":$indices, 704 "DenseElementsAttr":$values), [{ 705 assert(indices.getType().getElementType().isInteger(64) && 706 "expected sparse indices to be 64-bit integer values"); 707 assert((type.isa<RankedTensorType, VectorType>()) && 708 "type must be ranked tensor or vector"); 709 assert(type.hasStaticShape() && "type must have static shape"); 710 return $_get(type.getContext(), type, 711 indices.cast<DenseIntElementsAttr>(), values); 712 }]>, 713 ]; 714 let extraClassDeclaration = [{ 715 template <typename T> 716 using iterator = 717 llvm::mapped_iterator<typename decltype(llvm::seq<ptrdiff_t>(0, 0))::iterator, 718 std::function<T(ptrdiff_t)>>; 719 720 /// Return the values of this attribute in the form of the given type 'T'. 721 /// 'T' may be any of Attribute, APInt, APFloat, c++ integer/float types, 722 /// etc. 723 template <typename T> llvm::iterator_range<iterator<T>> getValues() const; 724 725 /// Return the value of the element at the given index. The 'index' is 726 /// expected to refer to a valid element. 727 Attribute getValue(ArrayRef<uint64_t> index) const; 728 729 private: 730 /// Get a zero APFloat for the given sparse attribute. 731 APFloat getZeroAPFloat() const; 732 733 /// Get a zero APInt for the given sparse attribute. 734 APInt getZeroAPInt() const; 735 736 /// Get a zero attribute for the given sparse attribute. 737 Attribute getZeroAttr() const; 738 739 /// Utility methods to generate a zero value of some type 'T'. This is used 740 /// by the 'iterator' class. 741 /// Get a zero for a given attribute type. 742 template <typename T> 743 typename std::enable_if<std::is_base_of<Attribute, T>::value, T>::type 744 getZeroValue() const { 745 return getZeroAttr().template cast<T>(); 746 } 747 /// Get a zero for an APInt. 748 template <typename T> 749 typename std::enable_if<std::is_same<APInt, T>::value, T>::type 750 getZeroValue() const { 751 return getZeroAPInt(); 752 } 753 template <typename T> 754 typename std::enable_if<std::is_same<std::complex<APInt>, T>::value, 755 T>::type 756 getZeroValue() const { 757 APInt intZero = getZeroAPInt(); 758 return {intZero, intZero}; 759 } 760 /// Get a zero for an APFloat. 761 template <typename T> 762 typename std::enable_if<std::is_same<APFloat, T>::value, T>::type 763 getZeroValue() const { 764 return getZeroAPFloat(); 765 } 766 template <typename T> 767 typename std::enable_if<std::is_same<std::complex<APFloat>, T>::value, 768 T>::type 769 getZeroValue() const { 770 APFloat floatZero = getZeroAPFloat(); 771 return {floatZero, floatZero}; 772 } 773 774 /// Get a zero for an C++ integer, float, StringRef, or complex type. 775 template <typename T> 776 typename std::enable_if< 777 std::numeric_limits<T>::is_integer || 778 DenseElementsAttr::is_valid_cpp_fp_type<T>::value || 779 std::is_same<T, StringRef>::value || 780 (detail::is_complex_t<T>::value && 781 !llvm::is_one_of<T, std::complex<APInt>, 782 std::complex<APFloat>>::value), 783 T>::type 784 getZeroValue() const { 785 return T(); 786 } 787 788 /// Flatten, and return, all of the sparse indices in this attribute in 789 /// row-major order. 790 std::vector<ptrdiff_t> getFlattenedSparseIndices() const; 791 792 public: 793 }]; 794 let skipDefaultBuilders = 1; 795} 796 797//===----------------------------------------------------------------------===// 798// StringAttr 799//===----------------------------------------------------------------------===// 800 801def Builtin_StringAttr : Builtin_Attr<"String"> { 802 let summary = "An Attribute containing a string"; 803 let description = [{ 804 Syntax: 805 806 ``` 807 string-attribute ::= string-literal (`:` type)? 808 ``` 809 810 A string attribute is an attribute that represents a string literal value. 811 812 Examples: 813 814 ```mlir 815 "An important string" 816 "string with a type" : !dialect.string 817 ``` 818 }]; 819 let parameters = (ins StringRefParameter<"">:$value, 820 AttributeSelfTypeParameter<"">:$type); 821 let builders = [ 822 AttrBuilderWithInferredContext<(ins "const Twine &":$bytes, "Type":$type)>, 823 /// Build an string attr with NoneType. 824 AttrBuilder<(ins "const Twine &":$bytes)>, 825 /// Build an empty string attr with NoneType. 826 AttrBuilder<(ins)> 827 ]; 828 let extraClassDeclaration = [{ 829 using ValueType = StringRef; 830 831 private: 832 /// Return an empty StringAttr with NoneType type. This is a special variant 833 /// of the `get` method that is used by the MLIRContext to cache the 834 /// instance. 835 static StringAttr getEmptyStringAttrUnchecked(MLIRContext *context); 836 friend MLIRContext; 837 public: 838 }]; 839 let skipDefaultBuilders = 1; 840} 841 842//===----------------------------------------------------------------------===// 843// SymbolRefAttr 844//===----------------------------------------------------------------------===// 845 846def Builtin_SymbolRefAttr : Builtin_Attr<"SymbolRef"> { 847 let summary = "An Attribute containing a symbolic reference to an Operation"; 848 let description = [{ 849 Syntax: 850 851 ``` 852 symbol-ref-attribute ::= symbol-ref-id (`::` symbol-ref-id)* 853 ``` 854 855 A symbol reference attribute is a literal attribute that represents a named 856 reference to an operation that is nested within an operation with the 857 `OpTrait::SymbolTable` trait. As such, this reference is given meaning by 858 the nearest parent operation containing the `OpTrait::SymbolTable` trait. It 859 may optionally contain a set of nested references that further resolve to a 860 symbol nested within a different symbol table. 861 862 This attribute can only be held internally by 863 [array attributes](#array-attribute) and 864 [dictionary attributes](#dictionary-attribute)(including the top-level 865 operation attribute dictionary), i.e. no other attribute kinds such as 866 Locations or extended attribute kinds. 867 868 **Rationale:** Identifying accesses to global data is critical to 869 enabling efficient multi-threaded compilation. Restricting global 870 data access to occur through symbols and limiting the places that can 871 legally hold a symbol reference simplifies reasoning about these data 872 accesses. 873 874 See [`Symbols And SymbolTables`](../SymbolsAndSymbolTables.md) for more 875 information. 876 877 Examples: 878 879 ```mlir 880 @flat_reference 881 @parent_reference::@nested_reference 882 ``` 883 }]; 884 let parameters = (ins 885 StringRefParameter<"">:$rootReference, 886 ArrayRefParameter<"FlatSymbolRefAttr", "">:$nestedReferences 887 ); 888 let extraClassDeclaration = [{ 889 static FlatSymbolRefAttr get(MLIRContext *ctx, StringRef value); 890 891 /// Returns the name of the fully resolved symbol, i.e. the leaf of the 892 /// reference path. 893 StringRef getLeafReference() const; 894 }]; 895} 896 897//===----------------------------------------------------------------------===// 898// TypeAttr 899//===----------------------------------------------------------------------===// 900 901def Builtin_TypeAttr : Builtin_Attr<"Type", [ 902 DeclareAttrInterfaceMethods<SubElementAttrInterface> 903 ]> { 904 let summary = "An Attribute containing a Type"; 905 let description = [{ 906 Syntax: 907 908 ``` 909 type-attribute ::= type 910 ``` 911 912 A type attribute is an attribute that represents a 913 [type object](#type-system). 914 915 Examples: 916 917 ```mlir 918 i32 919 !dialect.type 920 ``` 921 }]; 922 let parameters = (ins "Type":$value); 923 let builders = [ 924 AttrBuilderWithInferredContext<(ins "Type":$type), [{ 925 return $_get(type.getContext(), type); 926 }]>, 927 ]; 928 let extraClassDeclaration = "using ValueType = Type;"; 929 let skipDefaultBuilders = 1; 930} 931 932//===----------------------------------------------------------------------===// 933// UnitAttr 934//===----------------------------------------------------------------------===// 935 936def Builtin_UnitAttr : Builtin_Attr<"Unit"> { 937 let summary = "An Attribute value of `unit` type"; 938 let description = [{ 939 Syntax: 940 941 ``` 942 unit-attribute ::= `unit` 943 ``` 944 945 A unit attribute is an attribute that represents a value of `unit` type. The 946 `unit` type allows only one value forming a singleton set. This attribute 947 value is used to represent attributes that only have meaning from their 948 existence. 949 950 One example of such an attribute could be the `swift.self` attribute. This 951 attribute indicates that a function parameter is the self/context parameter. 952 It could be represented as a [boolean attribute](#boolean-attribute)(true or 953 false), but a value of false doesn't really bring any value. The parameter 954 either is the self/context or it isn't. 955 956 957 Examples: 958 959 ```mlir 960 // A unit attribute defined with the `unit` value specifier. 961 func @verbose_form() attributes {dialectName.unitAttr = unit} 962 963 // A unit attribute in an attribute dictionary can also be defined without 964 // the value specifier. 965 func @simple_form() attributes {dialectName.unitAttr} 966 ``` 967 }]; 968 let extraClassDeclaration = [{ 969 static UnitAttr get(MLIRContext *context); 970 }]; 971} 972 973#endif // BUILTIN_ATTRIBUTES 974