[mlir][IR][NFC] Move a majority of the builtin attributes to ODS

Now that attributes can be generated using ODS, we can move the builtin attributes as well. This revision removes a majority of the builtin attributes with a few left for followup revisions. The attributes moved to ODS in this revision are: AffineMapAttr, ArrayAttr, DictionaryAttr, IntegerSetAttr, StringAttr, SymbolRefAttr, TypeAttr, and UnitAttr.

Differential Revision: https://reviews.llvm.org/D97591
This commit is contained in:
River Riddle 2021-03-04 12:37:32 -08:00
parent 1447ec5182
commit 2f37cdd569
8 changed files with 485 additions and 577 deletions

View File

@ -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 OpaqueElementsAttributeStorage;
struct SparseElementsAttributeStorage;
} // namespace detail
//===----------------------------------------------------------------------===//
// AffineMapAttr
//===----------------------------------------------------------------------===//
class AffineMapAttr
: public Attribute::AttrBase<AffineMapAttr, Attribute,
detail::AffineMapAttributeStorage> {
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<ArrayAttr, Attribute,
detail::ArrayAttributeStorage> {
public:
using Base::Base;
using ValueType = ArrayRef<Attribute>;
static ArrayAttr get(MLIRContext *context, ArrayRef<Attribute> value);
ArrayRef<Attribute> getValue() const;
Attribute operator[](unsigned idx) const;
/// Support range iteration.
using iterator = llvm::ArrayRef<Attribute>::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 <typename AttrTy>
class attr_value_iterator final
: public llvm::mapped_iterator<ArrayAttr::iterator,
AttrTy (*)(Attribute)> {
public:
explicit attr_value_iterator(ArrayAttr::iterator it)
: llvm::mapped_iterator<ArrayAttr::iterator, AttrTy (*)(Attribute)>(
it, [](Attribute attr) { return attr.cast<AttrTy>(); }) {}
AttrTy operator*() const { return (*this->I).template cast<AttrTy>(); }
};
public:
template <typename AttrTy>
iterator_range<attr_value_iterator<AttrTy>> getAsRange() {
return llvm::make_range(attr_value_iterator<AttrTy>(begin()),
attr_value_iterator<AttrTy>(end()));
}
template <typename AttrTy, typename UnderlyingTy = typename AttrTy::ValueType>
auto getAsValueRange() {
return llvm::map_range(getAsRange<AttrTy>(), [](AttrTy attr) {
return static_cast<UnderlyingTy>(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<DictionaryAttr, Attribute,
detail::DictionaryAttributeStorage> {
public:
using Base::Base;
using ValueType = ArrayRef<NamedAttribute>;
/// 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<NamedAttribute> value);
/// Construct a dictionary with an array of values that is known to already be
/// sorted by name and uniqued.
static DictionaryAttr getWithSorted(ArrayRef<NamedAttribute> value,
MLIRContext *context);
ArrayRef<NamedAttribute> 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<NamedAttribute> getNamed(StringRef name) const;
Optional<NamedAttribute> getNamed(Identifier name) const;
/// Support range iteration.
using iterator = llvm::ArrayRef<NamedAttribute>::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<NamedAttribute> values,
SmallVectorImpl<NamedAttribute> &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<NamedAttribute> &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<NamedAttribute>
findDuplicate(SmallVectorImpl<NamedAttribute> &array, bool isSorted);
private:
/// Return empty dictionary.
static DictionaryAttr getEmpty(MLIRContext *context);
};
//===----------------------------------------------------------------------===//
// FloatAttr
//===----------------------------------------------------------------------===//
@ -267,110 +142,9 @@ public:
};
//===----------------------------------------------------------------------===//
// IntegerSetAttr
// FlatSymbolRefAttr
//===----------------------------------------------------------------------===//
class IntegerSetAttr
: public Attribute::AttrBase<IntegerSetAttr, Attribute,
detail::IntegerSetAttributeStorage> {
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<OpaqueAttr, Attribute,
detail::OpaqueAttributeStorage> {
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<InFlightDiagnostic()> 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<InFlightDiagnostic()> emitError,
Identifier dialect, StringRef attrData,
Type type);
};
//===----------------------------------------------------------------------===//
// StringAttr
//===----------------------------------------------------------------------===//
class StringAttr : public Attribute::AttrBase<StringAttr, Attribute,
detail::StringAttributeStorage> {
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
//===----------------------------------------------------------------------===//
class FlatSymbolRefAttr;
/// A symbol reference attribute represents a symbolic reference to another
/// operation.
class SymbolRefAttr
: public Attribute::AttrBase<SymbolRefAttr, Attribute,
detail::SymbolRefAttributeStorage> {
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<FlatSymbolRefAttr> 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<FlatSymbolRefAttr> 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 @@ private:
using SymbolRefAttr::getNestedReferences;
};
//===----------------------------------------------------------------------===//
// Type
//===----------------------------------------------------------------------===//
class TypeAttr : public Attribute::AttrBase<TypeAttr, Attribute,
detail::TypeAttributeStorage> {
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<UnitAttr, Attribute, AttributeStorage> {
public:
using Base::Base;
static UnitAttr get(MLIRContext *context);
};
//===----------------------------------------------------------------------===//
// Elements Attributes
//===----------------------------------------------------------------------===//
@ -1460,6 +1205,10 @@ auto ElementsAttr::getValues() const -> iterator_range<T> {
} // end namespace mlir.
//===----------------------------------------------------------------------===//
// Attribute Utilities
//===----------------------------------------------------------------------===//
namespace llvm {
template <>

View File

@ -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<string name> : AttrDef<Builtin_Dialect, name> {
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<Attribute>;
/// 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<Attribute>::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 <typename AttrTy>
class attr_value_iterator final
: public llvm::mapped_iterator<ArrayAttr::iterator,
AttrTy (*)(Attribute)> {
public:
explicit attr_value_iterator(ArrayAttr::iterator it)
: llvm::mapped_iterator<ArrayAttr::iterator, AttrTy (*)(Attribute)>(
it, [](Attribute attr) { return attr.cast<AttrTy>(); }) {}
AttrTy operator*() const { return (*this->I).template cast<AttrTy>(); }
};
public:
template <typename AttrTy>
iterator_range<attr_value_iterator<AttrTy>> getAsRange() {
return llvm::make_range(attr_value_iterator<AttrTy>(begin()),
attr_value_iterator<AttrTy>(end()));
}
template <typename AttrTy,
typename UnderlyingTy = typename AttrTy::ValueType>
auto getAsValueRange() {
return llvm::map_range(getAsRange<AttrTy>(), [](AttrTy attr) {
return static_cast<UnderlyingTy>(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<NamedAttribute>":$value)>
];
let extraClassDeclaration = [{
using ValueType = ArrayRef<NamedAttribute>;
/// 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<NamedAttribute> 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<NamedAttribute> getNamed(StringRef name) const;
Optional<NamedAttribute> getNamed(Identifier name) const;
/// Support range iteration.
using iterator = llvm::ArrayRef<NamedAttribute>::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<NamedAttribute> values,
SmallVectorImpl<NamedAttribute> &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<NamedAttribute> &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<NamedAttribute>
findDuplicate(SmallVectorImpl<NamedAttribute> &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

View File

@ -2,6 +2,11 @@ add_mlir_interface(OpAsmInterface)
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)

View File

@ -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>())
AffineMapAttributeStorage(key);
}
AffineMap value;
};
/// An attribute representing an array of other attributes.
struct ArrayAttributeStorage : public AttributeStorage {
using KeyTy = ArrayRef<Attribute>;
ArrayAttributeStorage(ArrayRef<Attribute> 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>())
ArrayAttributeStorage(allocator.copyInto(key));
}
ArrayRef<Attribute> value;
};
/// An attribute representing a dictionary of sorted named attributes.
struct DictionaryAttributeStorage final
: public AttributeStorage,
private llvm::TrailingObjects<DictionaryAttributeStorage,
NamedAttribute> {
using KeyTy = ArrayRef<NamedAttribute>;
/// Given a list of NamedAttribute's, canonicalize the list (sorting
/// by name) and return the unique'd result.
static DictionaryAttributeStorage *get(ArrayRef<NamedAttribute> 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<NamedAttribute>(
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<NamedAttribute>());
return result;
}
/// Return the elements of this dictionary attribute.
ArrayRef<NamedAttribute> getElements() const {
return {getTrailingObjects<NamedAttribute>(), numElements};
}
private:
friend class llvm::TrailingObjects<DictionaryAttributeStorage,
NamedAttribute>;
// This is used by the llvm::TrailingObjects base class.
size_t numTrailingObjects(OverloadToken<NamedAttribute>) 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 @@ struct IntegerAttributeStorage final
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>())
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<Identifier, StringRef, Type>;
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>())
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<StringRef, Type>;
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>())
StringAttributeStorage(allocator.copyInto(key.first), key.second);
}
StringRef value;
};
/// An attribute representing a symbol reference.
struct SymbolRefAttributeStorage final
: public AttributeStorage,
public llvm::TrailingObjects<SymbolRefAttributeStorage,
FlatSymbolRefAttr> {
using KeyTy = std::pair<StringRef, ArrayRef<FlatSymbolRefAttr>>;
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<FlatSymbolRefAttr>(
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<FlatSymbolRefAttr>());
return result;
}
/// Returns the set of nested references.
ArrayRef<FlatSymbolRefAttr> getNestedRefs() const {
return {getTrailingObjects<FlatSymbolRefAttr>(), 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>())
TypeAttributeStorage(key);
}
Type value;
};
//===----------------------------------------------------------------------===//
// Elements Attributes
//===----------------------------------------------------------------------===//

View File

@ -22,29 +22,11 @@ using namespace mlir;
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<Attribute> value) {
return Base::get(context, value);
}
ArrayRef<Attribute> 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 @@ DictionaryAttr DictionaryAttr::get(MLIRContext *context,
}
/// Construct a dictionary with an array of values that is known to already be
/// sorted by name and uniqued.
DictionaryAttr DictionaryAttr::getWithSorted(ArrayRef<NamedAttribute> value,
MLIRContext *context) {
DictionaryAttr DictionaryAttr::getWithSorted(MLIRContext *context,
ArrayRef<NamedAttribute> value) {
if (value.empty())
return DictionaryAttr::getEmpty(context);
// Ensure that the attribute elements are unique and sorted.
@ -167,10 +149,6 @@ DictionaryAttr DictionaryAttr::getWithSorted(ArrayRef<NamedAttribute> value,
return Base::get(context, value);
}
ArrayRef<NamedAttribute> DictionaryAttr::getValue() const {
return getImpl()->getElements();
}
/// Return the specified attribute if present, null otherwise.
Attribute DictionaryAttr::get(StringRef name) const {
Optional<NamedAttribute> attr = getNamed(name);
@ -203,6 +181,10 @@ DictionaryAttr::iterator DictionaryAttr::end() const {
}
size_t DictionaryAttr::size() const { return getValue().size(); }
DictionaryAttr DictionaryAttr::getEmptyUnchecked(MLIRContext *context) {
return Base::get(context, ArrayRef<NamedAttribute>());
}
//===----------------------------------------------------------------------===//
// FloatAttr
//===----------------------------------------------------------------------===//
@ -272,25 +254,14 @@ LogicalResult FloatAttr::verify(function_ref<InFlightDiagnostic()> emitError,
//===----------------------------------------------------------------------===//
FlatSymbolRefAttr SymbolRefAttr::get(MLIRContext *ctx, StringRef value) {
return Base::get(ctx, value, llvm::None).cast<FlatSymbolRefAttr>();
return get(ctx, value, llvm::None).cast<FlatSymbolRefAttr>();
}
SymbolRefAttr SymbolRefAttr::get(MLIRContext *ctx, StringRef value,
ArrayRef<FlatSymbolRefAttr> nestedReferences) {
return Base::get(ctx, value, nestedReferences);
}
StringRef SymbolRefAttr::getRootReference() const { return getImpl()->value; }
StringRef SymbolRefAttr::getLeafReference() const {
ArrayRef<FlatSymbolRefAttr> nestedRefs = getNestedReferences();
return nestedRefs.empty() ? getRootReference() : nestedRefs.back().getValue();
}
ArrayRef<FlatSymbolRefAttr> SymbolRefAttr::getNestedReferences() const {
return getImpl()->getNestedRefs();
}
//===----------------------------------------------------------------------===//
// IntegerAttr
//===----------------------------------------------------------------------===//
@ -368,40 +339,10 @@ bool BoolAttr::classof(Attribute attr) {
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<InFlightDiagnostic()> 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<InFlightDiagnostic()> emitError,
Identifier dialect, StringRef attrData,
Type type) {
@ -410,31 +351,6 @@ LogicalResult OpaqueAttr::verify(function_ref<InFlightDiagnostic()> emitError,
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
//===----------------------------------------------------------------------===//

View File

@ -33,6 +33,7 @@ add_mlir_library(MLIRIR
${MLIR_MAIN_INCLUDE_DIR}/mlir/IR
DEPENDS
MLIRBuiltinAttributesIncGen
MLIRBuiltinDialectIncGen
MLIRBuiltinOpsIncGen
MLIRBuiltinTypesIncGen

View File

@ -403,8 +403,7 @@ MLIRContext::MLIRContext(const DialectRegistry &registry)
/// Unknown Location Attribute.
impl->unknownLocAttr = AttributeUniquer::get<UnknownLoc>(this);
/// The empty dictionary attribute.
impl->emptyDictionaryAttr =
AttributeUniquer::get<DictionaryAttr>(this, ArrayRef<NamedAttribute>());
impl->emptyDictionaryAttr = DictionaryAttr::getEmptyUnchecked(this);
// Register the affine storage objects with the uniquer.
impl->affineUniquer

View File

@ -54,7 +54,7 @@ DictionaryAttr NamedAttrList::getDictionary(MLIRContext *context) const {
dictionarySorted.setPointerAndInt(nullptr, true);
}
if (!dictionarySorted.getPointer())
dictionarySorted.setPointer(DictionaryAttr::getWithSorted(attrs, context));
dictionarySorted.setPointer(DictionaryAttr::getWithSorted(context, attrs));
return dictionarySorted.getPointer().cast<DictionaryAttr>();
}