blob: 0312ac7ec1d8df56caa07c3982d30329169ee010 [file] [log] [blame]
//===-- CommonAttrConstraints.td - Common Attr Constraints--*- 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
//
//===----------------------------------------------------------------------===//
//
// This file contains commonly used attr constraints.
//
//===----------------------------------------------------------------------===//
#ifndef COMMON_ATTR_CONSTRAINTS_TD
#define COMMON_ATTR_CONSTRAINTS_TD
include "mlir/IR/Constraints.td"
include "mlir/IR/CommonTypeConstraints.td"
include "mlir/IR/DialectBase.td"
//===----------------------------------------------------------------------===//
// Attribute definitions
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Base attribute definition
// Base class for all attributes.
class Attr<Pred condition, string summary = ""> :
AttrConstraint<condition, summary> {
code storageType = ?; // The backing mlir::Attribute type
code returnType = ?; // The underlying C++ value type
// The call expression to convert from the storage type to the return
// type. For example, an enum can be stored as an int but returned as an
// enum class.
//
// Format: $_self will be expanded to the attribute.
//
// For example, `$_self.getValue().getSExtValue()` for `IntegerAttr val` will
// expand to `getAttrOfType<IntegerAttr>("val").getValue().getSExtValue()`.
code convertFromStorage = "$_self.getValue()";
// The call expression to build an attribute from a constant value.
//
// Format: $0 will be expanded to the constant value of the attribute.
//
// For example, `$_builder.getStringAttr("$0")` for `StringAttr:"foo"` will
// expand to `builder.getStringAttr("foo")`.
string constBuilderCall = ?;
// Default value for attribute.
// Requires a constBuilderCall defined.
string defaultValue = ?;
// The value type of this attribute. This corresponds to the mlir::Type that
// this attribute returns via `getType()`.
Type valueType = ?;
// Whether the attribute is optional. Typically requires a custom
// convertFromStorage method to handle the case where the attribute is
// not present.
bit isOptional = 0;
// What is the base-level Attr instantiation that this Attr is built upon.
// Unset means this is a base-level Attr.
//
// This field is used by attribute wrapper classes (DefaultValuedAttr,
// OptionalAttr, etc.) to retrieve the base-level attribute definition.
// This can be used for getting its name; otherwise, we will see
// "anonymous_<number>" as the attribute def name because of template
// instantiation.
// TOOD(b/132458159): deduplicate the fields in attribute wrapper classes.
Attr baseAttr = ?;
// The fully-qualified C++ namespace where the generated class lives.
string cppNamespace = "";
// The full description of this attribute.
string description = "";
}
// An attribute of a specific dialect.
class DialectAttr<Dialect d, Pred condition, string summary = ""> :
Attr<condition, summary> {
Dialect dialect = d;
let cppNamespace = d.cppNamespace;
}
//===----------------------------------------------------------------------===//
// Attribute modifier definition
// Decorates an attribute to have an (unvalidated) default value if not present.
class DefaultValuedAttr<Attr attr, string val> :
Attr<attr.predicate, attr.summary> {
// Construct this attribute with the input attribute and change only
// the default value.
// Note: this has to be kept up to date with Attr above.
let storageType = attr.storageType;
let returnType = attr.returnType;
let convertFromStorage = attr.convertFromStorage;
let constBuilderCall = attr.constBuilderCall;
let defaultValue = val;
let valueType = attr.valueType;
let baseAttr = attr;
}
// Decorates an optional attribute to have an (unvalidated) default value
// return by ODS generated accessors if not present.
class DefaultValuedOptionalAttr<Attr attr, string val> :
Attr<attr.predicate, attr.summary> {
// Construct this attribute with the input attribute and change only
// the default value.
// Note: this has to be kept up to date with Attr above.
let storageType = attr.storageType;
let returnType = attr.returnType;
let convertFromStorage = attr.convertFromStorage;
let constBuilderCall = attr.constBuilderCall;
let defaultValue = val;
let valueType = attr.valueType;
let isOptional = 1;
let baseAttr = attr;
}
// Decorates an attribute as optional. The return type of the generated
// attribute accessor method will be Optional<>.
class OptionalAttr<Attr attr> : Attr<attr.predicate, attr.summary> {
// Rewrite the attribute to be optional.
// Note: this has to be kept up to date with Attr above.
let storageType = attr.storageType;
let returnType = "::std::optional<" # attr.returnType #">";
let convertFromStorage = "$_self ? " # returnType # "(" #
attr.convertFromStorage # ") : (::std::nullopt)";
let valueType = attr.valueType;
let isOptional = 1;
let baseAttr = attr;
}
// Default-valued string-based attribute. Wraps the default value in escaped
// quotes.
class DefaultValuedStrAttr<Attr attr, string val>
: DefaultValuedAttr<attr, "\"" # val # "\"">;
class DefaultValuedOptionalStrAttr<Attr attr, string val>
: DefaultValuedOptionalAttr<attr, "\"" # val # "\"">;
//===----------------------------------------------------------------------===//
// Primitive attribute kinds
// A generic attribute that must be constructed around a specific buildable type
// `attrValType`. Backed by MLIR attribute kind `attrKind`.
class TypedAttrBase<Type attrValType, string attrKind, Pred condition,
string descr> :
Attr<condition, descr> {
let constBuilderCall = "$_builder.get" # attrKind # "(" #
attrValType.builderCall # ", $0)";
let storageType = "::mlir::" # attrKind;
let valueType = attrValType;
}
// Any attribute.
def AnyAttr : Attr<CPred<"true">, "any attribute"> {
let storageType = "::mlir::Attribute";
let returnType = "::mlir::Attribute";
let convertFromStorage = "$_self";
let constBuilderCall = "$0";
}
// Any attribute from the given list
class AnyAttrOf<list<Attr> allowedAttrs, string summary = "",
string cppClassName = "::mlir::Attribute",
string fromStorage = "$_self"> : Attr<
// Satisfy any of the allowed attribute's condition
Or<!foreach(allowedattr, allowedAttrs, allowedattr.predicate)>,
!if(!eq(summary, ""),
!interleave(!foreach(t, allowedAttrs, t.summary), " or "),
summary)> {
let returnType = cppClassName;
let convertFromStorage = fromStorage;
}
def LocationAttr : Attr<CPred<"::llvm::isa<::mlir::LocationAttr>($_self)">,
"location attribute">;
def BoolAttr : Attr<CPred<"::llvm::isa<::mlir::BoolAttr>($_self)">, "bool attribute"> {
let storageType = [{ ::mlir::BoolAttr }];
let returnType = [{ bool }];
let valueType = I1;
let constBuilderCall = "$_builder.getBoolAttr($0)";
}
// Index attribute.
def IndexAttr :
TypedAttrBase<
Index, "IntegerAttr",
And<[CPred<"::llvm::isa<::mlir::IntegerAttr>($_self)">,
CPred<"::llvm::isa<::mlir::IndexType>(::llvm::cast<::mlir::IntegerAttr>($_self).getType())">]>,
"index attribute"> {
let returnType = [{ ::llvm::APInt }];
}
// Base class for any integer (regardless of signedness semantics) attributes
// of fixed width.
class AnyIntegerAttrBase<AnyI attrValType, string descr> :
TypedAttrBase<
attrValType, "IntegerAttr",
And<[CPred<"::llvm::isa<::mlir::IntegerAttr>($_self)">,
CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getType()."
"isInteger(" # attrValType.bitwidth # ")">]>,
descr> {
let returnType = [{ ::llvm::APInt }];
let constBuilderCall = ?;
}
def AnyI1Attr : AnyIntegerAttrBase<AnyI1, "1-bit integer attribute">;
def AnyI8Attr : AnyIntegerAttrBase<AnyI8, "8-bit integer attribute">;
def AnyI16Attr : AnyIntegerAttrBase<AnyI16, "16-bit integer attribute">;
def AnyI32Attr : AnyIntegerAttrBase<AnyI32, "32-bit integer attribute">;
def AnyI64Attr : AnyIntegerAttrBase<AnyI64, "64-bit integer attribute">;
def APIntAttr : Attr<CPred<"::llvm::isa<::mlir::IntegerAttr>($_self)">,
"arbitrary integer attribute"> {
let storageType = [{ ::mlir::IntegerAttr }];
let returnType = [{ ::mlir::APInt }];
}
// Base class for signless integer attributes of fixed width.
class SignlessIntegerAttrBase<I attrValType, string descr> :
TypedAttrBase<
attrValType, "IntegerAttr",
And<[CPred<"::llvm::isa<::mlir::IntegerAttr>($_self)">,
CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getType()."
"isSignlessInteger(" # attrValType.bitwidth # ")">]>,
descr> {
let returnType = [{ ::llvm::APInt }];
}
// Base class for signless integer attributes of fixed width that have a
// corresponding C++ type.
class TypedSignlessIntegerAttrBase<I attrValType, string retType, string descr>
: SignlessIntegerAttrBase<attrValType, descr> {
let returnType = retType;
let convertFromStorage = "$_self.getValue().getZExtValue()";
}
def I1Attr : TypedSignlessIntegerAttrBase<
I1, "bool", "1-bit signless integer attribute">;
def I8Attr : TypedSignlessIntegerAttrBase<
I8, "uint8_t", "8-bit signless integer attribute">;
def I16Attr : TypedSignlessIntegerAttrBase<
I16, "uint16_t", "16-bit signless integer attribute">;
def I32Attr : TypedSignlessIntegerAttrBase<
I32, "uint32_t", "32-bit signless integer attribute">;
def I64Attr : TypedSignlessIntegerAttrBase<
I64, "uint64_t", "64-bit signless integer attribute">;
// Base class for signed integer attributes of fixed width.
class SignedIntegerAttrBase<SI attrValType, string descr> :
TypedAttrBase<
attrValType, "IntegerAttr",
And<[CPred<"::llvm::isa<::mlir::IntegerAttr>($_self)">,
CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getType()."
"isSignedInteger(" # attrValType.bitwidth # ")">]>,
descr> {
let returnType = [{ ::llvm::APInt }];
}
// Base class for signed integer attributes of fixed width that have a
// corresponding C++ type.
class TypedSignedIntegerAttrBase<SI attrValType, string retType, string descr>
: SignedIntegerAttrBase<attrValType, descr> {
let returnType = retType;
let convertFromStorage = "$_self.getValue().getSExtValue()";
}
def SI1Attr : TypedSignedIntegerAttrBase<
SI1, "bool", "1-bit signed integer attribute">;
def SI8Attr : TypedSignedIntegerAttrBase<
SI8, "int8_t", "8-bit signed integer attribute">;
def SI16Attr : TypedSignedIntegerAttrBase<
SI16, "int16_t", "16-bit signed integer attribute">;
def SI32Attr : TypedSignedIntegerAttrBase<
SI32, "int32_t", "32-bit signed integer attribute">;
def SI64Attr : TypedSignedIntegerAttrBase<
SI64, "int64_t", "64-bit signed integer attribute">;
// Base class for unsigned integer attributes of fixed width.
class UnsignedIntegerAttrBase<UI attrValType, string descr> :
TypedAttrBase<
attrValType, "IntegerAttr",
And<[CPred<"::llvm::isa<::mlir::IntegerAttr>($_self)">,
CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getType()."
"isUnsignedInteger(" # attrValType.bitwidth # ")">]>,
descr> {
let returnType = [{ ::llvm::APInt }];
}
// Base class for unsigned integer attributes of fixed width that have a
// corresponding C++ type.
class TypedUnsignedIntegerAttrBase<UI attrValType, string retType, string descr>
: UnsignedIntegerAttrBase<attrValType, descr> {
let returnType = retType;
let convertFromStorage = "$_self.getValue().getZExtValue()";
}
def UI1Attr : TypedUnsignedIntegerAttrBase<
UI1, "bool", "1-bit unsigned integer attribute">;
def UI8Attr : TypedUnsignedIntegerAttrBase<
UI8, "uint8_t", "8-bit unsigned integer attribute">;
def UI16Attr : TypedUnsignedIntegerAttrBase<
UI16, "uint16_t", "16-bit unsigned integer attribute">;
def UI32Attr : TypedUnsignedIntegerAttrBase<
UI32, "uint32_t", "32-bit unsigned integer attribute">;
def UI64Attr : TypedUnsignedIntegerAttrBase<
UI64, "uint64_t", "64-bit unsigned integer attribute">;
// Base class for float attributes of fixed width.
class FloatAttrBase<F attrValType, string descr> :
TypedAttrBase<attrValType, "FloatAttr",
And<[CPred<"::llvm::isa<::mlir::FloatAttr>($_self)">,
CPred<"::llvm::cast<::mlir::FloatAttr>($_self).getType().isF" #
attrValType.bitwidth # "()">]>,
descr> {
let returnType = [{ ::llvm::APFloat }];
}
def F32Attr : FloatAttrBase<F32, "32-bit float attribute">;
def F64Attr : FloatAttrBase<F64, "64-bit float attribute">;
// An attribute backed by a string type.
class StringBasedAttr<Pred condition, string descr> : Attr<condition, descr> {
let constBuilderCall = "$_builder.getStringAttr($0)";
let storageType = [{ ::mlir::StringAttr }];
let returnType = [{ ::llvm::StringRef }];
let valueType = NoneType;
}
def StrAttr : StringBasedAttr<CPred<"::llvm::isa<::mlir::StringAttr>($_self)">,
"string attribute">;
// A string attribute that represents the name of a symbol.
def SymbolNameAttr : StringBasedAttr<CPred<"::llvm::isa<::mlir::StringAttr>($_self)">,
"string attribute">;
// String attribute that has a specific value type.
class TypedStrAttr<Type ty>
: StringBasedAttr<CPred<"::llvm::isa<::mlir::StringAttr>($_self)">,
"string attribute"> {
let valueType = ty;
}
// Base class for attributes containing types. Example:
// def IntTypeAttr : TypeAttrBase<"IntegerType", "integer type attribute">
// defines a type attribute containing an integer type.
class TypeAttrBase<string retType, string summary,
Pred typePred = CPred<"true">> :
Attr<And<[
CPred<"::llvm::isa<::mlir::TypeAttr>($_self)">,
CPred<"::llvm::isa<" # retType # ">(::llvm::cast<::mlir::TypeAttr>($_self).getValue())">,
SubstLeaves<"$_self",
"::llvm::cast<::mlir::TypeAttr>($_self).getValue()", typePred>]>,
summary> {
let storageType = [{ ::mlir::TypeAttr }];
let returnType = retType;
let valueType = NoneType;
let convertFromStorage = "::llvm::cast<" # retType # ">($_self.getValue())";
}
def TypeAttr : TypeAttrBase<"::mlir::Type", "any type attribute"> {
let constBuilderCall = "::mlir::TypeAttr::get($0)";
}
class TypeAttrOf<Type ty>
: TypeAttrBase<ty.cppClassName, "type attribute of " # ty.summary,
ty.predicate> {
let constBuilderCall = "::mlir::TypeAttr::get($0)";
}
// The mere presence of unit attributes has a meaning. Therefore, unit
// attributes are always treated as optional and accessors to them return
// "true" if the attribute is present and "false" otherwise.
def UnitAttr : Attr<CPred<"::llvm::isa<::mlir::UnitAttr>($_self)">, "unit attribute"> {
let storageType = [{ ::mlir::UnitAttr }];
let constBuilderCall = "(($0) ? $_builder.getUnitAttr() : nullptr)";
let convertFromStorage = "$_self != nullptr";
let returnType = "bool";
let defaultValue = "false";
let valueType = NoneType;
let isOptional = 1;
}
//===----------------------------------------------------------------------===//
// Composite attribute kinds
class DictionaryAttrBase<Pred condition, string summary> :
Attr<condition, summary> {
let storageType = [{ ::mlir::DictionaryAttr }];
let constBuilderCall = "$_builder.getDictionaryAttr($0)";
let returnType = [{ ::mlir::DictionaryAttr }];
let valueType = NoneType;
let convertFromStorage = "$_self";
}
def DictionaryAttr
: DictionaryAttrBase<CPred<"::llvm::isa<::mlir::DictionaryAttr>($_self)">,
"dictionary of named attribute values">;
class ElementsAttrBase<Pred condition, string summary> :
Attr<condition, summary> {
let storageType = [{ ::mlir::ElementsAttr }];
let returnType = [{ ::mlir::ElementsAttr }];
let convertFromStorage = "$_self";
}
def ElementsAttr : ElementsAttrBase<CPred<"::llvm::isa<::mlir::ElementsAttr>($_self)">,
"constant vector/tensor attribute">;
class IntElementsAttrBase<Pred condition, string summary> :
ElementsAttrBase<And<[CPred<"::llvm::isa<::mlir::DenseIntElementsAttr>($_self)">,
condition]>,
summary> {
let storageType = [{ ::mlir::DenseIntElementsAttr }];
let returnType = [{ ::mlir::DenseIntElementsAttr }];
let convertFromStorage = "$_self";
}
class DenseArrayAttrBase<string denseAttrName, string cppType, string summaryName> :
ElementsAttrBase<CPred<"::llvm::isa<::mlir::" # denseAttrName # ">($_self)">,
summaryName # " dense array attribute"> {
let storageType = "::mlir::" # denseAttrName;
let returnType = "::llvm::ArrayRef<" # cppType # ">";
let constBuilderCall = "$_builder.get" # denseAttrName # "($0)";
}
def DenseBoolArrayAttr : DenseArrayAttrBase<"DenseBoolArrayAttr", "bool", "i1">;
def DenseI8ArrayAttr : DenseArrayAttrBase<"DenseI8ArrayAttr", "int8_t", "i8">;
def DenseI16ArrayAttr : DenseArrayAttrBase<"DenseI16ArrayAttr", "int16_t", "i16">;
def DenseI32ArrayAttr : DenseArrayAttrBase<"DenseI32ArrayAttr", "int32_t", "i32">;
def DenseI64ArrayAttr : DenseArrayAttrBase<"DenseI64ArrayAttr", "int64_t", "i64">;
def DenseF32ArrayAttr : DenseArrayAttrBase<"DenseF32ArrayAttr", "float", "f32">;
def DenseF64ArrayAttr : DenseArrayAttrBase<"DenseF64ArrayAttr", "double", "f64">;
def IndexElementsAttr
: IntElementsAttrBase<CPred<[{::llvm::cast<::mlir::DenseIntElementsAttr>($_self)
.getType()
.getElementType()
.isIndex()}]>,
"index elements attribute">;
def AnyIntElementsAttr : IntElementsAttrBase<CPred<"true">, "integer elements attribute">;
class IntElementsAttrOf<int width> : IntElementsAttrBase<
CPred<"::llvm::cast<::mlir::DenseIntElementsAttr>($_self).getType()."
"getElementType().isInteger(" # width # ")">,
width # "-bit integer elements attribute">;
def AnyI32ElementsAttr : IntElementsAttrOf<32>;
def AnyI64ElementsAttr : IntElementsAttrOf<64>;
class SignlessIntElementsAttr<int width> : IntElementsAttrBase<
CPred<"::llvm::cast<::mlir::DenseIntElementsAttr>($_self).getType()."
"getElementType().isSignlessInteger(" # width # ")">,
width # "-bit signless integer elements attribute"> {
// Note that this is only constructing scalar elements attribute.
let constBuilderCall = "::llvm::cast<::mlir::DenseIntElementsAttr>("
"::mlir::DenseElementsAttr::get("
"::mlir::RankedTensorType::get({}, $_builder.getIntegerType(" # width # ")), "
"::llvm::ArrayRef($0)))";
}
def I32ElementsAttr : SignlessIntElementsAttr<32>;
def I64ElementsAttr : SignlessIntElementsAttr<64>;
// A `width`-bit signless integer elements attribute. The attribute should be
// ranked and has a shape as specified in `dims`.
class RankedSignlessIntElementsAttr<int width, list<int> dims> :
SignlessIntElementsAttr<width> {
// Check that this has the specified shape.
let predicate = And<[
SignlessIntElementsAttr<width>.predicate,
CPred<"::llvm::cast<::mlir::DenseIntElementsAttr>($_self).getType().getShape() == "
"::mlir::ArrayRef<int64_t>({" # !interleave(dims, ", ") # "})">]>;
let summary = width # "-bit signless int elements attribute of shape [" #
!interleave(dims, ", ") # "]";
let constBuilderCall = "::mlir::DenseIntElementsAttr::get("
"::mlir::RankedTensorType::get({" # !interleave(dims, ", ") #
"}, $_builder.getIntegerType(" # width # ")), ::llvm::ArrayRef($0))";
}
class RankedI32ElementsAttr<list<int> dims> :
RankedSignlessIntElementsAttr<32, dims>;
class RankedI64ElementsAttr<list<int> dims> :
RankedSignlessIntElementsAttr<64, dims>;
class FloatElementsAttr<int width> : ElementsAttrBase<
CPred<"::llvm::isa<::mlir::DenseFPElementsAttr>($_self) &&"
"::llvm::cast<::mlir::DenseElementsAttr>($_self).getType()."
"getElementType().isF" # width # "()">,
width # "-bit float elements attribute"> {
let storageType = [{ ::mlir::DenseElementsAttr }];
let returnType = [{ ::mlir::DenseElementsAttr }];
// Note that this is only constructing scalar elements attribute.
let constBuilderCall = "::mlir::DenseElementsAttr::get("
"::mlir::RankedTensorType::get({}, $_builder.getF" # width # "Type()),"
"::llvm::ArrayRef($0))";
let convertFromStorage = "$_self";
}
def F64ElementsAttr : FloatElementsAttr<64>;
// A `width`-bit floating point elements attribute. The attribute should be
// ranked and has a shape as specified in `dims`.
class RankedFloatElementsAttr<int width, list<int> dims> : ElementsAttrBase<
CPred<"::llvm::isa<::mlir::DenseFPElementsAttr>($_self) &&"
"::llvm::cast<::mlir::DenseFPElementsAttr>($_self).getType()."
"getElementType().isF" # width # "() && "
// Check that this is ranked and has the specified shape.
"::llvm::cast<::mlir::DenseFPElementsAttr>($_self).getType().hasRank() && "
"::llvm::cast<::mlir::DenseFPElementsAttr>($_self).getType().getShape() == "
"::mlir::ArrayRef<int64_t>({" # !interleave(dims, ", ") # "})">,
width # "-bit float elements attribute of shape [" #
!interleave(dims, ", ") # "]"> {
let storageType = [{ ::mlir::DenseFPElementsAttr }];
let returnType = [{ ::mlir::DenseFPElementsAttr }];
let constBuilderCall = "::llvm::cast<::mlir::DenseFPElementsAttr>("
"::mlir::DenseElementsAttr::get("
"::mlir::RankedTensorType::get({" # !interleave(dims, ", ") #
"}, $_builder.getF" # width # "Type()), "
"::llvm::ArrayRef($0)))";
let convertFromStorage = "$_self";
}
class RankedF32ElementsAttr<list<int> dims> : RankedFloatElementsAttr<32, dims>;
class RankedF64ElementsAttr<list<int> dims> : RankedFloatElementsAttr<64, dims>;
def StringElementsAttr : ElementsAttrBase<
CPred<"::llvm::isa<::mlir::DenseStringElementsAttr>($_self)" >,
"string elements attribute"> {
let storageType = [{ ::mlir::DenseElementsAttr }];
let returnType = [{ ::mlir::DenseElementsAttr }];
let convertFromStorage = "$_self";
}
// Attributes containing affine maps.
def AffineMapAttr : Attr<
CPred<"::llvm::isa<::mlir::AffineMapAttr>($_self)">, "AffineMap attribute"> {
let storageType = [{::mlir::AffineMapAttr }];
let returnType = [{ ::mlir::AffineMap }];
let valueType = Index;
let constBuilderCall = "::mlir::AffineMapAttr::get($0)";
}
// Base class for array attributes.
class ArrayAttrBase<Pred condition, string summary> : Attr<condition, summary> {
let storageType = [{ ::mlir::ArrayAttr }];
let returnType = [{ ::mlir::ArrayAttr }];
let valueType = NoneType;
let convertFromStorage = "$_self";
let constBuilderCall = "$_builder.getArrayAttr($0)";
}
def ArrayAttr : ArrayAttrBase<CPred<"::llvm::isa<::mlir::ArrayAttr>($_self)">,
"array attribute">;
// Base class for array attributes whose elements are of the same kind.
// `element` specifies the element attribute kind stored in this array.
class TypedArrayAttrBase<Attr element, string summary>: ArrayAttrBase<
And<[
// Guarantee this is an ArrayAttr first
CPred<"::llvm::isa<::mlir::ArrayAttr>($_self)">,
// Guarantee all elements satisfy the constraints from `element`
Concat<"::llvm::all_of(::llvm::cast<::mlir::ArrayAttr>($_self), "
"[&](::mlir::Attribute attr) { return attr && (",
SubstLeaves<"$_self", "attr", element.predicate>,
"); })">]>,
summary> {
Attr elementAttr = element;
}
def LocationArrayAttr : TypedArrayAttrBase<LocationAttr,
"location array attribute">;
def AffineMapArrayAttr : TypedArrayAttrBase<AffineMapAttr,
"AffineMap array attribute"> {
let constBuilderCall = "$_builder.getAffineMapArrayAttr($0)";
}
def BoolArrayAttr : TypedArrayAttrBase<BoolAttr,
"1-bit boolean array attribute"> {
let constBuilderCall = "$_builder.getBoolArrayAttr($0)";
}
def I32ArrayAttr : TypedArrayAttrBase<I32Attr,
"32-bit integer array attribute"> {
let constBuilderCall = "$_builder.getI32ArrayAttr($0)";
}
def I64ArrayAttr : TypedArrayAttrBase<I64Attr,
"64-bit integer array attribute"> {
let constBuilderCall = "$_builder.getI64ArrayAttr($0)";
}
// Variant of I64ArrayAttr whose user accessor is SmallVector<in64_t>.
def I64SmallVectorArrayAttr :
TypedArrayAttrBase<I64Attr, "64-bit integer array attribute"> {
let returnType = [{ ::llvm::SmallVector<int64_t, 8> }];
let convertFromStorage = [{
llvm::to_vector<4>(
llvm::map_range($_self.getAsRange<mlir::IntegerAttr>(),
[](mlir::IntegerAttr attr) { return attr.getInt(); }));
}];
let constBuilderCall = "$_builder.getI64ArrayAttr($0)";
}
def F32ArrayAttr : TypedArrayAttrBase<F32Attr, "32-bit float array attribute"> {
let constBuilderCall = "$_builder.getF32ArrayAttr($0)";
}
def F64ArrayAttr : TypedArrayAttrBase<F64Attr, "64-bit float array attribute"> {
let constBuilderCall = "$_builder.getF64ArrayAttr($0)";
}
def StrArrayAttr : TypedArrayAttrBase<StrAttr, "string array attribute"> {
let constBuilderCall = "$_builder.getStrArrayAttr($0)";
}
def TypeArrayAttr : TypedArrayAttrBase<TypeAttr, "type array attribute"> {
let constBuilderCall = "$_builder.getTypeArrayAttr($0)";
}
def IndexListArrayAttr :
TypedArrayAttrBase<I64ArrayAttr, "Array of 64-bit integer array attributes">;
def DictArrayAttr :
TypedArrayAttrBase<DictionaryAttr, "Array of dictionary attributes">;
// Attributes containing symbol references.
def SymbolRefAttr : Attr<CPred<"::llvm::isa<::mlir::SymbolRefAttr>($_self)">,
"symbol reference attribute"> {
let storageType = [{ ::mlir::SymbolRefAttr }];
let returnType = [{ ::mlir::SymbolRefAttr }];
let valueType = NoneType;
let constBuilderCall =
"::mlir::SymbolRefAttr::get($_builder.getContext(), $0)";
let convertFromStorage = "$_self";
}
def FlatSymbolRefAttr : Attr<CPred<"::llvm::isa<::mlir::FlatSymbolRefAttr>($_self)">,
"flat symbol reference attribute"> {
let storageType = [{ ::mlir::FlatSymbolRefAttr }];
let returnType = [{ ::llvm::StringRef }];
let valueType = NoneType;
let constBuilderCall =
"::mlir::SymbolRefAttr::get($_builder.getContext(), $0)";
let convertFromStorage = "$_self.getValue()";
}
def SymbolRefArrayAttr :
TypedArrayAttrBase<SymbolRefAttr, "symbol ref array attribute"> {
let constBuilderCall = ?;
}
def FlatSymbolRefArrayAttr :
TypedArrayAttrBase<FlatSymbolRefAttr, "flat symbol ref array attribute"> {
let constBuilderCall = ?;
}
//===----------------------------------------------------------------------===//
// Derive attribute kinds
// DerivedAttr are attributes whose value is computed from properties
// of the operation. They do not require additional storage and are
// materialized as needed.
// Note: All derived attributes should be materializable as an Attribute. E.g.,
// do not use DerivedAttr for things that could not have been stored as
// Attribute.
//
class DerivedAttr<code ret, code b, code convert = ""> :
Attr<CPred<"true">, "derived attribute"> {
let returnType = ret;
code body = b;
// Specify how to convert from the derived attribute to an attribute.
//
// ## Special placeholders
//
// Special placeholders can be used to refer to entities during conversion:
//
// * `$_builder` will be replaced by a mlir::Builder instance.
// * `$_ctxt` will be replaced by the MLIRContext* instance.
// * `$_self` will be replaced with the derived attribute (value produces
// `returnType`).
let convertFromStorage = convert;
}
// Derived attribute that returns a mlir::Type.
class DerivedTypeAttr<code body> : DerivedAttr<"::mlir::Type", body> {
let convertFromStorage = "::mlir::TypeAttr::get($_self)";
}
//===----------------------------------------------------------------------===//
// Constant attribute kinds
// Represents a constant attribute of specific Attr type. A constant
// attribute can be specified only of attributes that have a constant
// builder call defined. The constant value is specified as a string.
//
// If used as a constraint, it generates a matcher on a constant attribute by
// using the constant value builder of the attribute and the value.
class ConstantAttr<Attr attribute, string val> : AttrConstraint<
CPred<"$_self == " # !subst("$0", val, attribute.constBuilderCall)>,
"constant attribute " # val> {
Attr attr = attribute;
string value = val;
}
class ConstF32Attr<string val> : ConstantAttr<F32Attr, val>;
def ConstBoolAttrFalse : ConstantAttr<BoolAttr, "false">;
def ConstBoolAttrTrue : ConstantAttr<BoolAttr, "true">;
def ConstUnitAttr : ConstantAttr<UnitAttr, "true">;
// Constant string-based attribute. Wraps the desired string in escaped quotes.
class ConstantStrAttr<Attr attribute, string val>
: ConstantAttr<attribute, "\"" # val # "\"">;
//===----------------------------------------------------------------------===//
// Common attribute constraints
//===----------------------------------------------------------------------===//
// A general mechanism to further confine the given `attr` with all the
// `constraints`. This allows to compose complex constraints out of a series
// of more primitive ones.
class ConfinedAttr<Attr attr, list<AttrConstraint> constraints> : Attr<
And<!listconcat([attr.predicate],
!foreach(pred, constraints, pred.predicate))>,
!foldl(/*init*/attr.summary, /*list*/constraints,
prev, cur, prev # " " # cur.summary)> {
let storageType = attr.storageType;
let returnType = attr.returnType;
let convertFromStorage = attr.convertFromStorage;
let constBuilderCall = attr.constBuilderCall;
let defaultValue = attr.defaultValue;
let valueType = attr.valueType;
let isOptional = attr.isOptional;
let baseAttr = attr;
}
// An AttrConstraint that holds if all attr constraints specified in
// 'constraints' hold.
class AllAttrOf<list<AttrConstraint> constraints> : AttrConstraint<
And<!listconcat([!head(constraints).predicate],
!foreach(pred, !tail(constraints), pred.predicate))>,
!interleave(!foreach(con, constraints, con.summary), " and ")> {
}
class IntNEQValue<int n> : AttrConstraint<
CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getInt() != " # n>,
"whose minimum value is " # n>;
class IntMinValue<int n> : AttrConstraint<
CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getInt() >= " # n>,
"whose minimum value is " # n>;
class IntMaxValue<int n> : AttrConstraint<
CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getInt() <= " # n>,
"whose maximum value is " # n>;
def IntNonNegative : AttrConstraint<
CPred<"!::llvm::cast<::mlir::IntegerAttr>($_self).getValue().isNegative()">,
"whose value is non-negative">;
def IntPositive : AttrConstraint<
CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getValue().isStrictlyPositive()">,
"whose value is positive">;
class ArrayMinCount<int n> : AttrConstraint<
CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() >= " # n>,
"with at least " # n # " elements">;
class ArrayCount<int n> : AttrConstraint<
CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() == " #n>,
"with exactly " # n # " elements">;
class DenseArrayCount<int n> : AttrConstraint<
CPred<"::llvm::cast<::mlir::DenseArrayAttr>($_self).size() == " #n>,
"with exactly " # n # " elements">;
class DenseArrayStrictlyPositive<DenseArrayAttrBase arrayType> : AttrConstraint<
CPred<"::llvm::all_of(::llvm::cast<" # arrayType #">($_self).asArrayRef(), "
"[&](auto v) { return v > 0; })">,
"whose value is positive">;
class DenseArrayNonNegative<DenseArrayAttrBase arrayType> : AttrConstraint<
CPred<"::llvm::all_of(::llvm::cast<" # arrayType #">($_self).asArrayRef(), "
"[&](auto v) { return v >= 0; })">,
"whose value is non-negative">;
class DenseArraySorted<DenseArrayAttrBase arrayType> : AttrConstraint<
CPred<"llvm::is_sorted(::llvm::cast<" # arrayType # ">($_self).asArrayRef())">,
"should be in non-decreasing order">;
class DenseArrayStrictlySorted<DenseArrayAttrBase arrayType> : AttrConstraint<
And<[
CPred<"llvm::is_sorted(::llvm::cast<" # arrayType # ">($_self).asArrayRef())">,
// Check that no two adjacent elements are the same.
CPred<"[](" # arrayType.returnType # " a) {\n"
"return std::adjacent_find(std::begin(a), std::end(a)) == "
"std::end(a);\n"
"}(::llvm::cast<" # arrayType # ">($_self).asArrayRef())"
>]>,
"should be in increasing order">;
class IntArrayNthElemEq<int index, int value> : AttrConstraint<
And<[
CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() > " # index>,
CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<::mlir::ArrayAttr>($_self)["
# index # "]).getInt() == " # value>
]>,
"whose " # index # "-th element must be " # value>;
class IntArrayNthElemMinValue<int index, int min> : AttrConstraint<
And<[
CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() > " # index>,
CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<::mlir::ArrayAttr>($_self)["
# index # "]).getInt() >= " # min>
]>,
"whose " # index # "-th element must be at least " # min>;
class IntArrayNthElemMaxValue<int index, int max> : AttrConstraint<
And<[
CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() > " # index>,
CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<::mlir::ArrayAttr>($_self)["
# index # "]).getInt() <= " # max>
]>,
"whose " # index # "-th element must be at most " # max>;
class IntArrayNthElemInRange<int index, int min, int max> : AttrConstraint<
And<[
CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() > " # index>,
CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<::mlir::ArrayAttr>($_self)["
# index # "]).getInt() >= " # min>,
CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<::mlir::ArrayAttr>($_self)["
# index # "]).getInt() <= " # max>
]>,
"whose " # index # "-th element must be at least " # min # " and at most " # max>;
def IsNullAttr : AttrConstraint<
CPred<"!$_self">, "empty attribute (for optional attributes)">;
#endif // COMMON_ATTR_CONSTRAINTS_TD