[Mlir-commits] [mlir] caa7038 - [mlir][IR] Move the remaining builtin attributes to ODS.
River Riddle
llvmlistbot at llvm.org
Tue Mar 16 16:39:23 PDT 2021
Author: River Riddle
Date: 2021-03-16T16:31:53-07:00
New Revision: caa7038a89328bc1e7d1df80f9fcede12dcb7df5
URL: https://github.com/llvm/llvm-project/commit/caa7038a89328bc1e7d1df80f9fcede12dcb7df5
DIFF: https://github.com/llvm/llvm-project/commit/caa7038a89328bc1e7d1df80f9fcede12dcb7df5.diff
LOG: [mlir][IR] Move the remaining builtin attributes to ODS.
With this revision, all builtin attributes and types will have been moved to the ODS generator.
Differential Revision: https://reviews.llvm.org/D98474
Added:
Modified:
mlir/include/mlir/IR/BuiltinAttributes.h
mlir/include/mlir/IR/BuiltinAttributes.td
mlir/include/mlir/IR/OpBase.td
mlir/lib/IR/AsmPrinter.cpp
mlir/lib/IR/AttributeDetail.h
mlir/lib/IR/BuiltinAttributes.cpp
mlir/lib/IR/MLIRContext.cpp
mlir/lib/Parser/AttributeParser.cpp
mlir/lib/TableGen/AttrOrTypeDef.cpp
mlir/test/CAPI/ir.c
mlir/test/IR/invalid.mlir
mlir/test/IR/pretty-attributes.mlir
mlir/test/mlir-tblgen/attrdefs.td
mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
Removed:
################################################################################
diff --git a/mlir/include/mlir/IR/BuiltinAttributes.h b/mlir/include/mlir/IR/BuiltinAttributes.h
index 99bb2b68cc62..ac98bfef1b58 100644
--- a/mlir/include/mlir/IR/BuiltinAttributes.h
+++ b/mlir/include/mlir/IR/BuiltinAttributes.h
@@ -16,160 +16,14 @@
namespace mlir {
class AffineMap;
+class BoolAttr;
+class DenseIntElementsAttr;
class FlatSymbolRefAttr;
class FunctionType;
class IntegerSet;
+class IntegerType;
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 IntegerAttributeStorage;
-struct FloatAttributeStorage;
-struct SymbolRefAttributeStorage;
-struct TypeAttributeStorage;
-
-/// Elements Attributes.
-struct DenseIntOrFPElementsAttributeStorage;
-struct DenseStringElementsAttributeStorage;
-struct OpaqueElementsAttributeStorage;
-struct SparseElementsAttributeStorage;
-} // namespace detail
-
-//===----------------------------------------------------------------------===//
-// FloatAttr
-//===----------------------------------------------------------------------===//
-
-class FloatAttr : public Attribute::AttrBase<FloatAttr, Attribute,
- detail::FloatAttributeStorage> {
-public:
- using Base::Base;
- using Base::getChecked;
- using ValueType = APFloat;
-
- /// Return a float attribute for the specified value in the specified type.
- /// These methods should only be used for simple constant values, e.g 1.0/2.0,
- /// that are known-valid both as host double and the 'type' format.
- static FloatAttr get(Type type, double value);
- static FloatAttr getChecked(function_ref<InFlightDiagnostic()> emitError,
- Type type, double value);
-
- /// Return a float attribute for the specified value in the specified type.
- static FloatAttr get(Type type, const APFloat &value);
- static FloatAttr getChecked(function_ref<InFlightDiagnostic()> emitError,
- Type type, const APFloat &value);
-
- APFloat getValue() const;
-
- /// This function is used to convert the value to a double, even if it loses
- /// precision.
- double getValueAsDouble() const;
- static double getValueAsDouble(APFloat val);
-
- /// Verify the construction invariants for a double value.
- static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
- Type type, double value);
- static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
- Type type, const APFloat &value);
-};
-
-//===----------------------------------------------------------------------===//
-// IntegerAttr
-//===----------------------------------------------------------------------===//
-
-class IntegerAttr
- : public Attribute::AttrBase<IntegerAttr, Attribute,
- detail::IntegerAttributeStorage> {
-public:
- using Base::Base;
- using ValueType = APInt;
-
- static IntegerAttr get(Type type, int64_t value);
- static IntegerAttr get(Type type, const APInt &value);
-
- APInt getValue() const;
- /// Return the integer value as a 64-bit int. The attribute must be a signless
- /// integer.
- // TODO: Change callers to use getValue instead.
- int64_t getInt() const;
- /// Return the integer value as a signed 64-bit int. The attribute must be
- /// a signed integer.
- int64_t getSInt() const;
- /// Return the integer value as a unsigned 64-bit int. The attribute must be
- /// an unsigned integer.
- uint64_t getUInt() const;
-
- static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
- Type type, int64_t value);
- static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
- Type type, const APInt &value);
-};
-
-//===----------------------------------------------------------------------===//
-// BoolAttr
-
-/// Special case of IntegerAttr to represent boolean integers, i.e., signless i1
-/// integers.
-class BoolAttr : public Attribute {
-public:
- using Attribute::Attribute;
- using ValueType = bool;
-
- static BoolAttr get(MLIRContext *context, bool value);
-
- /// Enable conversion to IntegerAttr. This uses conversion vs. inheritance to
- /// avoid bringing in all of IntegerAttrs methods.
- operator IntegerAttr() const { return IntegerAttr(impl); }
-
- /// Return the boolean value of this attribute.
- bool getValue() const;
-
- /// Methods for support type inquiry through isa, cast, and dyn_cast.
- static bool classof(Attribute attr);
-};
-
-//===----------------------------------------------------------------------===//
-// FlatSymbolRefAttr
-//===----------------------------------------------------------------------===//
-
-/// 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 {
-public:
- using SymbolRefAttr::SymbolRefAttr;
- using ValueType = StringRef;
-
- /// Construct a symbol reference for the given value name.
- static FlatSymbolRefAttr get(MLIRContext *ctx, StringRef value) {
- return SymbolRefAttr::get(ctx, value);
- }
-
- /// Returns the name of the held symbol reference.
- StringRef getValue() const { return getRootReference(); }
-
- /// Methods for support type inquiry through isa, cast, and dyn_cast.
- static bool classof(Attribute attr) {
- SymbolRefAttr refAttr = attr.dyn_cast<SymbolRefAttr>();
- return refAttr && refAttr.getNestedReferences().empty();
- }
-
-private:
- using SymbolRefAttr::get;
- using SymbolRefAttr::getNestedReferences;
-};
//===----------------------------------------------------------------------===//
// Elements Attributes
@@ -751,88 +605,91 @@ class DenseElementsAttr : public ElementsAttr {
bool isValidComplex(int64_t dataEltSize, bool isInt, bool isSigned) const;
};
-/// An attribute class for representing dense arrays of strings. The structure
-/// storing and querying a list of densely packed strings.
-class DenseStringElementsAttr
- : public Attribute::AttrBase<DenseStringElementsAttr, DenseElementsAttr,
- detail::DenseStringElementsAttributeStorage> {
-
+/// An attribute that represents a reference to a splat vector or tensor
+/// constant, meaning all of the elements have the same value.
+class SplatElementsAttr : public DenseElementsAttr {
public:
- using Base::Base;
-
- /// Overload of the raw 'get' method that asserts that the given type is of
- /// integer or floating-point type. This method is used to verify type
- /// invariants that the templatized 'get' method cannot.
- static DenseStringElementsAttr get(ShapedType type, ArrayRef<StringRef> data);
+ using DenseElementsAttr::DenseElementsAttr;
-protected:
- friend DenseElementsAttr;
+ /// Method for support type inquiry through isa, cast and dyn_cast.
+ static bool classof(Attribute attr) {
+ auto denseAttr = attr.dyn_cast<DenseElementsAttr>();
+ return denseAttr && denseAttr.isSplat();
+ }
};
-/// An attribute class for specializing behavior of Int and Floating-point
-/// densely packed string arrays.
-class DenseIntOrFPElementsAttr
- : public Attribute::AttrBase<DenseIntOrFPElementsAttr, DenseElementsAttr,
- detail::DenseIntOrFPElementsAttributeStorage> {
+} // namespace mlir
+//===----------------------------------------------------------------------===//
+// Tablegen Attribute Declarations
+//===----------------------------------------------------------------------===//
+
+#define GET_ATTRDEF_CLASSES
+#include "mlir/IR/BuiltinAttributes.h.inc"
+
+//===----------------------------------------------------------------------===//
+// C++ Attribute Declarations
+//===----------------------------------------------------------------------===//
+
+namespace mlir {
+//===----------------------------------------------------------------------===//
+// BoolAttr
+//===----------------------------------------------------------------------===//
+
+/// Special case of IntegerAttr to represent boolean integers, i.e., signless i1
+/// integers.
+class BoolAttr : public Attribute {
public:
- using Base::Base;
-
- /// Convert endianess of input ArrayRef for big-endian(BE) machines. All of
- /// the elements of `inRawData` has `type`. If `inRawData` is little endian
- /// (LE), it is converted to big endian (BE). Conversely, if `inRawData` is
- /// BE, converted to LE.
- static void
- convertEndianOfArrayRefForBEmachine(ArrayRef<char> inRawData,
- MutableArrayRef<char> outRawData,
- ShapedType type);
-
- /// Convert endianess of input for big-endian(BE) machines. The number of
- /// elements of `inRawData` is `numElements`, and each element has
- /// `elementBitWidth` bits. If `inRawData` is little endian (LE), it is
- /// converted to big endian (BE) and saved in `outRawData`. Conversely, if
- /// `inRawData` is BE, converted to LE.
- static void convertEndianOfCharForBEmachine(const char *inRawData,
- char *outRawData,
- size_t elementBitWidth,
- size_t numElements);
+ using Attribute::Attribute;
+ using ValueType = bool;
-protected:
- friend DenseElementsAttr;
+ static BoolAttr get(MLIRContext *context, bool value);
- /// Constructs a dense elements attribute from an array of raw APFloat values.
- /// Each APFloat value is expected to have the same bitwidth as the element
- /// type of 'type'. 'type' must be a vector or tensor with static shape.
- static DenseElementsAttr getRaw(ShapedType type, size_t storageWidth,
- ArrayRef<APFloat> values, bool isSplat);
+ /// Enable conversion to IntegerAttr. This uses conversion vs. inheritance to
+ /// avoid bringing in all of IntegerAttrs methods.
+ operator IntegerAttr() const { return IntegerAttr(impl); }
- /// Constructs a dense elements attribute from an array of raw APInt values.
- /// Each APInt value is expected to have the same bitwidth as the element type
- /// of 'type'. 'type' must be a vector or tensor with static shape.
- static DenseElementsAttr getRaw(ShapedType type, size_t storageWidth,
- ArrayRef<APInt> values, bool isSplat);
+ /// Return the boolean value of this attribute.
+ bool getValue() const;
- /// Get or create a new dense elements attribute instance with the given raw
- /// data buffer. 'type' must be a vector or tensor with static shape.
- static DenseElementsAttr getRaw(ShapedType type, ArrayRef<char> data,
- bool isSplat);
+ /// Methods for support type inquiry through isa, cast, and dyn_cast.
+ static bool classof(Attribute attr);
+};
- /// Overload of the raw 'get' method that asserts that the given type is of
- /// complex type. This method is used to verify type invariants that the
- /// templatized 'get' method cannot.
- static DenseElementsAttr getRawComplex(ShapedType type, ArrayRef<char> data,
- int64_t dataEltSize, bool isInt,
- bool isSigned);
+//===----------------------------------------------------------------------===//
+// FlatSymbolRefAttr
+//===----------------------------------------------------------------------===//
- /// Overload of the raw 'get' method that asserts that the given type is of
- /// integer or floating-point type. This method is used to verify type
- /// invariants that the templatized 'get' method cannot.
- static DenseElementsAttr getRawIntOrFloat(ShapedType type,
- ArrayRef<char> data,
- int64_t dataEltSize, bool isInt,
- bool isSigned);
+/// 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 {
+public:
+ using SymbolRefAttr::SymbolRefAttr;
+ using ValueType = StringRef;
+
+ /// Construct a symbol reference for the given value name.
+ static FlatSymbolRefAttr get(MLIRContext *ctx, StringRef value) {
+ return SymbolRefAttr::get(ctx, value);
+ }
+
+ /// Returns the name of the held symbol reference.
+ StringRef getValue() const { return getRootReference(); }
+
+ /// Methods for support type inquiry through isa, cast, and dyn_cast.
+ static bool classof(Attribute attr) {
+ SymbolRefAttr refAttr = attr.dyn_cast<SymbolRefAttr>();
+ return refAttr && refAttr.getNestedReferences().empty();
+ }
+
+private:
+ using SymbolRefAttr::get;
+ using SymbolRefAttr::getNestedReferences;
};
+//===----------------------------------------------------------------------===//
+// DenseFPElementsAttr
+//===----------------------------------------------------------------------===//
+
/// An attribute that represents a reference to a dense float vector or tensor
/// object. Each element is stored as a double.
class DenseFPElementsAttr : public DenseIntOrFPElementsAttr {
@@ -869,6 +726,10 @@ class DenseFPElementsAttr : public DenseIntOrFPElementsAttr {
static bool classof(Attribute attr);
};
+//===----------------------------------------------------------------------===//
+// DenseIntElementsAttr
+//===----------------------------------------------------------------------===//
+
/// An attribute that represents a reference to a dense integer vector or tensor
/// object.
class DenseIntElementsAttr : public DenseIntOrFPElementsAttr {
@@ -906,170 +767,27 @@ class DenseIntElementsAttr : public DenseIntOrFPElementsAttr {
static bool classof(Attribute attr);
};
-/// An opaque attribute that represents a reference to a vector or tensor
-/// constant with opaque content. This representation is for tensor constants
-/// which the compiler may not need to interpret. This attribute is always
-/// associated with a particular dialect, which provides a method to convert
-/// tensor representation to a non-opaque format.
-class OpaqueElementsAttr
- : public Attribute::AttrBase<OpaqueElementsAttr, ElementsAttr,
- detail::OpaqueElementsAttributeStorage> {
-public:
- using Base::Base;
- using ValueType = StringRef;
-
- static OpaqueElementsAttr get(Dialect *dialect, ShapedType type,
- StringRef bytes);
-
- StringRef getValue() const;
-
- /// Return the value at the given index. The 'index' is expected to refer to a
- /// valid element.
- Attribute getValue(ArrayRef<uint64_t> index) const;
-
- /// Decodes the attribute value using dialect-specific decoding hook.
- /// Returns false if decoding is successful. If not, returns true and leaves
- /// 'result' argument unspecified.
- bool decode(ElementsAttr &result);
-
- /// Returns dialect associated with this opaque constant.
- Dialect *getDialect() const;
-};
-
-/// An attribute that represents a reference to a sparse vector or tensor
-/// object.
-///
-/// This class uses COO (coordinate list) encoding to represent the sparse
-/// elements in an element attribute. Specifically, the sparse vector/tensor
-/// stores the indices and values as two separate dense elements attributes of
-/// tensor type (even if the sparse attribute is of vector type, in order to
-/// support empty lists). The dense elements attribute indices is a 2-D tensor
-/// of 64-bit integer elements with shape [N, ndims], which specifies the
-/// indices of the elements in the sparse tensor that contains nonzero values.
-/// The dense elements attribute values is a 1-D tensor with shape [N], and it
-/// supplies the corresponding values for the indices.
-///
-/// For example,
-/// `sparse<tensor<3x4xi32>, [[0, 0], [1, 2]], [1, 5]>` represents tensor
-/// [[1, 0, 0, 0],
-/// [0, 0, 5, 0],
-/// [0, 0, 0, 0]].
-class SparseElementsAttr
- : public Attribute::AttrBase<SparseElementsAttr, ElementsAttr,
- detail::SparseElementsAttributeStorage> {
-public:
- using Base::Base;
-
- template <typename T>
- using iterator =
- llvm::mapped_iterator<llvm::detail::value_sequence_iterator<ptr
diff _t>,
- std::function<T(ptr
diff _t)>>;
-
- /// 'type' must be a vector or tensor with static shape.
- static SparseElementsAttr get(ShapedType type, DenseElementsAttr indices,
- DenseElementsAttr values);
-
- DenseIntElementsAttr getIndices() const;
-
- DenseElementsAttr getValues() const;
-
- /// Return the values of this attribute in the form of the given type 'T'. 'T'
- /// may be any of Attribute, APInt, APFloat, c++ integer/float types, etc.
- template <typename T> llvm::iterator_range<iterator<T>> getValues() const {
- auto zeroValue = getZeroValue<T>();
- auto valueIt = getValues().getValues<T>().begin();
- const std::vector<ptr
diff _t> flatSparseIndices(getFlattenedSparseIndices());
- // TODO: Move-capture flatSparseIndices when c++14 is available.
- std::function<T(ptr
diff _t)> mapFn = [=](ptr
diff _t index) {
- // Try to map the current index to one of the sparse indices.
- for (unsigned i = 0, e = flatSparseIndices.size(); i != e; ++i)
- if (flatSparseIndices[i] == index)
- return *std::next(valueIt, i);
- // Otherwise, return the zero value.
- return zeroValue;
- };
- return llvm::map_range(llvm::seq<ptr
diff _t>(0, getNumElements()), mapFn);
- }
-
- /// Return the value of the element at the given index. The 'index' is
- /// expected to refer to a valid element.
- Attribute getValue(ArrayRef<uint64_t> index) const;
-
-private:
- /// Get a zero APFloat for the given sparse attribute.
- APFloat getZeroAPFloat() const;
-
- /// Get a zero APInt for the given sparse attribute.
- APInt getZeroAPInt() const;
-
- /// Get a zero attribute for the given sparse attribute.
- Attribute getZeroAttr() const;
-
- /// Utility methods to generate a zero value of some type 'T'. This is used by
- /// the 'iterator' class.
- /// Get a zero for a given attribute type.
- template <typename T>
- typename std::enable_if<std::is_base_of<Attribute, T>::value, T>::type
- getZeroValue() const {
- return getZeroAttr().template cast<T>();
- }
- /// Get a zero for an APInt.
- template <typename T>
- typename std::enable_if<std::is_same<APInt, T>::value, T>::type
- getZeroValue() const {
- return getZeroAPInt();
- }
- template <typename T>
- typename std::enable_if<std::is_same<std::complex<APInt>, T>::value, T>::type
- getZeroValue() const {
- APInt intZero = getZeroAPInt();
- return {intZero, intZero};
- }
- /// Get a zero for an APFloat.
- template <typename T>
- typename std::enable_if<std::is_same<APFloat, T>::value, T>::type
- getZeroValue() const {
- return getZeroAPFloat();
- }
- template <typename T>
- typename std::enable_if<std::is_same<std::complex<APFloat>, T>::value,
- T>::type
- getZeroValue() const {
- APFloat floatZero = getZeroAPFloat();
- return {floatZero, floatZero};
- }
-
- /// Get a zero for an C++ integer, float, StringRef, or complex type.
- template <typename T>
- typename std::enable_if<
- std::numeric_limits<T>::is_integer ||
- DenseElementsAttr::is_valid_cpp_fp_type<T>::value ||
- std::is_same<T, StringRef>::value ||
- (detail::is_complex_t<T>::value &&
- !llvm::is_one_of<T, std::complex<APInt>,
- std::complex<APFloat>>::value),
- T>::type
- getZeroValue() const {
- return T();
- }
-
- /// Flatten, and return, all of the sparse indices in this attribute in
- /// row-major order.
- std::vector<ptr
diff _t> getFlattenedSparseIndices() const;
-};
-
-/// An attribute that represents a reference to a splat vector or tensor
-/// constant, meaning all of the elements have the same value.
-class SplatElementsAttr : public DenseElementsAttr {
-public:
- using DenseElementsAttr::DenseElementsAttr;
+//===----------------------------------------------------------------------===//
+// SparseElementsAttr
+//===----------------------------------------------------------------------===//
- /// Method for support type inquiry through isa, cast and dyn_cast.
- static bool classof(Attribute attr) {
- auto denseAttr = attr.dyn_cast<DenseElementsAttr>();
- return denseAttr && denseAttr.isSplat();
- }
-};
+template <typename T>
+auto SparseElementsAttr::getValues() const
+ -> llvm::iterator_range<iterator<T>> {
+ auto zeroValue = getZeroValue<T>();
+ auto valueIt = getValues().getValues<T>().begin();
+ const std::vector<ptr
diff _t> flatSparseIndices(getFlattenedSparseIndices());
+ // TODO: Move-capture flatSparseIndices when c++14 is available.
+ std::function<T(ptr
diff _t)> mapFn = [=](ptr
diff _t index) {
+ // Try to map the current index to one of the sparse indices.
+ for (unsigned i = 0, e = flatSparseIndices.size(); i != e; ++i)
+ if (flatSparseIndices[i] == index)
+ return *std::next(valueIt, i);
+ // Otherwise, return the zero value.
+ return zeroValue;
+ };
+ return llvm::map_range(llvm::seq<ptr
diff _t>(0, getNumElements()), mapFn);
+}
namespace detail {
/// This class represents a general iterator over the values of an ElementsAttr.
diff --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td
index 530ab0b79e3f..433c33521a7a 100644
--- a/mlir/include/mlir/IR/BuiltinAttributes.td
+++ b/mlir/include/mlir/IR/BuiltinAttributes.td
@@ -22,7 +22,8 @@ include "mlir/IR/BuiltinDialect.td"
// to this file instead.
// Base class for Builtin dialect attributes.
-class Builtin_Attr<string name> : AttrDef<Builtin_Dialect, name> {
+class Builtin_Attr<string name, string baseCppClass = "::mlir::Attribute">
+ : AttrDef<Builtin_Dialect, name, baseCppClass> {
let mnemonic = ?;
}
@@ -127,6 +128,151 @@ def Builtin_ArrayAttr : Builtin_Attr<"Array"> {
}];
}
+//===----------------------------------------------------------------------===//
+// DenseIntOrFPElementsAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_DenseIntOrFPElementsAttr
+ : Builtin_Attr<"DenseIntOrFPElements", "DenseElementsAttr"> {
+ let summary = "An Attribute containing a dense multi-dimensional array of "
+ "integer or floating-point values";
+ let description = [{
+ Syntax:
+
+ ```
+ dense-intorfloat-elements-attribute ::= `dense` `<` attribute-value `>` `:`
+ ( tensor-type | vector-type )
+ ```
+
+ A dense int-or-float elements attribute is an elements attribute containing
+ a densely packed vector or tensor of integer or floating-point values. The
+ element type of this attribute is required to be either an `IntegerType` or
+ a `FloatType`.
+
+ Examples:
+
+ ```
+ // A splat tensor of integer values.
+ dense<10> : tensor<2xi32>
+ // A tensor of 2 float32 elements.
+ dense<[10.0, 11.0]> : tensor<2xf32>
+ ```
+ }];
+ let parameters = (ins AttributeSelfTypeParameter<"", "ShapedType">:$type,
+ "ArrayRef<char>":$rawData);
+ let extraClassDeclaration = [{
+ /// Convert endianess of input ArrayRef for big-endian(BE) machines. All of
+ /// the elements of `inRawData` has `type`. If `inRawData` is little endian
+ /// (LE), it is converted to big endian (BE). Conversely, if `inRawData` is
+ /// BE, converted to LE.
+ static void
+ convertEndianOfArrayRefForBEmachine(ArrayRef<char> inRawData,
+ MutableArrayRef<char> outRawData,
+ ShapedType type);
+
+ /// Convert endianess of input for big-endian(BE) machines. The number of
+ /// elements of `inRawData` is `numElements`, and each element has
+ /// `elementBitWidth` bits. If `inRawData` is little endian (LE), it is
+ /// converted to big endian (BE) and saved in `outRawData`. Conversely, if
+ /// `inRawData` is BE, converted to LE.
+ static void convertEndianOfCharForBEmachine(const char *inRawData,
+ char *outRawData,
+ size_t elementBitWidth,
+ size_t numElements);
+
+ protected:
+ friend DenseElementsAttr;
+
+ /// Constructs a dense elements attribute from an array of raw APFloat
+ /// values. Each APFloat value is expected to have the same bitwidth as the
+ /// element type of 'type'. 'type' must be a vector or tensor with static
+ /// shape.
+ static DenseElementsAttr getRaw(ShapedType type, size_t storageWidth,
+ ArrayRef<APFloat> values, bool isSplat);
+
+ /// Constructs a dense elements attribute from an array of raw APInt values.
+ /// Each APInt value is expected to have the same bitwidth as the element
+ /// type of 'type'. 'type' must be a vector or tensor with static shape.
+ static DenseElementsAttr getRaw(ShapedType type, size_t storageWidth,
+ ArrayRef<APInt> values, bool isSplat);
+
+ /// Get or create a new dense elements attribute instance with the given raw
+ /// data buffer. 'type' must be a vector or tensor with static shape.
+ static DenseElementsAttr getRaw(ShapedType type, ArrayRef<char> data,
+ bool isSplat);
+
+ /// Overload of the raw 'get' method that asserts that the given type is of
+ /// complex type. This method is used to verify type invariants that the
+ /// templatized 'get' method cannot.
+ static DenseElementsAttr getRawComplex(ShapedType type, ArrayRef<char> data,
+ int64_t dataEltSize, bool isInt,
+ bool isSigned);
+
+ /// Overload of the raw 'get' method that asserts that the given type is of
+ /// integer or floating-point type. This method is used to verify type
+ /// invariants that the templatized 'get' method cannot.
+ static DenseElementsAttr getRawIntOrFloat(ShapedType type,
+ ArrayRef<char> data,
+ int64_t dataEltSize, bool isInt,
+ bool isSigned);
+
+ public:
+ }];
+ let genAccessors = 0;
+ let genStorageClass = 0;
+ let skipDefaultBuilders = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// DenseStringElementsAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_DenseStringElementsAttr
+ : Builtin_Attr<"DenseStringElements", "DenseElementsAttr"> {
+ let summary = "An Attribute containing a dense multi-dimensional array of "
+ "strings";
+ let description = [{
+ Syntax:
+
+ ```
+ dense-string-elements-attribute ::= `dense` `<` attribute-value `>` `:`
+ ( tensor-type | vector-type )
+ ```
+
+ A dense string elements attribute is an elements attribute containing a
+ densely packed vector or tensor of string values. There are no restrictions
+ placed on the element type of this attribute, enabling the use of dialect
+ specific string types.
+
+ Examples:
+
+ ```
+ // A splat tensor of strings.
+ dense<"example"> : tensor<2x!foo.string>
+ // A tensor of 2 string elements.
+ dense<["example1", "example2"]> : tensor<2x!foo.string>
+ ```
+ }];
+ let parameters = (ins AttributeSelfTypeParameter<"", "ShapedType">:$type,
+ "ArrayRef<StringRef>":$value);
+ let builders = [
+ AttrBuilderWithInferredContext<(ins "ShapedType":$type,
+ "ArrayRef<StringRef>":$values), [{
+ return $_get(type.getContext(), type, values,
+ /* isSplat */(values.size() == 1));
+ }]>,
+ ];
+ let extraClassDeclaration = [{
+ protected:
+ friend DenseElementsAttr;
+
+ public:
+ }];
+ let genAccessors = 0;
+ let genStorageClass = 0;
+ let skipDefaultBuilders = 1;
+}
+
//===----------------------------------------------------------------------===//
// DictionaryAttr
//===----------------------------------------------------------------------===//
@@ -220,6 +366,147 @@ def Builtin_DictionaryAttr : Builtin_Attr<"Dictionary"> {
let skipDefaultBuilders = 1;
}
+//===----------------------------------------------------------------------===//
+// FloatAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_FloatAttr : Builtin_Attr<"Float"> {
+ let summary = "An Attribute containing a floating-point value";
+ let description = [{
+ Syntax:
+
+ ```
+ float-attribute ::= (float-literal (`:` float-type)?)
+ | (hexadecimal-literal `:` float-type)
+ ```
+
+ A float attribute is a literal attribute that represents a floating point
+ value of the specified [float type](#floating-point-types). It can be
+ represented in the hexadecimal form where the hexadecimal value is
+ interpreted as bits of the underlying binary representation. This form is
+ useful for representing infinity and NaN floating point values. To avoid
+ confusion with integer attributes, hexadecimal literals _must_ be followed
+ by a float type to define a float attribute.
+
+ Examples:
+
+ ```
+ 42.0 // float attribute defaults to f64 type
+ 42.0 : f32 // float attribute of f32 type
+ 0x7C00 : f16 // positive infinity
+ 0x7CFF : f16 // NaN (one of possible values)
+ 42 : f32 // Error: expected integer type
+ ```
+ }];
+ let parameters = (ins AttributeSelfTypeParameter<"">:$type,
+ APFloatParameter<"">:$value);
+ let builders = [
+ AttrBuilderWithInferredContext<(ins "Type":$type,
+ "const APFloat &":$value), [{
+ return $_get(type.getContext(), type, value);
+ }]>,
+ AttrBuilderWithInferredContext<(ins "Type":$type, "double":$value), [{
+ if (type.isF64())
+ return $_get(type.getContext(), type, APFloat(value));
+
+ // This handles, e.g., F16 because there is no APFloat constructor for it.
+ bool unused;
+ APFloat val(value);
+ val.convert(type.cast<FloatType>().getFloatSemantics(),
+ APFloat::rmNearestTiesToEven, &unused);
+ return $_get(type.getContext(), type, val);
+ }]>
+ ];
+ let extraClassDeclaration = [{
+ using ValueType = APFloat;
+
+ /// This function is used to convert the value to a double, even if it loses
+ /// precision.
+ double getValueAsDouble() const;
+ static double getValueAsDouble(APFloat val);
+ }];
+ let genVerifyDecl = 1;
+ let skipDefaultBuilders = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// IntegerAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_IntegerAttr : Builtin_Attr<"Integer"> {
+ let summary = "An Attribute containing a integer value";
+ let description = [{
+ Syntax:
+
+ ```
+ integer-attribute ::= (integer-literal ( `:` (index-type | integer-type) )?)
+ | `true` | `false`
+ ```
+
+ An integer attribute is a literal attribute that represents an integral
+ value of the specified integer or index type. `i1` integer attributes are
+ treated as `boolean` attributes, and use a unique assembly format of either
+ `true` or `false` depending on the value. The default type for non-boolean
+ integer attributes, if a type is not specified, is signless 64-bit integer.
+
+ Examples:
+
+ ```mlir
+ 10 : i32
+ 10 // : i64 is implied here.
+ true // A bool, i.e. i1, value.
+ false // A bool, i.e. i1, value.
+ ```
+ }];
+ let parameters = (ins AttributeSelfTypeParameter<"">:$type, "APInt":$value);
+ let builders = [
+ AttrBuilderWithInferredContext<(ins "Type":$type,
+ "const APInt &":$value), [{
+ if (type.isSignlessInteger(1))
+ return BoolAttr::get(type.getContext(), value.getBoolValue());
+ return $_get(type.getContext(), type, value);
+ }]>,
+ AttrBuilderWithInferredContext<(ins "Type":$type, "int64_t":$value), [{
+ // `index` has a defined internal storage width.
+ if (type.isIndex()) {
+ APInt apValue(IndexType::kInternalStorageBitWidth, value);
+ return $_get(type.getContext(), type, apValue);
+ }
+
+ IntegerType intTy = type.cast<IntegerType>();
+ APInt apValue(intTy.getWidth(), value, intTy.isSignedInteger());
+ return $_get(type.getContext(), type, apValue);
+ }]>
+ ];
+ let extraClassDeclaration = [{
+ using ValueType = APInt;
+
+ /// Return the integer value as a 64-bit int. The attribute must be a
+ /// signless integer.
+ // TODO: Change callers to use getValue instead.
+ int64_t getInt() const;
+ /// Return the integer value as a signed 64-bit int. The attribute must be
+ /// a signed integer.
+ int64_t getSInt() const;
+ /// Return the integer value as a unsigned 64-bit int. The attribute must be
+ /// an unsigned integer.
+ uint64_t getUInt() const;
+
+ private:
+ /// Return a boolean attribute. This is a special variant of the `get`
+ /// method that is used by the MLIRContext to cache the boolean IntegerAttr
+ /// instances.
+ static BoolAttr getBoolAttrUnchecked(IntegerType type, bool value);
+
+ /// Allow access to `getBoolAttrUnchecked`.
+ friend MLIRContext;
+
+ public:
+ }];
+ let genVerifyDecl = 1;
+ let skipDefaultBuilders = 1;
+}
+
//===----------------------------------------------------------------------===//
// IntegerSetAttr
//===----------------------------------------------------------------------===//
@@ -282,8 +569,212 @@ def Builtin_OpaqueAttr : Builtin_Attr<"Opaque"> {
return $_get(dialect.getContext(), dialect, attrData, type);
}]>
];
- bit genVerifyDecl = 1;
- // let skipDefaultBuilders = 1;
+ let genVerifyDecl = 1;
+ let skipDefaultBuilders = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// OpaqueElementsAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_OpaqueElementsAttr
+ : Builtin_Attr<"OpaqueElements", "ElementsAttr"> {
+ let summary = "An opaque representation of a multi-dimensional array";
+ let description = [{
+ Syntax:
+
+ ```
+ opaque-elements-attribute ::= `opaque` `<` dialect-namespace `,`
+ hex-string-literal `>` `:`
+ ( tensor-type | vector-type )
+ ```
+
+ An opaque elements attribute is an elements attribute where the content of
+ the value is opaque. The representation of the constant stored by this
+ elements attribute is only understood, and thus decodable, by the dialect
+ that created it.
+
+ Note: The parsed string literal must be in hexadecimal form.
+
+ Examples:
+
+ ```mlir
+ opaque<"foo_dialect", "0xDEADBEEF"> : tensor<10xi32>
+ ```
+ }];
+
+ // TODO: Provide a way to avoid copying content of large opaque
+ // tensors This will likely require a new reference attribute kind.
+ let parameters = (ins "Identifier":$dialect,
+ StringRefParameter<"">:$value,
+ AttributeSelfTypeParameter<"", "ShapedType">:$type);
+ let builders = [
+ AttrBuilderWithInferredContext<(ins "Identifier":$dialect,
+ "ShapedType":$type,
+ "StringRef":$value), [{
+ return $_get(dialect.getContext(), dialect, value, type);
+ }]>,
+ AttrBuilderWithInferredContext<(ins "Dialect *":$dialect,
+ "ShapedType":$type,
+ "StringRef":$value), [{
+ MLIRContext *ctxt = dialect->getContext();
+ Identifier dialectName = Identifier::get(dialect->getNamespace(), ctxt);
+ return $_get(ctxt, dialectName, value, type);
+ }]>
+ ];
+ let extraClassDeclaration = [{
+ using ValueType = StringRef;
+
+ /// Return the value at the given index. The 'index' is expected to refer to
+ /// a valid element.
+ Attribute getValue(ArrayRef<uint64_t> index) const;
+
+ /// Decodes the attribute value using dialect-specific decoding hook.
+ /// Returns false if decoding is successful. If not, returns true and leaves
+ /// 'result' argument unspecified.
+ bool decode(ElementsAttr &result);
+
+ }];
+ let genVerifyDecl = 1;
+ let skipDefaultBuilders = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// SparseElementsAttr
+//===----------------------------------------------------------------------===//
+
+def Builtin_SparseElementsAttr
+ : Builtin_Attr<"SparseElements", "ElementsAttr"> {
+ let summary = "An opaque representation of a multi-dimensional array";
+ let description = [{
+ Syntax:
+
+ ```
+ sparse-elements-attribute ::= `sparse` `<` attribute-value `,`
+ attribute-value `>` `:`
+ ( tensor-type | vector-type )
+ ```
+
+ A sparse elements attribute is an elements attribute that represents a
+ sparse vector or tensor object. This is where very few of the elements are
+ non-zero.
+
+ The attribute uses COO (coordinate list) encoding to represent the sparse
+ elements of the elements attribute. The indices are stored via a 2-D tensor
+ of 64-bit integer elements with shape [N, ndims], which specifies the
+ indices of the elements in the sparse tensor that contains non-zero values.
+ The element values are stored via a 1-D tensor with shape [N], that supplies
+ the corresponding values for the indices.
+
+ Example:
+
+ ```mlir
+ sparse<[[0, 0], [1, 2]], [1, 5]> : tensor<3x4xi32>
+
+ // This represents the following tensor:
+ /// [[1, 0, 0, 0],
+ /// [0, 0, 5, 0],
+ /// [0, 0, 0, 0]]
+ ```
+ }];
+
+ let parameters = (ins AttributeSelfTypeParameter<"", "ShapedType">:$type,
+ "DenseIntElementsAttr":$indices,
+ "DenseElementsAttr":$values);
+ let builders = [
+ AttrBuilderWithInferredContext<(ins "ShapedType":$type,
+ "DenseElementsAttr":$indices,
+ "DenseElementsAttr":$values), [{
+ assert(indices.getType().getElementType().isInteger(64) &&
+ "expected sparse indices to be 64-bit integer values");
+ assert((type.isa<RankedTensorType, VectorType>()) &&
+ "type must be ranked tensor or vector");
+ assert(type.hasStaticShape() && "type must have static shape");
+ return $_get(type.getContext(), type,
+ indices.cast<DenseIntElementsAttr>(), values);
+ }]>,
+ ];
+ let extraClassDeclaration = [{
+ template <typename T>
+ using iterator =
+ llvm::mapped_iterator<llvm::detail::value_sequence_iterator<ptr
diff _t>,
+ std::function<T(ptr
diff _t)>>;
+
+ /// Return the values of this attribute in the form of the given type 'T'.
+ /// 'T' may be any of Attribute, APInt, APFloat, c++ integer/float types,
+ /// etc.
+ template <typename T> llvm::iterator_range<iterator<T>> getValues() const;
+
+ /// Return the value of the element at the given index. The 'index' is
+ /// expected to refer to a valid element.
+ Attribute getValue(ArrayRef<uint64_t> index) const;
+
+ private:
+ /// Get a zero APFloat for the given sparse attribute.
+ APFloat getZeroAPFloat() const;
+
+ /// Get a zero APInt for the given sparse attribute.
+ APInt getZeroAPInt() const;
+
+ /// Get a zero attribute for the given sparse attribute.
+ Attribute getZeroAttr() const;
+
+ /// Utility methods to generate a zero value of some type 'T'. This is used
+ /// by the 'iterator' class.
+ /// Get a zero for a given attribute type.
+ template <typename T>
+ typename std::enable_if<std::is_base_of<Attribute, T>::value, T>::type
+ getZeroValue() const {
+ return getZeroAttr().template cast<T>();
+ }
+ /// Get a zero for an APInt.
+ template <typename T>
+ typename std::enable_if<std::is_same<APInt, T>::value, T>::type
+ getZeroValue() const {
+ return getZeroAPInt();
+ }
+ template <typename T>
+ typename std::enable_if<std::is_same<std::complex<APInt>, T>::value,
+ T>::type
+ getZeroValue() const {
+ APInt intZero = getZeroAPInt();
+ return {intZero, intZero};
+ }
+ /// Get a zero for an APFloat.
+ template <typename T>
+ typename std::enable_if<std::is_same<APFloat, T>::value, T>::type
+ getZeroValue() const {
+ return getZeroAPFloat();
+ }
+ template <typename T>
+ typename std::enable_if<std::is_same<std::complex<APFloat>, T>::value,
+ T>::type
+ getZeroValue() const {
+ APFloat floatZero = getZeroAPFloat();
+ return {floatZero, floatZero};
+ }
+
+ /// Get a zero for an C++ integer, float, StringRef, or complex type.
+ template <typename T>
+ typename std::enable_if<
+ std::numeric_limits<T>::is_integer ||
+ DenseElementsAttr::is_valid_cpp_fp_type<T>::value ||
+ std::is_same<T, StringRef>::value ||
+ (detail::is_complex_t<T>::value &&
+ !llvm::is_one_of<T, std::complex<APInt>,
+ std::complex<APFloat>>::value),
+ T>::type
+ getZeroValue() const {
+ return T();
+ }
+
+ /// Flatten, and return, all of the sparse indices in this attribute in
+ /// row-major order.
+ std::vector<ptr
diff _t> getFlattenedSparseIndices() const;
+
+ public:
+ }];
+ let skipDefaultBuilders = 1;
}
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td
index 819badc8b0f4..844f7685df7f 100644
--- a/mlir/include/mlir/IR/OpBase.td
+++ b/mlir/include/mlir/IR/OpBase.td
@@ -2723,7 +2723,8 @@ class ArrayRefOfSelfAllocationParameter<string arrayOf, string desc> :
// This is a special parameter used for AttrDefs that represents a `mlir::Type`
// that is also used as the value `Type` of the attribute. Only one parameter
// of the attribute may be of this type.
-class AttributeSelfTypeParameter<string desc> :
- AttrOrTypeParameter<"::mlir::Type", desc> {}
+class AttributeSelfTypeParameter<string desc,
+ string derivedType = "::mlir::Type"> :
+ AttrOrTypeParameter<derivedType, desc> {}
#endif // OP_BASE
diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp
index b6d327b1c78b..ad2c3c6a9075 100644
--- a/mlir/lib/IR/AsmPrinter.cpp
+++ b/mlir/lib/IR/AsmPrinter.cpp
@@ -1515,7 +1515,7 @@ static void printSymbolReference(StringRef symbolRef, raw_ostream &os) {
// accept the string "elided". The first string must be a registered dialect
// name and the latter must be a hex constant.
static void printElidedElementsAttr(raw_ostream &os) {
- os << R"(opaque<"", "0xDEADBEEF">)";
+ os << R"(opaque<"_", "0xDEADBEEF">)";
}
void ModulePrinter::printAttribute(Attribute attr,
@@ -1610,8 +1610,8 @@ void ModulePrinter::printAttribute(Attribute attr,
if (printerFlags.shouldElideElementsAttr(opaqueAttr)) {
printElidedElementsAttr(os);
} else {
- os << "opaque<\"" << opaqueAttr.getDialect()->getNamespace() << "\", ";
- os << '"' << "0x" << llvm::toHex(opaqueAttr.getValue()) << "\">";
+ os << "opaque<\"" << opaqueAttr.getDialect() << "\", \"0x"
+ << llvm::toHex(opaqueAttr.getValue()) << "\">";
}
} else if (auto intOrFpEltAttr = attr.dyn_cast<DenseIntOrFPElementsAttr>()) {
diff --git a/mlir/lib/IR/AttributeDetail.h b/mlir/lib/IR/AttributeDetail.h
index 9499a0f84c84..f62d886cacb6 100644
--- a/mlir/lib/IR/AttributeDetail.h
+++ b/mlir/lib/IR/AttributeDetail.h
@@ -27,113 +27,6 @@
namespace mlir {
namespace detail {
-/// An attribute representing a floating point value.
-struct FloatAttributeStorage final
- : public AttributeStorage,
- public llvm::TrailingObjects<FloatAttributeStorage, uint64_t> {
- using KeyTy = std::pair<Type, APFloat>;
-
- FloatAttributeStorage(const llvm::fltSemantics &semantics, Type type,
- size_t numObjects)
- : AttributeStorage(type), semantics(semantics), numObjects(numObjects) {}
-
- /// Key equality and hash functions.
- bool operator==(const KeyTy &key) const {
- return key.first == getType() && key.second.bitwiseIsEqual(getValue());
- }
- static unsigned hashKey(const KeyTy &key) {
- return llvm::hash_combine(key.first, llvm::hash_value(key.second));
- }
-
- /// Construct a key with a type and double.
- static KeyTy getKey(Type type, double value) {
- if (type.isF64())
- return KeyTy(type, APFloat(value));
-
- // This handles, e.g., F16 because there is no APFloat constructor for it.
- bool unused;
- APFloat val(value);
- val.convert(type.cast<FloatType>().getFloatSemantics(),
- APFloat::rmNearestTiesToEven, &unused);
- return KeyTy(type, val);
- }
-
- /// Construct a new storage instance.
- static FloatAttributeStorage *construct(AttributeStorageAllocator &allocator,
- const KeyTy &key) {
- const auto &apint = key.second.bitcastToAPInt();
-
- // Here one word's bitwidth equals to that of uint64_t.
- auto elements = ArrayRef<uint64_t>(apint.getRawData(), apint.getNumWords());
-
- auto byteSize =
- FloatAttributeStorage::totalSizeToAlloc<uint64_t>(elements.size());
- auto rawMem = allocator.allocate(byteSize, alignof(FloatAttributeStorage));
- auto result = ::new (rawMem) FloatAttributeStorage(
- key.second.getSemantics(), key.first, elements.size());
- std::uninitialized_copy(elements.begin(), elements.end(),
- result->getTrailingObjects<uint64_t>());
- return result;
- }
-
- /// Returns an APFloat representing the stored value.
- APFloat getValue() const {
- auto val = APInt(APFloat::getSizeInBits(semantics),
- {getTrailingObjects<uint64_t>(), numObjects});
- return APFloat(semantics, val);
- }
-
- const llvm::fltSemantics &semantics;
- size_t numObjects;
-};
-
-/// An attribute representing an integral value.
-struct IntegerAttributeStorage final
- : public AttributeStorage,
- public llvm::TrailingObjects<IntegerAttributeStorage, uint64_t> {
- using KeyTy = std::pair<Type, APInt>;
-
- IntegerAttributeStorage(Type type, size_t numObjects)
- : AttributeStorage(type), numObjects(numObjects) {
- assert((type.isIndex() || type.isa<IntegerType>()) && "invalid type");
- }
-
- /// Key equality and hash functions.
- bool operator==(const KeyTy &key) const {
- return key == KeyTy(getType(), getValue());
- }
- static unsigned hashKey(const KeyTy &key) {
- return llvm::hash_combine(key.first, llvm::hash_value(key.second));
- }
-
- /// Construct a new storage instance.
- static IntegerAttributeStorage *
- construct(AttributeStorageAllocator &allocator, const KeyTy &key) {
- Type type;
- APInt value;
- std::tie(type, value) = key;
-
- auto elements = ArrayRef<uint64_t>(value.getRawData(), value.getNumWords());
- auto size =
- IntegerAttributeStorage::totalSizeToAlloc<uint64_t>(elements.size());
- auto rawMem = allocator.allocate(size, alignof(IntegerAttributeStorage));
- auto result = ::new (rawMem) IntegerAttributeStorage(type, elements.size());
- std::uninitialized_copy(elements.begin(), elements.end(),
- result->getTrailingObjects<uint64_t>());
- return result;
- }
-
- /// Returns an APInt representing the stored value.
- APInt getValue() const {
- if (getType().isIndex())
- return APInt(64, {getTrailingObjects<uint64_t>(), numObjects});
- return APInt(getType().getIntOrFloatBitWidth(),
- {getTrailingObjects<uint64_t>(), numObjects});
- }
-
- size_t numObjects;
-};
-
//===----------------------------------------------------------------------===//
// Elements Attributes
//===----------------------------------------------------------------------===//
@@ -158,10 +51,9 @@ struct DenseElementsAttributeStorage : public AttributeStorage {
};
/// An attribute representing a reference to a dense vector or tensor object.
-struct DenseIntOrFPElementsAttributeStorage
- : public DenseElementsAttributeStorage {
- DenseIntOrFPElementsAttributeStorage(ShapedType ty, ArrayRef<char> data,
- bool isSplat = false)
+struct DenseIntOrFPElementsAttrStorage : public DenseElementsAttributeStorage {
+ DenseIntOrFPElementsAttrStorage(ShapedType ty, ArrayRef<char> data,
+ bool isSplat = false)
: DenseElementsAttributeStorage(ty, isSplat), data(data) {}
struct KeyTy {
@@ -287,7 +179,7 @@ struct DenseIntOrFPElementsAttributeStorage
}
/// Construct a new storage instance.
- static DenseIntOrFPElementsAttributeStorage *
+ static DenseIntOrFPElementsAttrStorage *
construct(AttributeStorageAllocator &allocator, KeyTy key) {
// If the data buffer is non-empty, we copy it into the allocator with a
// 64-bit alignment.
@@ -303,8 +195,8 @@ struct DenseIntOrFPElementsAttributeStorage
copy = ArrayRef<char>(rawData, data.size());
}
- return new (allocator.allocate<DenseIntOrFPElementsAttributeStorage>())
- DenseIntOrFPElementsAttributeStorage(key.type, copy, key.isSplat);
+ return new (allocator.allocate<DenseIntOrFPElementsAttrStorage>())
+ DenseIntOrFPElementsAttrStorage(key.type, copy, key.isSplat);
}
ArrayRef<char> data;
@@ -312,10 +204,9 @@ struct DenseIntOrFPElementsAttributeStorage
/// An attribute representing a reference to a dense vector or tensor object
/// containing strings.
-struct DenseStringElementsAttributeStorage
- : public DenseElementsAttributeStorage {
- DenseStringElementsAttributeStorage(ShapedType ty, ArrayRef<StringRef> data,
- bool isSplat = false)
+struct DenseStringElementsAttrStorage : public DenseElementsAttributeStorage {
+ DenseStringElementsAttrStorage(ShapedType ty, ArrayRef<StringRef> data,
+ bool isSplat = false)
: DenseElementsAttributeStorage(ty, isSplat), data(data) {}
struct KeyTy {
@@ -385,14 +276,14 @@ struct DenseStringElementsAttributeStorage
}
/// Construct a new storage instance.
- static DenseStringElementsAttributeStorage *
+ static DenseStringElementsAttrStorage *
construct(AttributeStorageAllocator &allocator, KeyTy key) {
// If the data buffer is non-empty, we copy it into the allocator with a
// 64-bit alignment.
ArrayRef<StringRef> copy, data = key.data;
if (data.empty()) {
- return new (allocator.allocate<DenseStringElementsAttributeStorage>())
- DenseStringElementsAttributeStorage(key.type, copy, key.isSplat);
+ return new (allocator.allocate<DenseStringElementsAttrStorage>())
+ DenseStringElementsAttrStorage(key.type, copy, key.isSplat);
}
int numEntries = key.isSplat ? 1 : data.size();
@@ -421,72 +312,13 @@ struct DenseStringElementsAttributeStorage
copy =
ArrayRef<StringRef>(reinterpret_cast<StringRef *>(rawData), numEntries);
- return new (allocator.allocate<DenseStringElementsAttributeStorage>())
- DenseStringElementsAttributeStorage(key.type, copy, key.isSplat);
+ return new (allocator.allocate<DenseStringElementsAttrStorage>())
+ DenseStringElementsAttrStorage(key.type, copy, key.isSplat);
}
ArrayRef<StringRef> data;
};
-/// An attribute representing a reference to a tensor constant with opaque
-/// content.
-struct OpaqueElementsAttributeStorage : public AttributeStorage {
- using KeyTy = std::tuple<Type, Dialect *, StringRef>;
-
- OpaqueElementsAttributeStorage(Type type, Dialect *dialect, StringRef bytes)
- : AttributeStorage(type), dialect(dialect), bytes(bytes) {}
-
- /// Key equality and hash functions.
- bool operator==(const KeyTy &key) const {
- return key == std::make_tuple(getType(), dialect, bytes);
- }
- static unsigned hashKey(const KeyTy &key) {
- return llvm::hash_combine(std::get<0>(key), std::get<1>(key),
- std::get<2>(key));
- }
-
- /// Construct a new storage instance.
- static OpaqueElementsAttributeStorage *
- construct(AttributeStorageAllocator &allocator, KeyTy key) {
- // TODO: Provide a way to avoid copying content of large opaque
- // tensors This will likely require a new reference attribute kind.
- return new (allocator.allocate<OpaqueElementsAttributeStorage>())
- OpaqueElementsAttributeStorage(std::get<0>(key), std::get<1>(key),
- allocator.copyInto(std::get<2>(key)));
- }
-
- Dialect *dialect;
- StringRef bytes;
-};
-
-/// An attribute representing a reference to a sparse vector or tensor object.
-struct SparseElementsAttributeStorage : public AttributeStorage {
- using KeyTy = std::tuple<Type, DenseIntElementsAttr, DenseElementsAttr>;
-
- SparseElementsAttributeStorage(Type type, DenseIntElementsAttr indices,
- DenseElementsAttr values)
- : AttributeStorage(type), indices(indices), values(values) {}
-
- /// Key equality and hash functions.
- bool operator==(const KeyTy &key) const {
- return key == std::make_tuple(getType(), indices, values);
- }
- static unsigned hashKey(const KeyTy &key) {
- return llvm::hash_combine(std::get<0>(key), std::get<1>(key),
- std::get<2>(key));
- }
-
- /// Construct a new storage instance.
- static SparseElementsAttributeStorage *
- construct(AttributeStorageAllocator &allocator, KeyTy key) {
- return new (allocator.allocate<SparseElementsAttributeStorage>())
- SparseElementsAttributeStorage(std::get<0>(key), std::get<1>(key),
- std::get<2>(key));
- }
-
- DenseIntElementsAttr indices;
- DenseElementsAttr values;
-};
} // namespace detail
} // namespace mlir
diff --git a/mlir/lib/IR/BuiltinAttributes.cpp b/mlir/lib/IR/BuiltinAttributes.cpp
index 5efb8f7c70ff..947ee143c963 100644
--- a/mlir/lib/IR/BuiltinAttributes.cpp
+++ b/mlir/lib/IR/BuiltinAttributes.cpp
@@ -202,26 +202,6 @@ DictionaryAttr DictionaryAttr::getEmptyUnchecked(MLIRContext *context) {
// FloatAttr
//===----------------------------------------------------------------------===//
-FloatAttr FloatAttr::get(Type type, double value) {
- return Base::get(type.getContext(), type, value);
-}
-
-FloatAttr FloatAttr::getChecked(function_ref<InFlightDiagnostic()> emitError,
- Type type, double value) {
- return Base::getChecked(emitError, type.getContext(), type, value);
-}
-
-FloatAttr FloatAttr::get(Type type, const APFloat &value) {
- return Base::get(type.getContext(), type, value);
-}
-
-FloatAttr FloatAttr::getChecked(function_ref<InFlightDiagnostic()> emitError,
- Type type, const APFloat &value) {
- return Base::getChecked(emitError, type.getContext(), type, value);
-}
-
-APFloat FloatAttr::getValue() const { return getImpl()->getValue(); }
-
double FloatAttr::getValueAsDouble() const {
return getValueAsDouble(getValue());
}
@@ -234,25 +214,11 @@ double FloatAttr::getValueAsDouble(APFloat value) {
return value.convertToDouble();
}
-/// Verify construction invariants.
-static LogicalResult
-verifyFloatTypeInvariants(function_ref<InFlightDiagnostic()> emitError,
- Type type) {
- if (!type.isa<FloatType>())
- return emitError() << "expected floating point type";
- return success();
-}
-
-LogicalResult FloatAttr::verify(function_ref<InFlightDiagnostic()> emitError,
- Type type, double value) {
- return verifyFloatTypeInvariants(emitError, type);
-}
-
LogicalResult FloatAttr::verify(function_ref<InFlightDiagnostic()> emitError,
- Type type, const APFloat &value) {
+ Type type, APFloat value) {
// Verify that the type is correct.
- if (failed(verifyFloatTypeInvariants(emitError, type)))
- return failure();
+ if (!type.isa<FloatType>())
+ return emitError() << "expected floating point type";
// Verify that the type semantics match that of the value.
if (&type.cast<FloatType>().getFloatSemantics() != &value.getSemantics()) {
@@ -279,72 +245,47 @@ StringRef SymbolRefAttr::getLeafReference() const {
// IntegerAttr
//===----------------------------------------------------------------------===//
-IntegerAttr IntegerAttr::get(Type type, const APInt &value) {
- if (type.isSignlessInteger(1))
- return BoolAttr::get(type.getContext(), value.getBoolValue());
- return Base::get(type.getContext(), type, value);
-}
-
-IntegerAttr IntegerAttr::get(Type type, int64_t value) {
- // This uses 64 bit APInts by default for index type.
- if (type.isIndex())
- return get(type, APInt(IndexType::kInternalStorageBitWidth, value));
-
- auto intType = type.cast<IntegerType>();
- return get(type, APInt(intType.getWidth(), value, intType.isSignedInteger()));
-}
-
-APInt IntegerAttr::getValue() const { return getImpl()->getValue(); }
-
int64_t IntegerAttr::getInt() const {
- assert((getImpl()->getType().isIndex() ||
- getImpl()->getType().isSignlessInteger()) &&
+ assert((getType().isIndex() || getType().isSignlessInteger()) &&
"must be signless integer");
return getValue().getSExtValue();
}
int64_t IntegerAttr::getSInt() const {
- assert(getImpl()->getType().isSignedInteger() && "must be signed integer");
+ assert(getType().isSignedInteger() && "must be signed integer");
return getValue().getSExtValue();
}
uint64_t IntegerAttr::getUInt() const {
- assert(getImpl()->getType().isUnsignedInteger() &&
- "must be unsigned integer");
+ assert(getType().isUnsignedInteger() && "must be unsigned integer");
return getValue().getZExtValue();
}
-static LogicalResult
-verifyIntegerTypeInvariants(function_ref<InFlightDiagnostic()> emitError,
- Type type) {
- if (type.isa<IntegerType, IndexType>())
- return success();
- return emitError() << "expected integer or index type";
-}
-
LogicalResult IntegerAttr::verify(function_ref<InFlightDiagnostic()> emitError,
- Type type, int64_t value) {
- return verifyIntegerTypeInvariants(emitError, type);
-}
-
-LogicalResult IntegerAttr::verify(function_ref<InFlightDiagnostic()> emitError,
- Type type, const APInt &value) {
- if (failed(verifyIntegerTypeInvariants(emitError, type)))
- return failure();
- if (auto integerType = type.dyn_cast<IntegerType>())
+ Type type, APInt value) {
+ if (IntegerType integerType = type.dyn_cast<IntegerType>()) {
if (integerType.getWidth() != value.getBitWidth())
return emitError() << "integer type bit width (" << integerType.getWidth()
<< ") doesn't match value bit width ("
<< value.getBitWidth() << ")";
- return success();
+ return success();
+ }
+ if (type.isa<IndexType>())
+ return success();
+ return emitError() << "expected integer or index type";
+}
+
+BoolAttr IntegerAttr::getBoolAttrUnchecked(IntegerType type, bool value) {
+ auto attr = Base::get(type.getContext(), type, APInt(/*numBits=*/1, value));
+ return attr.cast<BoolAttr>();
}
//===----------------------------------------------------------------------===//
// BoolAttr
bool BoolAttr::getValue() const {
- auto *storage = reinterpret_cast<IntegerAttributeStorage *>(impl);
- return storage->getValue().getBoolValue();
+ auto *storage = reinterpret_cast<IntegerAttrStorage *>(impl);
+ return storage->value.getBoolValue();
}
bool BoolAttr::classof(Attribute attr) {
@@ -987,11 +928,11 @@ auto DenseElementsAttr::getComplexFloatValues() const
/// Return the raw storage data held by this attribute.
ArrayRef<char> DenseElementsAttr::getRawData() const {
- return static_cast<DenseIntOrFPElementsAttributeStorage *>(impl)->data;
+ return static_cast<DenseIntOrFPElementsAttrStorage *>(impl)->data;
}
ArrayRef<StringRef> DenseElementsAttr::getRawStringData() const {
- return static_cast<DenseStringElementsAttributeStorage *>(impl)->data;
+ return static_cast<DenseStringElementsAttrStorage *>(impl)->data;
}
/// Return a new DenseElementsAttr that has the same data as the current
@@ -1021,15 +962,6 @@ DenseElementsAttr DenseElementsAttr::mapValues(
return cast<DenseFPElementsAttr>().mapValues(newElementType, mapping);
}
-//===----------------------------------------------------------------------===//
-// DenseStringElementsAttr
-//===----------------------------------------------------------------------===//
-
-DenseStringElementsAttr
-DenseStringElementsAttr::get(ShapedType type, ArrayRef<StringRef> values) {
- return Base::get(type.getContext(), type, values, (values.size() == 1));
-}
-
//===----------------------------------------------------------------------===//
// DenseIntOrFPElementsAttr
//===----------------------------------------------------------------------===//
@@ -1254,15 +1186,6 @@ bool DenseIntElementsAttr::classof(Attribute attr) {
// OpaqueElementsAttr
//===----------------------------------------------------------------------===//
-OpaqueElementsAttr OpaqueElementsAttr::get(Dialect *dialect, ShapedType type,
- StringRef bytes) {
- assert(TensorType::isValidElementType(type.getElementType()) &&
- "Input element type should be a valid tensor element type");
- return Base::get(type.getContext(), type, dialect, bytes);
-}
-
-StringRef OpaqueElementsAttr::getValue() const { return getImpl()->bytes; }
-
/// Return the value at the given index. If index does not refer to a valid
/// element, then a null attribute is returned.
Attribute OpaqueElementsAttr::getValue(ArrayRef<uint64_t> index) const {
@@ -1270,43 +1193,30 @@ Attribute OpaqueElementsAttr::getValue(ArrayRef<uint64_t> index) const {
return Attribute();
}
-Dialect *OpaqueElementsAttr::getDialect() const { return getImpl()->dialect; }
-
bool OpaqueElementsAttr::decode(ElementsAttr &result) {
- auto *d = getDialect();
- if (!d)
+ Dialect *dialect = getDialect().getDialect();
+ if (!dialect)
return true;
auto *interface =
- d->getRegisteredInterface<DialectDecodeAttributesInterface>();
+ dialect->getRegisteredInterface<DialectDecodeAttributesInterface>();
if (!interface)
return true;
return failed(interface->decode(*this, result));
}
+LogicalResult
+OpaqueElementsAttr::verify(function_ref<InFlightDiagnostic()> emitError,
+ Identifier dialect, StringRef value,
+ ShapedType type) {
+ if (!Dialect::isValidNamespace(dialect.strref()))
+ return emitError() << "invalid dialect namespace '" << dialect << "'";
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// SparseElementsAttr
//===----------------------------------------------------------------------===//
-SparseElementsAttr SparseElementsAttr::get(ShapedType type,
- DenseElementsAttr indices,
- DenseElementsAttr values) {
- assert(indices.getType().getElementType().isInteger(64) &&
- "expected sparse indices to be 64-bit integer values");
- assert((type.isa<RankedTensorType, VectorType>()) &&
- "type must be ranked tensor or vector");
- assert(type.hasStaticShape() && "type must have static shape");
- return Base::get(type.getContext(), type,
- indices.cast<DenseIntElementsAttr>(), values);
-}
-
-DenseIntElementsAttr SparseElementsAttr::getIndices() const {
- return getImpl()->indices;
-}
-
-DenseElementsAttr SparseElementsAttr::getValues() const {
- return getImpl()->values;
-}
-
/// Return the value of the element at the given index.
Attribute SparseElementsAttr::getValue(ArrayRef<uint64_t> index) const {
assert(isValidIndex(index) && "expected valid multi-dimensional index");
diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp
index 464c1a7c842f..ddc88047b7ee 100644
--- a/mlir/lib/IR/MLIRContext.cpp
+++ b/mlir/lib/IR/MLIRContext.cpp
@@ -390,17 +390,13 @@ MLIRContext::MLIRContext(const DialectRegistry ®istry)
//// Attributes.
//// Note: These must be registered after the types as they may generate one
//// of the above types internally.
+ /// Unknown Location Attribute.
+ impl->unknownLocAttr = AttributeUniquer::get<UnknownLoc>(this);
/// Bool Attributes.
- impl->falseAttr = AttributeUniquer::get<IntegerAttr>(
- this, impl->int1Ty, APInt(/*numBits=*/1, false))
- .cast<BoolAttr>();
- impl->trueAttr = AttributeUniquer::get<IntegerAttr>(
- this, impl->int1Ty, APInt(/*numBits=*/1, true))
- .cast<BoolAttr>();
+ impl->falseAttr = IntegerAttr::getBoolAttrUnchecked(impl->int1Ty, false);
+ impl->trueAttr = IntegerAttr::getBoolAttrUnchecked(impl->int1Ty, true);
/// Unit Attribute.
impl->unitAttr = AttributeUniquer::get<UnitAttr>(this);
- /// Unknown Location Attribute.
- impl->unknownLocAttr = AttributeUniquer::get<UnknownLoc>(this);
/// The empty dictionary attribute.
impl->emptyDictionaryAttr = DictionaryAttr::getEmptyUnchecked(this);
diff --git a/mlir/lib/Parser/AttributeParser.cpp b/mlir/lib/Parser/AttributeParser.cpp
index 98f74174e5a3..f71f2a21669a 100644
--- a/mlir/lib/Parser/AttributeParser.cpp
+++ b/mlir/lib/Parser/AttributeParser.cpp
@@ -862,16 +862,7 @@ Attribute Parser::parseOpaqueElementsAttr(Type attrType) {
if (getToken().isNot(Token::string))
return (emitError("expected dialect namespace"), nullptr);
- auto name = getToken().getStringValue();
- // Lazy load a dialect in the context if there is a possible namespace.
- Dialect *dialect = builder.getContext()->getOrLoadDialect(name);
-
- // TODO: Allow for having an unknown dialect on an opaque
- // attribute. Otherwise, it can't be roundtripped without having the dialect
- // registered.
- if (!dialect)
- return (emitError("no registered dialect with namespace '" + name + "'"),
- nullptr);
+ std::string name = getToken().getStringValue();
consumeToken(Token::string);
if (parseToken(Token::comma, "expected ','"))
@@ -888,7 +879,7 @@ Attribute Parser::parseOpaqueElementsAttr(Type attrType) {
std::string data;
if (parseElementAttrHexValues(*this, hexTok, data))
return nullptr;
- return OpaqueElementsAttr::get(dialect, type, data);
+ return OpaqueElementsAttr::get(builder.getIdentifier(name), type, data);
}
/// Shaped type for elements attribute.
diff --git a/mlir/lib/TableGen/AttrOrTypeDef.cpp b/mlir/lib/TableGen/AttrOrTypeDef.cpp
index eea03015d329..1e4f5e4becdd 100644
--- a/mlir/lib/TableGen/AttrOrTypeDef.cpp
+++ b/mlir/lib/TableGen/AttrOrTypeDef.cpp
@@ -45,10 +45,6 @@ AttrOrTypeDef::AttrOrTypeDef(const llvm::Record *def) : def(def) {
}
builders.emplace_back(builder);
}
- } else if (skipDefaultBuilders()) {
- PrintFatalError(
- def->getLoc(),
- "default builders are skipped and no custom builders provided");
}
}
diff --git a/mlir/test/CAPI/ir.c b/mlir/test/CAPI/ir.c
index b72a6e6cf2fd..beb73102615e 100644
--- a/mlir/test/CAPI/ir.c
+++ b/mlir/test/CAPI/ir.c
@@ -449,7 +449,7 @@ static void printFirstOfEach(MlirContext ctx, MlirOperation operation) {
mlirOperationPrintWithFlags(operation, flags, printToStderr, NULL);
fprintf(stderr, "\n");
// clang-format off
- // CHECK: Op print with all flags: %{{.*}} = "std.constant"() {elts = opaque<"", "0xDEADBEEF"> : tensor<4xi32>, value = 0 : index} : () -> index loc(unknown)
+ // CHECK: Op print with all flags: %{{.*}} = "std.constant"() {elts = opaque<"_", "0xDEADBEEF"> : tensor<4xi32>, value = 0 : index} : () -> index loc(unknown)
// clang-format on
mlirOpPrintingFlagsDestroy(flags);
diff --git a/mlir/test/IR/invalid.mlir b/mlir/test/IR/invalid.mlir
index 419c98626521..4c4df915167a 100644
--- a/mlir/test/IR/invalid.mlir
+++ b/mlir/test/IR/invalid.mlir
@@ -766,21 +766,14 @@ func @elementsattr_malformed_opaque() -> () {
func @elementsattr_malformed_opaque1() -> () {
^bb0:
- "foo"(){bar = opaque<"", "0xQZz123"> : tensor<1xi8>} : () -> () // expected-error {{expected string containing hex digits starting with `0x`}}
+ "foo"(){bar = opaque<"_", "0xQZz123"> : tensor<1xi8>} : () -> () // expected-error {{expected string containing hex digits starting with `0x`}}
}
// -----
func @elementsattr_malformed_opaque2() -> () {
^bb0:
- "foo"(){bar = opaque<"", "00abc"> : tensor<1xi8>} : () -> () // expected-error {{expected string containing hex digits starting with `0x`}}
-}
-
-// -----
-
-func @elementsattr_malformed_opaque3() -> () {
-^bb0:
- "foo"(){bar = opaque<"t", "0xabc"> : tensor<1xi8>} : () -> () // expected-error {{no registered dialect with namespace 't'}}
+ "foo"(){bar = opaque<"_", "00abc"> : tensor<1xi8>} : () -> () // expected-error {{expected string containing hex digits starting with `0x`}}
}
// -----
@@ -881,7 +874,7 @@ func @type_alias_unknown(!unknown_alias) -> () { // expected-error {{undefined s
func @complex_loops() {
affine.for %i1 = 1 to 100 {
// expected-error @+1 {{expected '"' in string literal}}
- "opaqueIntTensor"(){bar = opaque<"", "0x686]> : tensor<2x1x4xi32>} : () -> ()
+ "opaqueIntTensor"(){bar = opaque<"_", "0x686]> : tensor<2x1x4xi32>} : () -> ()
// -----
diff --git a/mlir/test/IR/pretty-attributes.mlir b/mlir/test/IR/pretty-attributes.mlir
index d4ac8e773935..280e32672ea5 100644
--- a/mlir/test/IR/pretty-attributes.mlir
+++ b/mlir/test/IR/pretty-attributes.mlir
@@ -5,17 +5,17 @@
// tensor which passes don't look at directly, this isn't an issue.
// RUN: mlir-opt %s -mlir-elide-elementsattrs-if-larger=2 | mlir-opt
-// CHECK: opaque<"", "0xDEADBEEF"> : tensor<3xi32>
+// CHECK: opaque<"_", "0xDEADBEEF"> : tensor<3xi32>
"test.dense_attr"() {foo.dense_attr = dense<[1, 2, 3]> : tensor<3xi32>} : () -> ()
// CHECK: dense<[1, 2]> : tensor<2xi32>
"test.non_elided_dense_attr"() {foo.dense_attr = dense<[1, 2]> : tensor<2xi32>} : () -> ()
-// CHECK: opaque<"", "0xDEADBEEF"> : vector<1x1x1xf16>
+// CHECK: opaque<"_", "0xDEADBEEF"> : vector<1x1x1xf16>
"test.sparse_attr"() {foo.sparse_attr = sparse<[[1, 2, 3]], -2.0> : vector<1x1x1xf16>} : () -> ()
-// CHECK: opaque<"", "0xDEADBEEF"> : tensor<100xf32>
-"test.opaque_attr"() {foo.opaque_attr = opaque<"", "0xEBFE"> : tensor<100xf32> } : () -> ()
+// CHECK: opaque<"_", "0xDEADBEEF"> : tensor<100xf32>
+"test.opaque_attr"() {foo.opaque_attr = opaque<"_", "0xEBFE"> : tensor<100xf32> } : () -> ()
// CHECK: dense<1> : tensor<3xi32>
"test.dense_splat"() {foo.dense_attr = dense<1> : tensor<3xi32>} : () -> ()
diff --git a/mlir/test/mlir-tblgen/attrdefs.td b/mlir/test/mlir-tblgen/attrdefs.td
index 252b9175b05d..fc95fba3c91c 100644
--- a/mlir/test/mlir-tblgen/attrdefs.td
+++ b/mlir/test/mlir-tblgen/attrdefs.td
@@ -95,7 +95,7 @@ def B_CompoundAttrA : TestAttr<"CompoundA"> {
// DEF: return new (allocator.allocate<CompoundAAttrStorage>())
// DEF-NEXT: CompoundAAttrStorage(widthOfSomething, exampleTdType, apFloat, dims, inner);
-// DEF: ::mlir::Type CompoundAAttr::getInner() const { return getImpl()->getType(); }
+// DEF: ::mlir::Type CompoundAAttr::getInner() const { return getImpl()->getType().cast<::mlir::Type>(); }
}
def C_IndexAttr : TestAttr<"Index"> {
diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
index 636d4f8b51ef..a951df92fe18 100644
--- a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
+++ b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
@@ -776,15 +776,19 @@ void DefGenerator::emitDefDef(const AttrOrTypeDef &def) {
// Generate accessor definitions only if we also generate the storage class.
// Otherwise, let the user define the exact accessor definition.
if (def.genAccessors() && def.genStorageClass()) {
- for (const AttrOrTypeParameter ¶meter : parameters) {
- StringRef paramStorageName = isa<AttributeSelfTypeParameter>(parameter)
- ? "getType()"
- : parameter.getName();
-
- SmallString<16> name = parameter.getName();
+ for (const AttrOrTypeParameter ¶m : parameters) {
+ SmallString<32> paramStorageName;
+ if (isa<AttributeSelfTypeParameter>(param)) {
+ Twine("getType().cast<" + param.getCppType() + ">()")
+ .toVector(paramStorageName);
+ } else {
+ paramStorageName = param.getName();
+ }
+
+ SmallString<16> name = param.getName();
name[0] = llvm::toUpper(name[0]);
os << formatv("{0} {3}::get{1}() const {{ return getImpl()->{2}; }\n",
- parameter.getCppType(), name, paramStorageName,
+ param.getCppType(), name, paramStorageName,
def.getCppClassName());
}
}
More information about the Mlir-commits
mailing list