659 lines
22 KiB
TableGen
659 lines
22 KiB
TableGen
//===-- LLVMInterfaces.td - LLVM Interfaces ----------------*- 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 defines interfaces for the LLVM dialect in MLIR.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVMIR_INTERFACES
|
|
#define LLVMIR_INTERFACES
|
|
|
|
include "mlir/IR/OpBase.td"
|
|
include "mlir/Interfaces/DataLayoutInterfaces.td"
|
|
|
|
def FastmathFlagsInterface : OpInterface<"FastmathFlagsInterface"> {
|
|
let description = [{
|
|
Access to op fastmath flags.
|
|
}];
|
|
|
|
let cppNamespace = "::mlir::LLVM";
|
|
|
|
let methods = [
|
|
InterfaceMethod<
|
|
/*desc=*/ "Returns a FastmathFlagsAttr attribute for the operation",
|
|
/*returnType=*/ "::mlir::LLVM::FastmathFlagsAttr",
|
|
/*methodName=*/ "getFastmathAttr",
|
|
/*args=*/ (ins),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
auto op = cast<ConcreteOp>(this->getOperation());
|
|
return op.getFastmathFlagsAttr();
|
|
}]
|
|
>,
|
|
StaticInterfaceMethod<
|
|
/*desc=*/ [{Returns the name of the FastmathFlagsAttr attribute
|
|
for the operation}],
|
|
/*returnType=*/ "::llvm::StringRef",
|
|
/*methodName=*/ "getFastmathAttrName",
|
|
/*args=*/ (ins),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
return "fastmathFlags";
|
|
}]
|
|
>
|
|
];
|
|
}
|
|
|
|
def IntegerOverflowFlagsInterface : OpInterface<"IntegerOverflowFlagsInterface"> {
|
|
let description = [{
|
|
This interface defines an LLVM operation with integer overflow flags and
|
|
provides a uniform API for accessing them.
|
|
}];
|
|
|
|
let cppNamespace = "::mlir::LLVM";
|
|
|
|
let methods = [
|
|
InterfaceMethod<[{
|
|
Get the integer overflow flags for the operation.
|
|
}], "IntegerOverflowFlags", "getOverflowFlags", (ins), [{}], [{
|
|
return $_op.getProperties().overflowFlags;
|
|
}]>,
|
|
InterfaceMethod<[{
|
|
Set the integer overflow flags for the operation.
|
|
}], "void", "setOverflowFlags", (ins "IntegerOverflowFlags":$flags), [{}], [{
|
|
$_op.getProperties().overflowFlags = flags;
|
|
}]>,
|
|
InterfaceMethod<[{
|
|
Returns whether the operation has the No Unsigned Wrap keyword.
|
|
}], "bool", "hasNoUnsignedWrap", (ins), [{}], [{
|
|
return bitEnumContainsAll($_op.getOverflowFlags(),
|
|
IntegerOverflowFlags::nuw);
|
|
}]>,
|
|
InterfaceMethod<[{
|
|
Returns whether the operation has the No Signed Wrap keyword.
|
|
}], "bool", "hasNoSignedWrap", (ins), [{}], [{
|
|
return bitEnumContainsAll($_op.getOverflowFlags(),
|
|
IntegerOverflowFlags::nsw);
|
|
}]>,
|
|
StaticInterfaceMethod<[{
|
|
Get the attribute name of the overflow flags property.
|
|
}], "StringRef", "getOverflowFlagsAttrName", (ins), [{}], [{
|
|
return "overflowFlags";
|
|
}]>,
|
|
];
|
|
}
|
|
|
|
def ExactFlagInterface : OpInterface<"ExactFlagInterface"> {
|
|
let description = [{
|
|
This interface defines an LLVM operation with an exact flag and
|
|
provides a uniform API for accessing it.
|
|
}];
|
|
|
|
let cppNamespace = "::mlir::LLVM";
|
|
|
|
let methods = [
|
|
InterfaceMethod<[{
|
|
Get the exact flag for the operation.
|
|
}], "bool", "getIsExact", (ins), [{}], [{
|
|
return $_op.getProperties().isExact;
|
|
}]>,
|
|
InterfaceMethod<[{
|
|
Set the exact flag for the operation.
|
|
}], "void", "setIsExact", (ins "bool":$isExact), [{}], [{
|
|
$_op.getProperties().isExact = isExact;
|
|
}]>,
|
|
StaticInterfaceMethod<[{
|
|
Get the attribute name of the isExact property.
|
|
}], "StringRef", "getIsExactName", (ins), [{}], [{
|
|
return "isExact";
|
|
}]>,
|
|
];
|
|
}
|
|
|
|
def DisjointFlagInterface : OpInterface<"DisjointFlagInterface"> {
|
|
let description = [{
|
|
This interface defines an LLVM operation with a disjoint flag and
|
|
provides a uniform API for accessing it.
|
|
}];
|
|
|
|
let cppNamespace = "::mlir::LLVM";
|
|
|
|
let methods = [
|
|
InterfaceMethod<[{
|
|
Get the disjoint flag for the operation.
|
|
}], "bool", "getIsDisjoint", (ins), [{}], [{
|
|
return $_op.getProperties().isDisjoint;
|
|
}]>,
|
|
InterfaceMethod<[{
|
|
Set the disjoint flag for the operation.
|
|
}], "void", "setIsDisjoint", (ins "bool":$isDisjoint), [{}], [{
|
|
$_op.getProperties().isDisjoint = isDisjoint;
|
|
}]>,
|
|
StaticInterfaceMethod<[{
|
|
Get the attribute name of the isDisjoint property.
|
|
}], "StringRef", "getIsDisjointName", (ins), [{}], [{
|
|
return "isDisjoint";
|
|
}]>,
|
|
];
|
|
}
|
|
|
|
def NonNegFlagInterface : OpInterface<"NonNegFlagInterface"> {
|
|
let description = [{
|
|
This interface defines an LLVM operation with an nneg flag and
|
|
provides a uniform API for accessing it.
|
|
}];
|
|
|
|
let cppNamespace = "::mlir::LLVM";
|
|
|
|
let methods = [
|
|
InterfaceMethod<[{
|
|
Get the nneg flag for the operation.
|
|
}], "bool", "getNonNeg", (ins), [{}], [{
|
|
return $_op.getProperties().nonNeg;
|
|
}]>,
|
|
InterfaceMethod<[{
|
|
Set the nneg flag for the operation.
|
|
}], "void", "setNonNeg", (ins "bool":$nonNeg), [{}], [{
|
|
$_op.getProperties().nonNeg = nonNeg;
|
|
}]>,
|
|
StaticInterfaceMethod<[{
|
|
Get the attribute name of the nonNeg property.
|
|
}], "StringRef", "getNonNegName", (ins), [{}], [{
|
|
return "nonNeg";
|
|
}]>,
|
|
];
|
|
}
|
|
|
|
def AccessGroupOpInterface : OpInterface<"AccessGroupOpInterface"> {
|
|
let description = [{
|
|
An interface for memory operations that can carry access groups metadata.
|
|
It provides setters and getters for the operation's access groups attribute.
|
|
The default implementations of the interface methods expect the operation
|
|
to have an attribute of type ArrayAttr named access_groups.
|
|
}];
|
|
|
|
let cppNamespace = "::mlir::LLVM";
|
|
let verify = [{ return detail::verifyAccessGroupOpInterface($_op); }];
|
|
|
|
let methods = [
|
|
InterfaceMethod<
|
|
/*desc=*/ "Returns the access groups attribute or nullptr",
|
|
/*returnType=*/ "::mlir::ArrayAttr",
|
|
/*methodName=*/ "getAccessGroupsOrNull",
|
|
/*args=*/ (ins),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
auto op = cast<ConcreteOp>(this->getOperation());
|
|
return op.getAccessGroupsAttr();
|
|
}]
|
|
>,
|
|
InterfaceMethod<
|
|
/*desc=*/ "Sets the access groups attribute",
|
|
/*returnType=*/ "void",
|
|
/*methodName=*/ "setAccessGroups",
|
|
/*args=*/ (ins "const ::mlir::ArrayAttr":$attr),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
auto op = cast<ConcreteOp>(this->getOperation());
|
|
op.setAccessGroupsAttr(attr);
|
|
}]
|
|
>
|
|
];
|
|
}
|
|
|
|
def AliasAnalysisOpInterface : OpInterface<"AliasAnalysisOpInterface"> {
|
|
let description = [{
|
|
An interface for memory operations that can carry alias analysis metadata.
|
|
It provides setters and getters for the operation's alias analysis
|
|
attributes. The default implementations of the interface methods expect
|
|
the operation to have attributes of type ArrayAttr named alias_scopes,
|
|
noalias_scopes, and tbaa.
|
|
}];
|
|
|
|
let cppNamespace = "::mlir::LLVM";
|
|
let verify = [{ return detail::verifyAliasAnalysisOpInterface($_op); }];
|
|
|
|
let methods = [
|
|
InterfaceMethod<
|
|
/*desc=*/ "Returns the alias scopes attribute or nullptr",
|
|
/*returnType=*/ "::mlir::ArrayAttr",
|
|
/*methodName=*/ "getAliasScopesOrNull",
|
|
/*args=*/ (ins),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
auto op = cast<ConcreteOp>(this->getOperation());
|
|
return op.getAliasScopesAttr();
|
|
}]
|
|
>,
|
|
InterfaceMethod<
|
|
/*desc=*/ "Sets the alias scopes attribute",
|
|
/*returnType=*/ "void",
|
|
/*methodName=*/ "setAliasScopes",
|
|
/*args=*/ (ins "const ::mlir::ArrayAttr":$attr),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
auto op = cast<ConcreteOp>(this->getOperation());
|
|
op.setAliasScopesAttr(attr);
|
|
}]
|
|
>,
|
|
InterfaceMethod<
|
|
/*desc=*/ "Returns the noalias scopes attribute or nullptr",
|
|
/*returnType=*/ "::mlir::ArrayAttr",
|
|
/*methodName=*/ "getNoAliasScopesOrNull",
|
|
/*args=*/ (ins),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
auto op = cast<ConcreteOp>(this->getOperation());
|
|
return op.getNoaliasScopesAttr();
|
|
}]
|
|
>,
|
|
InterfaceMethod<
|
|
/*desc=*/ "Sets the noalias scopes attribute",
|
|
/*returnType=*/ "void",
|
|
/*methodName=*/ "setNoAliasScopes",
|
|
/*args=*/ (ins "const ::mlir::ArrayAttr":$attr),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
auto op = cast<ConcreteOp>(this->getOperation());
|
|
op.setNoaliasScopesAttr(attr);
|
|
}]
|
|
>,
|
|
InterfaceMethod<
|
|
/*desc=*/ "Returns the tbaa attribute or nullptr",
|
|
/*returnType=*/ "::mlir::ArrayAttr",
|
|
/*methodName=*/ "getTBAATagsOrNull",
|
|
/*args=*/ (ins),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
auto op = cast<ConcreteOp>(this->getOperation());
|
|
return op.getTbaaAttr();
|
|
}]
|
|
>,
|
|
InterfaceMethod<
|
|
/*desc=*/ "Sets the tbaa attribute",
|
|
/*returnType=*/ "void",
|
|
/*methodName=*/ "setTBAATags",
|
|
/*args=*/ (ins "const ::mlir::ArrayAttr":$attr),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
auto op = cast<ConcreteOp>(this->getOperation());
|
|
op.setTbaaAttr(attr);
|
|
}]
|
|
>,
|
|
InterfaceMethod<
|
|
/*desc=*/ "Returns a list of all pointer operands accessed by the "
|
|
"operation",
|
|
/*returnType=*/ "::llvm::SmallVector<::mlir::Value>",
|
|
/*methodName=*/ "getAccessedOperands",
|
|
/*args=*/ (ins)
|
|
>
|
|
];
|
|
}
|
|
|
|
def DereferenceableOpInterface : OpInterface<"DereferenceableOpInterface"> {
|
|
let description = [{
|
|
An interface for memory operations that can carry dereferenceable metadata.
|
|
It provides setters and getters for the operation's dereferenceable
|
|
attributes. The default implementations of the interface methods expect
|
|
the operation to have an attribute of type DereferenceableAttr.
|
|
}];
|
|
|
|
let cppNamespace = "::mlir::LLVM";
|
|
let verify = [{ return detail::verifyDereferenceableOpInterface($_op); }];
|
|
|
|
let methods = [
|
|
InterfaceMethod<
|
|
/*desc=*/ "Returns the dereferenceable attribute or nullptr",
|
|
/*returnType=*/ "::mlir::LLVM::DereferenceableAttr",
|
|
/*methodName=*/ "getDereferenceableOrNull",
|
|
/*args=*/ (ins),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
auto op = cast<ConcreteOp>(this->getOperation());
|
|
return op.getDereferenceableAttr();
|
|
}]
|
|
>,
|
|
InterfaceMethod<
|
|
/*desc=*/ "Sets the dereferenceable attribute",
|
|
/*returnType=*/ "void",
|
|
/*methodName=*/ "setDereferenceable",
|
|
/*args=*/ (ins "::mlir::LLVM::DereferenceableAttr":$attr),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
auto op = cast<ConcreteOp>(this->getOperation());
|
|
op.setDereferenceableAttr(attr);
|
|
}]
|
|
>
|
|
];
|
|
}
|
|
|
|
def FPExceptionBehaviorOpInterface : OpInterface<"FPExceptionBehaviorOpInterface"> {
|
|
let description = [{
|
|
An interface for operations receiving an exception behavior attribute
|
|
controlling FP exception behavior.
|
|
}];
|
|
|
|
let cppNamespace = "::mlir::LLVM";
|
|
|
|
let methods = [
|
|
InterfaceMethod<
|
|
/*desc=*/ "Returns a FPExceptionBehavior attribute for the operation",
|
|
/*returnType=*/ "::mlir::LLVM::FPExceptionBehaviorAttr",
|
|
/*methodName=*/ "getFPExceptionBehaviorAttr",
|
|
/*args=*/ (ins),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
auto op = cast<ConcreteOp>(this->getOperation());
|
|
return op.getFpExceptionBehaviorAttr();
|
|
}]
|
|
>,
|
|
StaticInterfaceMethod<
|
|
/*desc=*/ [{Returns the name of the FPExceptionBehaviorAttr
|
|
attribute for the operation}],
|
|
/*returnType=*/ "::llvm::StringRef",
|
|
/*methodName=*/ "getFPExceptionBehaviorAttrName",
|
|
/*args=*/ (ins),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
return "fpExceptionBehavior";
|
|
}]
|
|
>
|
|
];
|
|
}
|
|
|
|
def RoundingModeOpInterface : OpInterface<"RoundingModeOpInterface"> {
|
|
let description = [{
|
|
An interface for operations receiving a rounding mode attribute
|
|
controlling FP rounding mode.
|
|
}];
|
|
|
|
let cppNamespace = "::mlir::LLVM";
|
|
|
|
let methods = [
|
|
InterfaceMethod<
|
|
/*desc=*/ "Returns a RoundingMode attribute for the operation",
|
|
/*returnType=*/ "::mlir::LLVM::RoundingModeAttr",
|
|
/*methodName=*/ "getRoundingModeAttr",
|
|
/*args=*/ (ins),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
auto op = cast<ConcreteOp>(this->getOperation());
|
|
return op.getRoundingmodeAttr();
|
|
}]
|
|
>,
|
|
StaticInterfaceMethod<
|
|
/*desc=*/ [{Returns the name of the RoundingModeAttr attribute
|
|
for the operation}],
|
|
/*returnType=*/ "::llvm::StringRef",
|
|
/*methodName=*/ "getRoundingModeAttrName",
|
|
/*args=*/ (ins),
|
|
/*methodBody=*/ [{}],
|
|
/*defaultImpl=*/ [{
|
|
return "roundingmode";
|
|
}]
|
|
>,
|
|
];
|
|
}
|
|
|
|
def OneToOneIntrinsicOpInterface : OpInterface<"OneToOneIntrinsicOpInterface"> {
|
|
let description = [{
|
|
An interface for operations modelling LLVM intrinsics suitable for
|
|
1-to-1 conversion.
|
|
|
|
An op implementing this interface can be directly replaced by a call
|
|
to a matching intrinsic function.
|
|
The op must ensure that the combinations of its arguments and results
|
|
have valid intrinsic counterparts.
|
|
|
|
For example, an operation supporting different inputs:
|
|
```mlir
|
|
%res_v8 = intr.op %value_v8 : vector<8xf32>
|
|
%res_v16 = intr.op %value_v16 : vector<16xf32>
|
|
```
|
|
can be converted to the following intrinsic calls:
|
|
```mlir
|
|
%res_v8 = llvm.call_intrinsic "llvm.x86.op.intr.256"(%value_v8)
|
|
%res_v16 = llvm.call_intrinsic "llvm.x86.op.intr.512"(%value_v16)
|
|
```
|
|
}];
|
|
|
|
let cppNamespace = "::mlir::LLVM";
|
|
|
|
let methods = [
|
|
InterfaceMethod<
|
|
/*desc=*/[{
|
|
Returns mangled LLVM intrinsic function name matching the operation
|
|
variant.
|
|
}],
|
|
/*retType=*/"std::string",
|
|
/*methodName=*/"getIntrinsicName"
|
|
>,
|
|
InterfaceMethod<
|
|
/*desc=*/[{
|
|
Returns operands for a corresponding LLVM intrinsic.
|
|
|
|
Additional operations may be created to facilitate mapping
|
|
between the source operands and the target intrinsic.
|
|
}],
|
|
/*retType=*/"SmallVector<Value>",
|
|
/*methodName=*/"getIntrinsicOperands",
|
|
/*args=*/(ins "::mlir::ArrayRef<Value>":$operands,
|
|
"const ::mlir::LLVMTypeConverter &":$typeConverter,
|
|
"::mlir::RewriterBase &":$rewriter),
|
|
/*methodBody=*/"",
|
|
/*defaultImplementation=*/"return SmallVector<Value>(operands);"
|
|
>,
|
|
];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// LLVM dialect type interfaces.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// An interface for LLVM pointer element types.
|
|
def LLVM_PointerElementTypeInterface
|
|
: TypeInterface<"PointerElementTypeInterface"> {
|
|
let cppNamespace = "::mlir::LLVM";
|
|
|
|
let description = [{
|
|
An interface for types that are allowed as elements of LLVM pointer type.
|
|
Such types must have a size.
|
|
}];
|
|
|
|
let methods = [
|
|
InterfaceMethod<
|
|
/*description=*/"Returns the size of the type in bytes.",
|
|
/*retTy=*/"unsigned",
|
|
/*methodName=*/"getSizeInBytes",
|
|
/*args=*/(ins "const ::mlir::DataLayout &":$dataLayout),
|
|
/*methodBody=*/"",
|
|
/*defaultImplementation=*/[{
|
|
return dataLayout.getTypeSize($_type);
|
|
}]
|
|
>
|
|
];
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// LLVM dialect attr interfaces.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def LLVM_DIRecursiveTypeAttrInterface
|
|
: AttrInterface<"DIRecursiveTypeAttrInterface"> {
|
|
let description = [{
|
|
This attribute represents a DITypeAttr that is recursive. Only DITypeAttrs
|
|
that translate to LLVM DITypes that support mutation should implement this
|
|
interface.
|
|
|
|
There are two modes for conforming attributes:
|
|
|
|
1. "rec-decl":
|
|
- This attr is a recursive declaration identified by a recId.
|
|
|
|
2. "rec-self":
|
|
- This attr is considered a recursive self reference.
|
|
- This attr itself is a placeholder type that should be conceptually
|
|
replaced with the closest parent attr of the same type with the same
|
|
recId.
|
|
|
|
For example, to represent a linked list struct:
|
|
|
|
#rec_self = di_composite_type<recId = 0>
|
|
#ptr = di_derived_type<baseType: #rec_self, ...>
|
|
#field = di_derived_type<name = "next", baseType: #ptr, ...>
|
|
#rec = di_composite_type<recId = 0, name = "Node", elements: #field, ...>
|
|
#var = di_local_variable<type = #rec, ...>
|
|
|
|
Note that a rec-self without an outer rec-decl with the same recId is
|
|
conceptually the same as an "unbound" variable. The context needs to provide
|
|
meaning to the rec-self.
|
|
}];
|
|
let cppNamespace = "::mlir::LLVM";
|
|
let methods = [
|
|
InterfaceMethod<[{
|
|
Get whether this attr describes a recursive self reference.
|
|
}], "bool", "getIsRecSelf", (ins)>,
|
|
InterfaceMethod<[{
|
|
Get the recursive ID used for matching "rec-decl" with "rec-self".
|
|
If this attr instance is not recursive, return a null attribute.
|
|
}], "DistinctAttr", "getRecId", (ins)>,
|
|
InterfaceMethod<[{
|
|
Get a copy of this type attr but with the recursive ID set to `recId`.
|
|
}], "DIRecursiveTypeAttrInterface", "withRecId",
|
|
(ins "DistinctAttr":$recId)>,
|
|
StaticInterfaceMethod<[{
|
|
Build a rec-self instance using the provided `recId`.
|
|
}], "DIRecursiveTypeAttrInterface", "getRecSelf",
|
|
(ins "DistinctAttr":$recId)>
|
|
];
|
|
}
|
|
|
|
def LLVM_LLVMAddrSpaceAttrInterface :
|
|
AttrInterface<"LLVMAddrSpaceAttrInterface"> {
|
|
let description = [{
|
|
An interface for attributes that represent LLVM address spaces.
|
|
Implementing attributes should provide access to the address space value
|
|
as an unsigned integer.
|
|
}];
|
|
let cppNamespace = "::mlir::LLVM";
|
|
let methods = [
|
|
InterfaceMethod<
|
|
/*description=*/"Returns the address space as an unsigned integer.",
|
|
/*retTy=*/"unsigned",
|
|
/*methodName=*/"getAddressSpace",
|
|
/*args=*/(ins)
|
|
>
|
|
];
|
|
}
|
|
|
|
def LLVM_IntrinsicIntegerAttrInterface :
|
|
AttrInterface<"IntrinsicIntegerAttrInterface"> {
|
|
let description = [{
|
|
An interface for attributes that represent LLVM intrinsic integer immediate
|
|
arguments while using a richer dialect-specific assembly form.
|
|
|
|
The default implementation is intended for enum-style attributes whose
|
|
`getValue()` returns an enum with a storage type that matches the LLVM
|
|
immarg width. Attributes with non-enum storage or a different LLVM immarg
|
|
width must override `getIntegerAttr`.
|
|
}];
|
|
let cppNamespace = "::mlir::LLVM";
|
|
let methods = [
|
|
InterfaceMethod<
|
|
/*description=*/"Returns the integer attribute to pass to LLVM.",
|
|
/*retTy=*/"::mlir::IntegerAttr",
|
|
/*methodName=*/"getIntegerAttr",
|
|
/*args=*/(ins),
|
|
/*methodBody=*/[{}],
|
|
/*defaultImplementation=*/[{
|
|
using EnumType = decltype($_attr.getValue());
|
|
using StorageType = std::underlying_type_t<EnumType>;
|
|
auto type = ::mlir::IntegerType::get($_attr.getContext(),
|
|
sizeof(StorageType) * 8);
|
|
return ::mlir::IntegerAttr::get(
|
|
type, static_cast<StorageType>($_attr.getValue()));
|
|
}]
|
|
>
|
|
];
|
|
}
|
|
|
|
def LLVM_ModuleFlagAttrInterface :
|
|
AttrInterface<"ModuleFlagAttrInterface"> {
|
|
let description = [{
|
|
An interface for attributes that represent LLVM module flag metadata entries.
|
|
|
|
Implementing attributes provide the module flag merge behavior, metadata key,
|
|
and metadata value. This lets target dialects define richer, target-specific
|
|
module flag attributes while still sharing `llvm.module_flags` as the common
|
|
operation container. Values returned by this interface must use a shape that
|
|
can be exported to LLVM IR: integer attributes (exported as i32 constants),
|
|
string attributes, attributes implementing `IntrinsicIntegerAttrInterface`,
|
|
supported array values, or `ModuleFlagProfileSummaryAttr`.
|
|
}];
|
|
let cppNamespace = "::mlir::LLVM";
|
|
let methods = [
|
|
InterfaceMethod<
|
|
/*description=*/"Returns the module flag merge behavior.",
|
|
/*retTy=*/"::mlir::LLVM::ModFlagBehavior",
|
|
/*methodName=*/"getModuleFlagBehavior",
|
|
/*args=*/(ins)
|
|
>,
|
|
InterfaceMethod<
|
|
/*description=*/"Returns the module flag metadata key.",
|
|
/*retTy=*/"::mlir::StringAttr",
|
|
/*methodName=*/"getModuleFlagKey",
|
|
/*args=*/(ins)
|
|
>,
|
|
InterfaceMethod<
|
|
/*description=*/"Returns the module flag metadata value.",
|
|
/*retTy=*/"::mlir::Attribute",
|
|
/*methodName=*/"getModuleFlagValue",
|
|
/*args=*/(ins)
|
|
>
|
|
];
|
|
}
|
|
|
|
def LLVM_TargetAttrInterface
|
|
: AttrInterface<"TargetAttrInterface", [DLTIQueryInterface]> {
|
|
let description = [{
|
|
Interface for attributes that describe LLVM targets.
|
|
|
|
These attributes should be able to return the specified target `triple`,
|
|
`chip` and `features`.
|
|
|
|
Implementing attributes should provide a `DLTIQueryInterface::query()`
|
|
implementation which responds to keys `"triple"`, `"chip"` and `"features"`
|
|
by returning appropriate `StringAttr`s.
|
|
}];
|
|
let cppNamespace = "::mlir::LLVM";
|
|
let methods = [
|
|
InterfaceMethod<
|
|
/*description=*/"Returns the target triple identifier.",
|
|
/*retTy=*/"StringAttr",
|
|
/*methodName=*/"getTriple",
|
|
/*args=*/(ins)
|
|
>,
|
|
InterfaceMethod<
|
|
/*description=*/"Returns the target chip (i.e. \"cpu\") identifier.",
|
|
/*retTy=*/"StringAttr",
|
|
/*methodName=*/"getChip",
|
|
/*args=*/(ins)
|
|
>,
|
|
InterfaceMethod<
|
|
/*description=*/"Returns the target features as a TargetFeaturesAttr.",
|
|
/*retTy=*/"Attribute", // NB: will be a LLVM::TargetFeaturesAttr, though
|
|
// need to work around a cyclic dependency on
|
|
// LLVMInterfaces.td and LLVMAttrDefs.td.
|
|
/*methodName=*/"getFeatures",
|
|
/*args=*/(ins)
|
|
>
|
|
];
|
|
}
|
|
|
|
#endif // LLVMIR_INTERFACES
|