diff --git a/mlir/include/mlir/IR/BuiltinAttributes.h b/mlir/include/mlir/IR/BuiltinAttributes.h --- a/mlir/include/mlir/IR/BuiltinAttributes.h +++ b/mlir/include/mlir/IR/BuiltinAttributes.h @@ -16,21 +16,29 @@ namespace mlir { class AffineMap; +class FlatSymbolRefAttr; class FunctionType; class IntegerSet; class Location; class ShapedType; +} // namespace mlir + +//===----------------------------------------------------------------------===// +// Tablegen Attribute Declarations +//===----------------------------------------------------------------------===// + +#define GET_ATTRDEF_CLASSES +#include "mlir/IR/BuiltinAttributes.h.inc" + +//===----------------------------------------------------------------------===// +// C++ Attribute Declarations +//===----------------------------------------------------------------------===// +namespace mlir { namespace detail { -struct AffineMapAttributeStorage; -struct ArrayAttributeStorage; -struct DictionaryAttributeStorage; struct IntegerAttributeStorage; -struct IntegerSetAttributeStorage; struct FloatAttributeStorage; -struct OpaqueAttributeStorage; -struct StringAttributeStorage; struct SymbolRefAttributeStorage; struct TypeAttributeStorage; @@ -41,139 +49,6 @@ struct SparseElementsAttributeStorage; } // namespace detail -//===----------------------------------------------------------------------===// -// AffineMapAttr -//===----------------------------------------------------------------------===// - -class AffineMapAttr - : public Attribute::AttrBase { -public: - using Base::Base; - using ValueType = AffineMap; - - static AffineMapAttr get(AffineMap value); - - AffineMap getValue() const; -}; - -//===----------------------------------------------------------------------===// -// ArrayAttr -//===----------------------------------------------------------------------===// - -/// Array attributes are lists of other attributes. They are not necessarily -/// type homogenous given that attributes don't, in general, carry types. -class ArrayAttr : public Attribute::AttrBase { -public: - using Base::Base; - using ValueType = ArrayRef; - - static ArrayAttr get(MLIRContext *context, ArrayRef value); - - ArrayRef getValue() const; - Attribute operator[](unsigned idx) const; - - /// Support range iteration. - using iterator = llvm::ArrayRef::iterator; - iterator begin() const { return getValue().begin(); } - iterator end() const { return getValue().end(); } - size_t size() const { return getValue().size(); } - bool empty() const { return size() == 0; } - -private: - /// Class for underlying value iterator support. - template - class attr_value_iterator final - : public llvm::mapped_iterator { - public: - explicit attr_value_iterator(ArrayAttr::iterator it) - : llvm::mapped_iterator( - it, [](Attribute attr) { return attr.cast(); }) {} - AttrTy operator*() const { return (*this->I).template cast(); } - }; - -public: - template - iterator_range> getAsRange() { - return llvm::make_range(attr_value_iterator(begin()), - attr_value_iterator(end())); - } - template - auto getAsValueRange() { - return llvm::map_range(getAsRange(), [](AttrTy attr) { - return static_cast(attr.getValue()); - }); - } -}; - -//===----------------------------------------------------------------------===// -// DictionaryAttr -//===----------------------------------------------------------------------===// - -/// Dictionary attribute is an attribute that represents a sorted collection of -/// named attribute values. The elements are sorted by name, and each name must -/// be unique within the collection. -class DictionaryAttr - : public Attribute::AttrBase { -public: - using Base::Base; - using ValueType = ArrayRef; - - /// Construct a dictionary attribute with the provided list of named - /// attributes. This method assumes that the provided list is unordered. If - /// the caller can guarantee that the attributes are ordered by name, - /// getWithSorted should be used instead. - static DictionaryAttr get(MLIRContext *context, - ArrayRef value); - - /// Construct a dictionary with an array of values that is known to already be - /// sorted by name and uniqued. - static DictionaryAttr getWithSorted(ArrayRef value, - MLIRContext *context); - - ArrayRef getValue() const; - - /// Return the specified attribute if present, null otherwise. - Attribute get(StringRef name) const; - Attribute get(Identifier name) const; - - /// Return the specified named attribute if present, None otherwise. - Optional getNamed(StringRef name) const; - Optional getNamed(Identifier name) const; - - /// Support range iteration. - using iterator = llvm::ArrayRef::iterator; - iterator begin() const; - iterator end() const; - bool empty() const { return size() == 0; } - size_t size() const; - - /// Sorts the NamedAttributes in the array ordered by name as expected by - /// getWithSorted and returns whether the values were sorted. - /// Requires: uniquely named attributes. - static bool sort(ArrayRef values, - SmallVectorImpl &storage); - - /// Sorts the NamedAttributes in the array ordered by name as expected by - /// getWithSorted in place on an array and returns whether the values needed - /// to be sorted. - /// Requires: uniquely named attributes. - static bool sortInPlace(SmallVectorImpl &array); - - /// Returns an entry with a duplicate name in `array`, if it exists, else - /// returns llvm::None. If `isSorted` is true, the array is assumed to be - /// sorted else it will be sorted in place before finding the duplicate entry. - static Optional - findDuplicate(SmallVectorImpl &array, bool isSorted); - -private: - /// Return empty dictionary. - static DictionaryAttr getEmpty(MLIRContext *context); -}; - //===----------------------------------------------------------------------===// // FloatAttr //===----------------------------------------------------------------------===// @@ -267,110 +142,9 @@ }; //===----------------------------------------------------------------------===// -// IntegerSetAttr -//===----------------------------------------------------------------------===// - -class IntegerSetAttr - : public Attribute::AttrBase { -public: - using Base::Base; - using ValueType = IntegerSet; - - static IntegerSetAttr get(IntegerSet value); - - IntegerSet getValue() const; -}; - -//===----------------------------------------------------------------------===// -// OpaqueAttr -//===----------------------------------------------------------------------===// - -/// Opaque attributes represent attributes of non-registered dialects. These are -/// attribute represented in their raw string form, and can only usefully be -/// tested for attribute equality. -class OpaqueAttr : public Attribute::AttrBase { -public: - using Base::Base; - using Base::getChecked; - - /// Get or create a new OpaqueAttr with the provided dialect and string data. - static OpaqueAttr get(Identifier dialect, StringRef attrData, Type type); - - /// Get or create a new OpaqueAttr with the provided dialect and string data. - /// If the given identifier is not a valid namespace for a dialect, then a - /// null attribute is returned. - static OpaqueAttr getChecked(function_ref emitError, - Identifier dialect, StringRef attrData, - Type type); - - /// Returns the dialect namespace of the opaque attribute. - Identifier getDialectNamespace() const; - - /// Returns the raw attribute data of the opaque attribute. - StringRef getAttrData() const; - - /// Verify the construction of an opaque attribute. - static LogicalResult verify(function_ref emitError, - Identifier dialect, StringRef attrData, - Type type); -}; - -//===----------------------------------------------------------------------===// -// StringAttr -//===----------------------------------------------------------------------===// - -class StringAttr : public Attribute::AttrBase { -public: - using Base::Base; - using ValueType = StringRef; - - /// Get an instance of a StringAttr with the given string. - static StringAttr get(MLIRContext *context, StringRef bytes); - - /// Get an instance of a StringAttr with the given string and Type. - static StringAttr get(StringRef bytes, Type type); - - StringRef getValue() const; -}; - -//===----------------------------------------------------------------------===// -// SymbolRefAttr +// FlatSymbolRefAttr //===----------------------------------------------------------------------===// -class FlatSymbolRefAttr; - -/// A symbol reference attribute represents a symbolic reference to another -/// operation. -class SymbolRefAttr - : public Attribute::AttrBase { -public: - using Base::Base; - - /// Construct a symbol reference for the given value name. - static FlatSymbolRefAttr get(MLIRContext *ctx, StringRef value); - - /// Construct a symbol reference for the given value name, and a set of nested - /// references that are further resolve to a nested symbol. - static SymbolRefAttr get(MLIRContext *ctx, StringRef value, - ArrayRef references); - - /// Returns the name of the top level symbol reference, i.e. the root of the - /// reference path. - StringRef getRootReference() const; - - /// Returns the name of the fully resolved symbol, i.e. the leaf of the - /// reference path. - StringRef getLeafReference() const; - - /// Returns the set of nested references representing the path to the symbol - /// nested under the root reference. - ArrayRef getNestedReferences() const; -}; - /// A symbol reference with a reference path containing a single element. This /// is used to refer to an operation within the current symbol table. class FlatSymbolRefAttr : public SymbolRefAttr { @@ -397,35 +171,6 @@ using SymbolRefAttr::getNestedReferences; }; -//===----------------------------------------------------------------------===// -// Type -//===----------------------------------------------------------------------===// - -class TypeAttr : public Attribute::AttrBase { -public: - using Base::Base; - using ValueType = Type; - - static TypeAttr get(Type value); - - Type getValue() const; -}; - -//===----------------------------------------------------------------------===// -// UnitAttr -//===----------------------------------------------------------------------===// - -/// Unit attributes are attributes that hold no specific value and are given -/// meaning by their existence. -class UnitAttr - : public Attribute::AttrBase { -public: - using Base::Base; - - static UnitAttr get(MLIRContext *context); -}; - //===----------------------------------------------------------------------===// // Elements Attributes //===----------------------------------------------------------------------===// @@ -1460,6 +1205,10 @@ } // end namespace mlir. +//===----------------------------------------------------------------------===// +// Attribute Utilities +//===----------------------------------------------------------------------===// + namespace llvm { template <> diff --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/IR/BuiltinAttributes.td @@ -0,0 +1,448 @@ +//===- BuiltinAttributes.td - Builtin attr definitions -----*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Defines the set of builtin MLIR types, or the set of types necessary for the +// validity of and defining the IR. +// +//===----------------------------------------------------------------------===// + +#ifndef BUILTIN_ATTRIBUTES +#define BUILTIN_ATTRIBUTES + +include "mlir/IR/BuiltinDialect.td" + +// TODO: Currently the attributes defined in this file are prefixed with +// `Builtin_`. This is to differentiate the attributes here with the ones in +// OpBase.td. We should remove the definitions in OpBase.td, and repoint users +// to this file instead. + +// Base class for Builtin dialect attributes. +class Builtin_Attr : AttrDef { + let mnemonic = ?; +} + +//===----------------------------------------------------------------------===// +// AffineMapAttr +//===----------------------------------------------------------------------===// + +def Builtin_AffineMapAttr : Builtin_Attr<"AffineMap"> { + let summary = "An Attribute containing an AffineMap object"; + let description = [{ + Syntax: + + ``` + affine-map-attribute ::= `affine_map` `<` affine-map `>` + ``` + + Examples: + + ```mlir + affine_map<(d0) -> (d0)> + affine_map<(d0, d1, d2) -> (d0, d1)> + ``` + }]; + let parameters = (ins "AffineMap":$value); + let builders = [ + AttrBuilderWithInferredContext<(ins "AffineMap":$value), [{ + return $_get(value.getContext(), value); + }]> + ]; + let extraClassDeclaration = "using ValueType = AffineMap;"; + let skipDefaultBuilders = 1; + let typeBuilder = "IndexType::get($_value.getContext())"; +} + +//===----------------------------------------------------------------------===// +// ArrayAttr +//===----------------------------------------------------------------------===// + +def Builtin_ArrayAttr : Builtin_Attr<"Array"> { + let summary = "A collection of other Attribute values"; + let description = [{ + Syntax: + + ``` + array-attribute ::= `[` (attribute-value (`,` attribute-value)*)? `]` + ``` + + An array attribute is an attribute that represents a collection of attribute + values. + + Examples: + + ```mlir + [] + [10, i32] + [affine_map<(d0, d1, d2) -> (d0, d1)>, i32, "string attribute"] + ``` + }]; + let parameters = (ins ArrayRefParameter<"Attribute", "">:$value); + let extraClassDeclaration = [{ + using ValueType = ArrayRef; + + /// Return the element at the given index. + Attribute operator[](unsigned idx) const { + assert(idx < size() && "index out of bounds"); + return getValue()[idx]; + } + + /// Support range iteration. + using iterator = llvm::ArrayRef::iterator; + iterator begin() const { return getValue().begin(); } + iterator end() const { return getValue().end(); } + size_t size() const { return getValue().size(); } + bool empty() const { return size() == 0; } + + private: + /// Class for underlying value iterator support. + template + class attr_value_iterator final + : public llvm::mapped_iterator { + public: + explicit attr_value_iterator(ArrayAttr::iterator it) + : llvm::mapped_iterator( + it, [](Attribute attr) { return attr.cast(); }) {} + AttrTy operator*() const { return (*this->I).template cast(); } + }; + + public: + template + iterator_range> getAsRange() { + return llvm::make_range(attr_value_iterator(begin()), + attr_value_iterator(end())); + } + template + auto getAsValueRange() { + return llvm::map_range(getAsRange(), [](AttrTy attr) { + return static_cast(attr.getValue()); + }); + } + }]; +} + +//===----------------------------------------------------------------------===// +// DictionaryAttr +//===----------------------------------------------------------------------===// + +def Builtin_DictionaryAttr : Builtin_Attr<"Dictionary"> { + let summary = "An dictionary of named Attribute values"; + let description = [{ + Syntax: + + ``` + dictionary-attribute ::= `{` (attribute-entry (`,` attribute-entry)*)? `}` + ``` + + A dictionary attribute is an attribute that represents a sorted collection of + named attribute values. The elements are sorted by name, and each name must be + unique within the collection. + + Examples: + + ```mlir + {} + {attr_name = "string attribute"} + {int_attr = 10, "string attr name" = "string attribute"} + ``` + }]; + let parameters = (ins ArrayRefParameter<"NamedAttribute", "">:$value); + let builders = [ + AttrBuilder<(ins "ArrayRef":$value)> + ]; + let extraClassDeclaration = [{ + using ValueType = ArrayRef; + + /// Construct a dictionary with an array of values that is known to already + /// be sorted by name and uniqued. + static DictionaryAttr getWithSorted(MLIRContext *context, + ArrayRef value); + + /// Return the specified attribute if present, null otherwise. + Attribute get(StringRef name) const; + Attribute get(Identifier name) const; + + /// Return the specified named attribute if present, None otherwise. + Optional getNamed(StringRef name) const; + Optional getNamed(Identifier name) const; + + /// Support range iteration. + using iterator = llvm::ArrayRef::iterator; + iterator begin() const; + iterator end() const; + bool empty() const { return size() == 0; } + size_t size() const; + + /// Sorts the NamedAttributes in the array ordered by name as expected by + /// getWithSorted and returns whether the values were sorted. + /// Requires: uniquely named attributes. + static bool sort(ArrayRef values, + SmallVectorImpl &storage); + + /// Sorts the NamedAttributes in the array ordered by name as expected by + /// getWithSorted in place on an array and returns whether the values needed + /// to be sorted. + /// Requires: uniquely named attributes. + static bool sortInPlace(SmallVectorImpl &array); + + /// Returns an entry with a duplicate name in `array`, if it exists, else + /// returns llvm::None. If `isSorted` is true, the array is assumed to be + /// sorted else it will be sorted in place before finding the duplicate entry. + static Optional + findDuplicate(SmallVectorImpl &array, bool isSorted); + + private: + /// Return empty dictionary. + static DictionaryAttr getEmpty(MLIRContext *context); + + /// Return empty dictionary. This is a special variant of the above method + /// that is used by the MLIRContext to cache the empty dictionary instance. + static DictionaryAttr getEmptyUnchecked(MLIRContext *context); + + /// Allow access to `getEmptyUnchecked`. + friend MLIRContext; + + public: + }]; + let skipDefaultBuilders = 1; +} + +//===----------------------------------------------------------------------===// +// IntegerSetAttr +//===----------------------------------------------------------------------===// + +def Builtin_IntegerSetAttr : Builtin_Attr<"IntegerSet"> { + let summary = "An Attribute containing an IntegerSet object"; + let description = [{ + Syntax: + + ``` + integer-set-attribute ::= `affine_set` `<` integer-set `>` + ``` + + Examples: + + ```mlir + affine_set<(d0) : (d0 - 2 >= 0)> + ``` + }]; + let parameters = (ins "IntegerSet":$value); + let builders = [ + AttrBuilderWithInferredContext<(ins "IntegerSet":$value), [{ + return $_get(value.getContext(), value); + }]> + ]; + let extraClassDeclaration = "using ValueType = IntegerSet;"; + let skipDefaultBuilders = 1; +} + +//===----------------------------------------------------------------------===// +// OpaqueAttr +//===----------------------------------------------------------------------===// + +def Builtin_OpaqueAttr : Builtin_Attr<"Opaque"> { + let summary = "An opaque representation of another Attribute"; + let description = [{ + Syntax: + + ``` + opaque-attribute ::= dialect-namespace `<` attr-data `>` + ``` + + Opaque attributes represent attributes of non-registered dialects. These are + attribute represented in their raw string form, and can only usefully be + tested for attribute equality. + + Examples: + + ```mlir + #dialect<"opaque attribute data"> + ``` + }]; + let parameters = (ins "Identifier":$dialectNamespace, + StringRefParameter<"">:$attrData, + AttributeSelfTypeParameter<"">:$type); + let builders = [ + AttrBuilderWithInferredContext<(ins "Identifier":$dialect, + "StringRef":$attrData, + "Type":$type), [{ + return $_get(dialect.getContext(), dialect, attrData, type); + }]> + ]; + bit genVerifyDecl = 1; + // let skipDefaultBuilders = 1; +} + +//===----------------------------------------------------------------------===// +// StringAttr +//===----------------------------------------------------------------------===// + +def Builtin_StringAttr : Builtin_Attr<"String"> { + let summary = "An Attribute containing a string"; + let description = [{ + Syntax: + + ``` + string-attribute ::= string-literal (`:` type)? + ``` + + A string attribute is an attribute that represents a string literal value. + + Examples: + + ```mlir + "An important string" + "string with a type" : !dialect.string + ``` + }]; + let parameters = (ins StringRefParameter<"">:$value, + AttributeSelfTypeParameter<"">:$type); + let builders = [ + AttrBuilderWithInferredContext<(ins "StringRef":$bytes, + "Type":$type), [{ + return $_get(type.getContext(), bytes, type); + }]>, + AttrBuilder<(ins "StringRef":$bytes), [{ + return $_get($_ctxt, bytes, NoneType::get($_ctxt)); + }]> + ]; + let extraClassDeclaration = "using ValueType = StringRef;"; + let skipDefaultBuilders = 1; +} + +//===----------------------------------------------------------------------===// +// SymbolRefAttr +//===----------------------------------------------------------------------===// + +def Builtin_SymbolRefAttr : Builtin_Attr<"SymbolRef"> { + let summary = "An Attribute containing a symbolic reference to an Operation"; + let description = [{ + Syntax: + + ``` + symbol-ref-attribute ::= symbol-ref-id (`::` symbol-ref-id)* + ``` + + A symbol reference attribute is a literal attribute that represents a named + reference to an operation that is nested within an operation with the + `OpTrait::SymbolTable` trait. As such, this reference is given meaning by + the nearest parent operation containing the `OpTrait::SymbolTable` trait. It + may optionally contain a set of nested references that further resolve to a + symbol nested within a different symbol table. + + This attribute can only be held internally by + [array attributes](#array-attribute) and + [dictionary attributes](#dictionary-attribute)(including the top-level + operation attribute dictionary), i.e. no other attribute kinds such as + Locations or extended attribute kinds. + + **Rationale:** Identifying accesses to global data is critical to + enabling efficient multi-threaded compilation. Restricting global + data access to occur through symbols and limiting the places that can + legally hold a symbol reference simplifies reasoning about these data + accesses. + + See [`Symbols And SymbolTables`](SymbolsAndSymbolTables.md) for more + information. + + Examples: + + ```mlir + @flat_reference + @parent_reference::@nested_reference + ``` + }]; + let parameters = (ins + StringRefParameter<"">:$rootReference, + ArrayRefParameter<"FlatSymbolRefAttr", "">:$nestedReferences + ); + let extraClassDeclaration = [{ + static FlatSymbolRefAttr get(MLIRContext *ctx, StringRef value); + + /// Returns the name of the fully resolved symbol, i.e. the leaf of the + /// reference path. + StringRef getLeafReference() const; + }]; +} + +//===----------------------------------------------------------------------===// +// TypeAttr +//===----------------------------------------------------------------------===// + +def Builtin_TypeAttr : Builtin_Attr<"Type"> { + let summary = "An Attribute containing a Type"; + let description = [{ + Syntax: + + ``` + type-attribute ::= type + ``` + + A type attribute is an attribute that represents a + [type object](#type-system). + + Examples: + + ```mlir + i32 + !dialect.type + ``` + }]; + let parameters = (ins "Type":$value); + let builders = [ + AttrBuilderWithInferredContext<(ins "Type":$type), [{ + return $_get(type.getContext(), type); + }]>, + ]; + let extraClassDeclaration = "using ValueType = Type;"; + let skipDefaultBuilders = 1; +} + +//===----------------------------------------------------------------------===// +// UnitAttr +//===----------------------------------------------------------------------===// + +def Builtin_UnitAttr : Builtin_Attr<"Unit"> { + let summary = "An Attribute value of `unit` type"; + let description = [{ + Syntax: + + ``` + unit-attribute ::= `unit` + ``` + + A unit attribute is an attribute that represents a value of `unit` type. The + `unit` type allows only one value forming a singleton set. This attribute + value is used to represent attributes that only have meaning from their + existence. + + One example of such an attribute could be the `swift.self` attribute. This + attribute indicates that a function parameter is the self/context parameter. + It could be represented as a [boolean attribute](#boolean-attribute)(true or + false), but a value of false doesn't really bring any value. The parameter + either is the self/context or it isn't. + + + Examples: + + ```mlir + // A unit attribute defined with the `unit` value specifier. + func @verbose_form() attributes {dialectName.unitAttr = unit} + + // A unit attribute in an attribute dictionary can also be defined without + // the value specifier. + func @simple_form() attributes {dialectName.unitAttr} + ``` + }]; + let extraClassDeclaration = [{ + static UnitAttr get(MLIRContext *context); + }]; +} + +#endif // BUILTIN_ATTRIBUTES diff --git a/mlir/include/mlir/IR/CMakeLists.txt b/mlir/include/mlir/IR/CMakeLists.txt --- a/mlir/include/mlir/IR/CMakeLists.txt +++ b/mlir/include/mlir/IR/CMakeLists.txt @@ -2,6 +2,11 @@ add_mlir_interface(SymbolInterfaces) add_mlir_interface(RegionKindInterface) +set(LLVM_TARGET_DEFINITIONS BuiltinAttributes.td) +mlir_tablegen(BuiltinAttributes.h.inc -gen-attrdef-decls) +mlir_tablegen(BuiltinAttributes.cpp.inc -gen-attrdef-defs) +add_public_tablegen_target(MLIRBuiltinAttributesIncGen) + set(LLVM_TARGET_DEFINITIONS BuiltinDialect.td) mlir_tablegen(BuiltinDialect.h.inc -gen-dialect-decls) add_public_tablegen_target(MLIRBuiltinDialectIncGen) diff --git a/mlir/lib/IR/AttributeDetail.h b/mlir/lib/IR/AttributeDetail.h --- a/mlir/lib/IR/AttributeDetail.h +++ b/mlir/lib/IR/AttributeDetail.h @@ -26,91 +26,6 @@ namespace mlir { namespace detail { -// An attribute representing a reference to an affine map. -struct AffineMapAttributeStorage : public AttributeStorage { - using KeyTy = AffineMap; - - AffineMapAttributeStorage(AffineMap value) - : AttributeStorage(IndexType::get(value.getContext())), value(value) {} - - /// Key equality function. - bool operator==(const KeyTy &key) const { return key == value; } - - /// Construct a new storage instance. - static AffineMapAttributeStorage * - construct(AttributeStorageAllocator &allocator, KeyTy key) { - return new (allocator.allocate()) - AffineMapAttributeStorage(key); - } - - AffineMap value; -}; - -/// An attribute representing an array of other attributes. -struct ArrayAttributeStorage : public AttributeStorage { - using KeyTy = ArrayRef; - - ArrayAttributeStorage(ArrayRef value) : value(value) {} - - /// Key equality function. - bool operator==(const KeyTy &key) const { return key == value; } - - /// Construct a new storage instance. - static ArrayAttributeStorage *construct(AttributeStorageAllocator &allocator, - const KeyTy &key) { - return new (allocator.allocate()) - ArrayAttributeStorage(allocator.copyInto(key)); - } - - ArrayRef value; -}; - -/// An attribute representing a dictionary of sorted named attributes. -struct DictionaryAttributeStorage final - : public AttributeStorage, - private llvm::TrailingObjects { - using KeyTy = ArrayRef; - - /// Given a list of NamedAttribute's, canonicalize the list (sorting - /// by name) and return the unique'd result. - static DictionaryAttributeStorage *get(ArrayRef attrs); - - /// Key equality function. - bool operator==(const KeyTy &key) const { return key == getElements(); } - - /// Construct a new storage instance. - static DictionaryAttributeStorage * - construct(AttributeStorageAllocator &allocator, const KeyTy &key) { - auto size = DictionaryAttributeStorage::totalSizeToAlloc( - key.size()); - auto rawMem = allocator.allocate(size, alignof(DictionaryAttributeStorage)); - - // Initialize the storage and trailing attribute list. - auto result = ::new (rawMem) DictionaryAttributeStorage(key.size()); - std::uninitialized_copy(key.begin(), key.end(), - result->getTrailingObjects()); - return result; - } - - /// Return the elements of this dictionary attribute. - ArrayRef getElements() const { - return {getTrailingObjects(), numElements}; - } - -private: - friend class llvm::TrailingObjects; - - // This is used by the llvm::TrailingObjects base class. - size_t numTrailingObjects(OverloadToken) const { - return numElements; - } - DictionaryAttributeStorage(unsigned numElements) : numElements(numElements) {} - - /// This is the number of attributes. - const unsigned numElements; -}; /// An attribute representing a floating point value. struct FloatAttributeStorage final @@ -219,131 +134,6 @@ size_t numObjects; }; -// An attribute representing a reference to an integer set. -struct IntegerSetAttributeStorage : public AttributeStorage { - using KeyTy = IntegerSet; - - IntegerSetAttributeStorage(IntegerSet value) : value(value) {} - - /// Key equality function. - bool operator==(const KeyTy &key) const { return key == value; } - - /// Construct a new storage instance. - static IntegerSetAttributeStorage * - construct(AttributeStorageAllocator &allocator, KeyTy key) { - return new (allocator.allocate()) - IntegerSetAttributeStorage(key); - } - - IntegerSet value; -}; - -/// Opaque Attribute Storage and Uniquing. -struct OpaqueAttributeStorage : public AttributeStorage { - OpaqueAttributeStorage(Identifier dialectNamespace, StringRef attrData, - Type type) - : AttributeStorage(type), dialectNamespace(dialectNamespace), - attrData(attrData) {} - - /// The hash key used for uniquing. - using KeyTy = std::tuple; - bool operator==(const KeyTy &key) const { - return key == KeyTy(dialectNamespace, attrData, getType()); - } - - static OpaqueAttributeStorage *construct(AttributeStorageAllocator &allocator, - const KeyTy &key) { - return new (allocator.allocate()) - OpaqueAttributeStorage(std::get<0>(key), - allocator.copyInto(std::get<1>(key)), - std::get<2>(key)); - } - - // The dialect namespace. - Identifier dialectNamespace; - - // The parser attribute data for this opaque attribute. - StringRef attrData; -}; - -/// An attribute representing a string value. -struct StringAttributeStorage : public AttributeStorage { - using KeyTy = std::pair; - - StringAttributeStorage(StringRef value, Type type) - : AttributeStorage(type), value(value) {} - - /// Key equality function. - bool operator==(const KeyTy &key) const { - return key == KeyTy(value, getType()); - } - - /// Construct a new storage instance. - static StringAttributeStorage *construct(AttributeStorageAllocator &allocator, - const KeyTy &key) { - return new (allocator.allocate()) - StringAttributeStorage(allocator.copyInto(key.first), key.second); - } - - StringRef value; -}; - -/// An attribute representing a symbol reference. -struct SymbolRefAttributeStorage final - : public AttributeStorage, - public llvm::TrailingObjects { - using KeyTy = std::pair>; - - SymbolRefAttributeStorage(StringRef value, size_t numNestedRefs) - : value(value), numNestedRefs(numNestedRefs) {} - - /// Key equality function. - bool operator==(const KeyTy &key) const { - return key == KeyTy(value, getNestedRefs()); - } - - /// Construct a new storage instance. - static SymbolRefAttributeStorage * - construct(AttributeStorageAllocator &allocator, const KeyTy &key) { - auto size = SymbolRefAttributeStorage::totalSizeToAlloc( - key.second.size()); - auto rawMem = allocator.allocate(size, alignof(SymbolRefAttributeStorage)); - auto result = ::new (rawMem) SymbolRefAttributeStorage( - allocator.copyInto(key.first), key.second.size()); - std::uninitialized_copy(key.second.begin(), key.second.end(), - result->getTrailingObjects()); - return result; - } - - /// Returns the set of nested references. - ArrayRef getNestedRefs() const { - return {getTrailingObjects(), numNestedRefs}; - } - - StringRef value; - size_t numNestedRefs; -}; - -/// An attribute representing a reference to a type. -struct TypeAttributeStorage : public AttributeStorage { - using KeyTy = Type; - - TypeAttributeStorage(Type value) : value(value) {} - - /// Key equality function. - bool operator==(const KeyTy &key) const { return key == value; } - - /// Construct a new storage instance. - static TypeAttributeStorage *construct(AttributeStorageAllocator &allocator, - KeyTy key) { - return new (allocator.allocate()) - TypeAttributeStorage(key); - } - - Type value; -}; - //===----------------------------------------------------------------------===// // Elements Attributes //===----------------------------------------------------------------------===// diff --git a/mlir/lib/IR/BuiltinAttributes.cpp b/mlir/lib/IR/BuiltinAttributes.cpp --- a/mlir/lib/IR/BuiltinAttributes.cpp +++ b/mlir/lib/IR/BuiltinAttributes.cpp @@ -22,29 +22,11 @@ using namespace mlir::detail; //===----------------------------------------------------------------------===// -// AffineMapAttr +/// Tablegen Attribute Definitions //===----------------------------------------------------------------------===// -AffineMapAttr AffineMapAttr::get(AffineMap value) { - return Base::get(value.getContext(), value); -} - -AffineMap AffineMapAttr::getValue() const { return getImpl()->value; } - -//===----------------------------------------------------------------------===// -// ArrayAttr -//===----------------------------------------------------------------------===// - -ArrayAttr ArrayAttr::get(MLIRContext *context, ArrayRef value) { - return Base::get(context, value); -} - -ArrayRef ArrayAttr::getValue() const { return getImpl()->value; } - -Attribute ArrayAttr::operator[](unsigned idx) const { - assert(idx < size() && "index out of bounds"); - return getValue()[idx]; -} +#define GET_ATTRDEF_CLASSES +#include "mlir/IR/BuiltinAttributes.cpp.inc" //===----------------------------------------------------------------------===// // DictionaryAttr @@ -152,8 +134,8 @@ } /// Construct a dictionary with an array of values that is known to already be /// sorted by name and uniqued. -DictionaryAttr DictionaryAttr::getWithSorted(ArrayRef value, - MLIRContext *context) { +DictionaryAttr DictionaryAttr::getWithSorted(MLIRContext *context, + ArrayRef value) { if (value.empty()) return DictionaryAttr::getEmpty(context); // Ensure that the attribute elements are unique and sorted. @@ -167,10 +149,6 @@ return Base::get(context, value); } -ArrayRef DictionaryAttr::getValue() const { - return getImpl()->getElements(); -} - /// Return the specified attribute if present, null otherwise. Attribute DictionaryAttr::get(StringRef name) const { Optional attr = getNamed(name); @@ -203,6 +181,10 @@ } size_t DictionaryAttr::size() const { return getValue().size(); } +DictionaryAttr DictionaryAttr::getEmptyUnchecked(MLIRContext *context) { + return Base::get(context, ArrayRef()); +} + //===----------------------------------------------------------------------===// // FloatAttr //===----------------------------------------------------------------------===// @@ -272,25 +254,14 @@ //===----------------------------------------------------------------------===// FlatSymbolRefAttr SymbolRefAttr::get(MLIRContext *ctx, StringRef value) { - return Base::get(ctx, value, llvm::None).cast(); + return get(ctx, value, llvm::None).cast(); } -SymbolRefAttr SymbolRefAttr::get(MLIRContext *ctx, StringRef value, - ArrayRef nestedReferences) { - return Base::get(ctx, value, nestedReferences); -} - -StringRef SymbolRefAttr::getRootReference() const { return getImpl()->value; } - StringRef SymbolRefAttr::getLeafReference() const { ArrayRef nestedRefs = getNestedReferences(); return nestedRefs.empty() ? getRootReference() : nestedRefs.back().getValue(); } -ArrayRef SymbolRefAttr::getNestedReferences() const { - return getImpl()->getNestedRefs(); -} - //===----------------------------------------------------------------------===// // IntegerAttr //===----------------------------------------------------------------------===// @@ -368,40 +339,10 @@ return intAttr && intAttr.getType().isSignlessInteger(1); } -//===----------------------------------------------------------------------===// -// IntegerSetAttr -//===----------------------------------------------------------------------===// - -IntegerSetAttr IntegerSetAttr::get(IntegerSet value) { - return Base::get(value.getConstraint(0).getContext(), value); -} - -IntegerSet IntegerSetAttr::getValue() const { return getImpl()->value; } - //===----------------------------------------------------------------------===// // OpaqueAttr //===----------------------------------------------------------------------===// -OpaqueAttr OpaqueAttr::get(Identifier dialect, StringRef attrData, Type type) { - return Base::get(dialect.getContext(), dialect, attrData, type); -} - -OpaqueAttr OpaqueAttr::getChecked(function_ref emitError, - Identifier dialect, StringRef attrData, - Type type) { - return Base::getChecked(emitError, dialect.getContext(), dialect, attrData, - type); -} - -/// Returns the dialect namespace of the opaque attribute. -Identifier OpaqueAttr::getDialectNamespace() const { - return getImpl()->dialectNamespace; -} - -/// Returns the raw attribute data of the opaque attribute. -StringRef OpaqueAttr::getAttrData() const { return getImpl()->attrData; } - -/// Verify the construction of an opaque attribute. LogicalResult OpaqueAttr::verify(function_ref emitError, Identifier dialect, StringRef attrData, Type type) { @@ -410,31 +351,6 @@ return success(); } -//===----------------------------------------------------------------------===// -// StringAttr -//===----------------------------------------------------------------------===// - -StringAttr StringAttr::get(MLIRContext *context, StringRef bytes) { - return get(bytes, NoneType::get(context)); -} - -/// Get an instance of a StringAttr with the given string and Type. -StringAttr StringAttr::get(StringRef bytes, Type type) { - return Base::get(type.getContext(), bytes, type); -} - -StringRef StringAttr::getValue() const { return getImpl()->value; } - -//===----------------------------------------------------------------------===// -// TypeAttr -//===----------------------------------------------------------------------===// - -TypeAttr TypeAttr::get(Type value) { - return Base::get(value.getContext(), value); -} - -Type TypeAttr::getValue() const { return getImpl()->value; } - //===----------------------------------------------------------------------===// // ElementsAttr //===----------------------------------------------------------------------===// diff --git a/mlir/lib/IR/CMakeLists.txt b/mlir/lib/IR/CMakeLists.txt --- a/mlir/lib/IR/CMakeLists.txt +++ b/mlir/lib/IR/CMakeLists.txt @@ -33,6 +33,7 @@ ${MLIR_MAIN_INCLUDE_DIR}/mlir/IR DEPENDS + MLIRBuiltinAttributesIncGen MLIRBuiltinDialectIncGen MLIRBuiltinOpsIncGen MLIRBuiltinTypesIncGen diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp --- a/mlir/lib/IR/MLIRContext.cpp +++ b/mlir/lib/IR/MLIRContext.cpp @@ -403,8 +403,7 @@ /// Unknown Location Attribute. impl->unknownLocAttr = AttributeUniquer::get(this); /// The empty dictionary attribute. - impl->emptyDictionaryAttr = - AttributeUniquer::get(this, ArrayRef()); + impl->emptyDictionaryAttr = DictionaryAttr::getEmptyUnchecked(this); // Register the affine storage objects with the uniquer. impl->affineUniquer diff --git a/mlir/lib/IR/OperationSupport.cpp b/mlir/lib/IR/OperationSupport.cpp --- a/mlir/lib/IR/OperationSupport.cpp +++ b/mlir/lib/IR/OperationSupport.cpp @@ -54,7 +54,7 @@ dictionarySorted.setPointerAndInt(nullptr, true); } if (!dictionarySorted.getPointer()) - dictionarySorted.setPointer(DictionaryAttr::getWithSorted(attrs, context)); + dictionarySorted.setPointer(DictionaryAttr::getWithSorted(context, attrs)); return dictionarySorted.getPointer().cast(); }