22 #include "llvm/ADT/ScopeExit.h"
23 #include "llvm/ADT/TypeSwitch.h"
24 #include "llvm/Support/TypeSize.h"
53 params.push_back(type);
61 params.push_back(type);
68 llvm::interleaveComma(params, p,
93 auto typeOrIntParser = [&]() -> ParseResult {
96 if (intResult.has_value() && !failed(*intResult)) {
98 intParams.push_back(i);
108 typeParams.push_back(t);
116 "failed to parse parameter list for target extension type");
125 if (!typeParams.empty() && !intParams.empty())
139 LLVM_ATTRIBUTE_UNUSED
static LogicalResult
142 #include "mlir/Dialect/LLVMIR/LLVMTypeInterfaces.cpp.inc"
144 #define GET_TYPEDEF_CLASSES
145 #include "mlir/Dialect/LLVMIR/LLVMTypes.cpp.inc"
151 bool LLVMArrayType::isValidElementType(
Type type) {
152 return !llvm::isa<LLVMVoidType, LLVMLabelType, LLVMMetadataType,
153 LLVMFunctionType, LLVMTokenType>(type);
157 assert(elementType &&
"expected non-null subtype");
163 Type elementType, uint64_t numElements) {
164 assert(elementType &&
"expected non-null subtype");
171 Type elementType, uint64_t numElements) {
172 if (!isValidElementType(elementType))
173 return emitError() <<
"invalid array element type: " << elementType;
182 LLVMArrayType::getTypeSizeInBits(
const DataLayout &dataLayout,
185 getTypeSize(dataLayout, params));
188 llvm::TypeSize LLVMArrayType::getTypeSize(
const DataLayout &dataLayout,
195 uint64_t LLVMArrayType::getABIAlignment(
const DataLayout &dataLayout,
201 LLVMArrayType::getPreferredAlignment(
const DataLayout &dataLayout,
210 bool LLVMFunctionType::isValidArgumentType(
Type type) {
211 return !llvm::isa<LLVMVoidType, LLVMFunctionType>(type);
214 bool LLVMFunctionType::isValidResultType(
Type type) {
215 return !llvm::isa<LLVMFunctionType, LLVMMetadataType, LLVMLabelType>(type);
220 assert(result &&
"expected non-null result");
228 assert(result &&
"expected non-null result");
235 assert(results.size() == 1 &&
"expected a single result type");
236 return get(results[0], llvm::to_vector(inputs), isVarArg());
240 return static_cast<detail::LLVMFunctionTypeStorage *
>(getImpl())->returnType;
246 if (!isValidResultType(result))
247 return emitError() <<
"invalid function result type: " << result;
249 for (
Type arg : arguments)
250 if (!isValidArgumentType(arg))
251 return emitError() <<
"invalid function argument type: " << arg;
265 auto spec = cast<DenseIntElementsAttr>(attr);
266 auto idx =
static_cast<int64_t
>(pos);
267 if (idx >= spec.size())
269 return spec.getValues<uint64_t>()[idx];
276 static std::optional<uint64_t>
281 for (DataLayoutEntryInterface entry : params) {
282 if (!entry.isTypeEntry())
284 if (cast<LLVMPointerType>(cast<Type>(entry.getKey())).getAddressSpace() ==
285 type.getAddressSpace()) {
286 currentEntry = entry.getValue();
303 if (type.getAddressSpace() == 0) {
313 LLVMPointerType::getTypeSizeInBits(
const DataLayout &dataLayout,
315 if (std::optional<uint64_t> size =
317 return llvm::TypeSize::getFixed(*size);
324 uint64_t LLVMPointerType::getABIAlignment(
const DataLayout &dataLayout,
326 if (std::optional<uint64_t> alignment =
334 LLVMPointerType::getPreferredAlignment(
const DataLayout &dataLayout,
336 if (std::optional<uint64_t> alignment =
343 std::optional<uint64_t>
346 if (std::optional<uint64_t> indexBitwidth =
348 return *indexBitwidth;
353 bool LLVMPointerType::areCompatible(
355 DataLayoutSpecInterface newSpec,
357 for (DataLayoutEntryInterface newEntry : newLayout) {
358 if (!newEntry.isTypeEntry())
363 llvm::cast<LLVMPointerType>(llvm::cast<Type>(newEntry.getKey()));
365 llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
366 if (
auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
367 return llvm::cast<LLVMPointerType>(type).getAddressSpace() ==
368 newType.getAddressSpace();
372 if (it == oldLayout.end()) {
373 llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
374 if (
auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
375 return llvm::cast<LLVMPointerType>(type).getAddressSpace() == 0;
380 if (it != oldLayout.end()) {
385 Attribute newSpec = llvm::cast<DenseIntElementsAttr>(newEntry.getValue());
388 if (size != newSize || abi < newAbi || abi % newAbi != 0)
396 for (DataLayoutEntryInterface entry : entries) {
397 if (!entry.isTypeEntry())
399 auto key = llvm::cast<Type>(entry.getKey());
400 auto values = llvm::dyn_cast<DenseIntElementsAttr>(entry.getValue());
401 if (!values || (values.size() != 3 && values.size() != 4)) {
403 <<
"expected layout attribute for " << key
404 <<
" to be a dense integer elements attribute with 3 or 4 "
407 if (!values.getElementType().isInteger(64))
408 return emitError(loc) <<
"expected i64 parameters for " << key;
412 return emitError(loc) <<
"preferred alignment is expected to be at least "
413 "as large as ABI alignment";
423 bool LLVMStructType::isValidElementType(
Type type) {
424 return !llvm::isa<LLVMVoidType, LLVMLabelType, LLVMMetadataType,
425 LLVMFunctionType, LLVMTokenType>(type);
428 LLVMStructType LLVMStructType::getIdentified(
MLIRContext *context,
433 LLVMStructType LLVMStructType::getIdentifiedChecked(
436 return Base::getChecked(
emitError, context, name,
false);
439 LLVMStructType LLVMStructType::getNewIdentified(
MLIRContext *context,
443 std::string stringName = name.str();
444 unsigned counter = 0;
446 auto type = LLVMStructType::getIdentified(context, stringName);
447 if (type.isInitialized() || failed(type.setBody(elements, isPacked))) {
449 stringName = (Twine(name) +
"." + std::to_string(counter)).str();
456 LLVMStructType LLVMStructType::getLiteral(
MLIRContext *context,
458 return Base::get(context, types, isPacked);
465 return Base::getChecked(
emitError, context, types, isPacked);
468 LLVMStructType LLVMStructType::getOpaque(StringRef name,
MLIRContext *context) {
475 return Base::getChecked(
emitError, context, name,
true);
478 LogicalResult LLVMStructType::setBody(
ArrayRef<Type> types,
bool isPacked) {
479 assert(isIdentified() &&
"can only set bodies of identified structs");
480 assert(llvm::all_of(types, LLVMStructType::isValidElementType) &&
481 "expected valid body types");
482 return Base::mutate(types, isPacked);
485 bool LLVMStructType::isPacked()
const {
return getImpl()->isPacked(); }
486 bool LLVMStructType::isIdentified()
const {
return getImpl()->isIdentified(); }
487 bool LLVMStructType::isOpaque()
const {
488 return getImpl()->isIdentified() &&
489 (getImpl()->isOpaque() || !getImpl()->isInitialized());
491 bool LLVMStructType::isInitialized() {
return getImpl()->isInitialized(); }
492 StringRef LLVMStructType::getName()
const {
return getImpl()->getIdentifier(); }
494 return isIdentified() ? getImpl()->getIdentifiedStructBody()
495 : getImpl()->getTypeList();
508 if (!isValidElementType(t))
509 return emitError() <<
"invalid LLVM structure element type: " << t;
515 LLVMStructType::getTypeSizeInBits(
const DataLayout &dataLayout,
517 auto structSize = llvm::TypeSize::getFixed(0);
518 uint64_t structAlignment = 1;
519 for (
Type element : getBody()) {
520 uint64_t elementAlignment =
524 structSize = llvm::alignTo(structSize, elementAlignment);
529 structAlignment =
std::max(elementAlignment, structAlignment);
533 structSize = llvm::alignTo(structSize, structAlignment);
541 static std::optional<uint64_t>
543 StructDLEntryPos pos) {
544 const auto *currentEntry =
545 llvm::find_if(params, [](DataLayoutEntryInterface entry) {
546 return entry.isTypeEntry();
548 if (currentEntry == params.end())
551 auto attr = llvm::cast<DenseIntElementsAttr>(currentEntry->getValue());
552 if (pos == StructDLEntryPos::Preferred &&
553 attr.size() <=
static_cast<int64_t
>(StructDLEntryPos::Preferred))
555 pos = StructDLEntryPos::Abi;
557 return attr.getValues<uint64_t>()[
static_cast<size_t>(pos)];
563 StructDLEntryPos pos) {
565 if (pos == StructDLEntryPos::Abi && type.isPacked()) {
571 uint64_t structAlignment = 1;
572 for (
Type iter : type.getBody()) {
578 if (std::optional<uint64_t> entryResult =
582 return structAlignment;
585 uint64_t LLVMStructType::getABIAlignment(
const DataLayout &dataLayout,
588 StructDLEntryPos::Abi);
592 LLVMStructType::getPreferredAlignment(
const DataLayout &dataLayout,
595 StructDLEntryPos::Preferred);
599 return llvm::cast<DenseIntElementsAttr>(attr)
600 .getValues<uint64_t>()[
static_cast<size_t>(pos)];
603 bool LLVMStructType::areCompatible(
605 DataLayoutSpecInterface newSpec,
607 for (DataLayoutEntryInterface newEntry : newLayout) {
608 if (!newEntry.isTypeEntry())
611 const auto *previousEntry =
612 llvm::find_if(oldLayout, [](DataLayoutEntryInterface entry) {
613 return entry.isTypeEntry();
615 if (previousEntry == oldLayout.end())
619 StructDLEntryPos::Abi);
622 if (abi < newAbi || abi % newAbi != 0)
630 for (DataLayoutEntryInterface entry : entries) {
631 if (!entry.isTypeEntry())
634 auto key = llvm::cast<LLVMStructType>(llvm::cast<Type>(entry.getKey()));
635 auto values = llvm::dyn_cast<DenseIntElementsAttr>(entry.getValue());
636 if (!values || (values.size() != 2 && values.size() != 1)) {
638 <<
"expected layout attribute for "
639 << llvm::cast<Type>(entry.getKey())
640 <<
" to be a dense integer elements attribute of 1 or 2 elements";
642 if (!values.getElementType().isInteger(64))
643 return emitError(loc) <<
"expected i64 entries for " << key;
645 if (key.isIdentified() || !key.getBody().empty()) {
646 return emitError(loc) <<
"unexpected layout attribute for struct " << key;
649 if (values.size() == 1)
654 return emitError(loc) <<
"preferred alignment is expected to be at least "
655 "as large as ABI alignment";
658 return mlir::success();
668 bool LLVM::LLVMTargetExtType::hasProperty(Property prop)
const {
670 uint64_t properties = 0;
674 (LLVMTargetExtType::HasZeroInit | LLVM::LLVMTargetExtType::CanBeGlobal);
676 return (properties & prop) == prop;
679 bool LLVM::LLVMTargetExtType::supportsMemOps()
const {
694 const llvm::fltSemantics &LLVMPPCFP128Type::getFloatSemantics()
const {
695 return APFloat::PPCDoubleDouble();
728 if (
auto intType = llvm::dyn_cast<IntegerType>(type))
729 return intType.isSignless();
732 if (
auto vecType = llvm::dyn_cast<VectorType>(type))
733 return vecType.getRank() == 1;
739 if (!compatibleTypes.insert(type).second)
742 auto isCompatible = [&](
Type type) {
748 .Case<LLVMStructType>([&](
auto structType) {
749 return llvm::all_of(structType.getBody(), isCompatible);
751 .Case<LLVMFunctionType>([&](
auto funcType) {
752 return isCompatible(funcType.getReturnType()) &&
753 llvm::all_of(funcType.getParams(), isCompatible);
755 .Case<IntegerType>([](
auto intType) {
return intType.isSignless(); })
756 .Case<VectorType>([&](
auto vecType) {
757 return vecType.getRank() == 1 &&
758 isCompatible(vecType.getElementType());
760 .Case<LLVMPointerType>([&](
auto pointerType) {
return true; })
761 .Case<LLVMTargetExtType>([&](
auto extType) {
762 return llvm::all_of(extType.getTypeParams(), isCompatible);
767 >([&](
auto containerType) {
768 return isCompatible(containerType.getElementType());
783 >([](
Type) {
return true; })
785 .Default([](
Type) {
return false; });
788 compatibleTypes.erase(type);
794 if (
auto *llvmDialect =
807 return llvm::isa<BFloat16Type, Float16Type, Float32Type, Float64Type,
808 Float80Type, Float128Type, LLVMPPCFP128Type>(type);
812 if (
auto vecType = llvm::dyn_cast<VectorType>(type)) {
813 if (vecType.getRank() != 1)
815 Type elementType = vecType.getElementType();
816 if (
auto intType = llvm::dyn_cast<IntegerType>(elementType))
817 return intType.isSignless();
818 return llvm::isa<BFloat16Type, Float16Type, Float32Type, Float64Type,
819 Float80Type, Float128Type, LLVMPointerType>(elementType);
825 auto vecTy = dyn_cast<VectorType>(type);
826 assert(vecTy &&
"incompatible with LLVM vector type");
827 if (vecTy.isScalable())
828 return llvm::ElementCount::getScalable(vecTy.getNumElements());
829 return llvm::ElementCount::getFixed(vecTy.getNumElements());
833 assert(llvm::isa<VectorType>(vectorType) &&
834 "expected LLVM-compatible vector type");
835 return llvm::cast<VectorType>(vectorType).isScalable();
840 assert(VectorType::isValidElementType(elementType) &&
841 "incompatible element type");
846 const llvm::ElementCount &numElements) {
847 if (numElements.isScalable())
848 return getVectorType(elementType, numElements.getKnownMinValue(),
850 return getVectorType(elementType, numElements.getFixedValue(),
856 "expected a type compatible with the LLVM dialect");
859 .Case<BFloat16Type, Float16Type>(
860 [](
Type) {
return llvm::TypeSize::getFixed(16); })
861 .Case<Float32Type>([](
Type) {
return llvm::TypeSize::getFixed(32); })
862 .Case<Float64Type>([](
Type) {
return llvm::TypeSize::getFixed(64); })
863 .Case<Float80Type>([](
Type) {
return llvm::TypeSize::getFixed(80); })
864 .Case<Float128Type>([](
Type) {
return llvm::TypeSize::getFixed(128); })
865 .Case<IntegerType>([](IntegerType intTy) {
866 return llvm::TypeSize::getFixed(intTy.getWidth());
868 .Case<LLVMPPCFP128Type>(
869 [](
Type) {
return llvm::TypeSize::getFixed(128); })
870 .Case<VectorType>([](VectorType t) {
872 "unexpected incompatible with LLVM vector type");
873 llvm::TypeSize elementSize =
875 return llvm::TypeSize(elementSize.getFixedValue() * t.getNumElements(),
876 elementSize.isScalable());
878 .Default([](
Type ty) {
879 assert((llvm::isa<LLVMVoidType, LLVMLabelType, LLVMMetadataType,
880 LLVMTokenType, LLVMStructType, LLVMArrayType,
881 LLVMPointerType, LLVMFunctionType, LLVMTargetExtType>(
883 "unexpected missing support for primitive type");
884 return llvm::TypeSize::getFixed(0);
892 void LLVMDialect::registerTypes() {
894 #define GET_TYPEDEF_LIST
895 #include "mlir/Dialect/LLVMIR/LLVMTypes.cpp.inc"
static LogicalResult verifyEntries(function_ref< InFlightDiagnostic()> emitError, ArrayRef< DataLayoutEntryInterface > entries, bool allowTypes=true)
Verify entries, with the option to disallow types as keys.
static uint64_t getIndexBitwidth(DataLayoutEntryListRef params)
Returns the bitwidth of the index type if specified in the param list.
static MLIRContext * getContext(OpFoldResult val)
static int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
constexpr static const uint64_t kDefaultPointerAlignment
static void printExtTypeParams(AsmPrinter &p, ArrayRef< Type > typeParams, ArrayRef< unsigned int > intParams)
constexpr static const uint64_t kDefaultPointerSizeBits
static LLVM_ATTRIBUTE_UNUSED OptionalParseResult generatedTypeParser(AsmParser &parser, StringRef *mnemonic, Type &value)
These are unused for now.
static void printFunctionTypes(AsmPrinter &p, ArrayRef< Type > params, bool isVarArg)
static bool isCompatibleImpl(Type type, DenseSet< Type > &compatibleTypes)
static ParseResult parseExtTypeParams(AsmParser &p, SmallVectorImpl< Type > &typeParams, SmallVectorImpl< unsigned int > &intParams)
Parses the parameter list for a target extension type.
static LLVM_ATTRIBUTE_UNUSED LogicalResult generatedTypePrinter(Type def, AsmPrinter &printer)
static constexpr llvm::StringRef kSpirvPrefix
static ParseResult parseFunctionTypes(AsmParser &p, SmallVector< Type > ¶ms, bool &isVarArg)
constexpr static const uint64_t kBitsInByte
static constexpr llvm::StringRef kArmSVCount
static std::optional< uint64_t > getPointerDataLayoutEntry(DataLayoutEntryListRef params, LLVMPointerType type, PtrDLEntryPos pos)
Returns the part of the data layout entry that corresponds to pos for the given type by interpreting ...
static std::optional< uint64_t > getStructDataLayoutEntry(DataLayoutEntryListRef params, LLVMStructType type, StructDLEntryPos pos)
static uint64_t extractStructSpecValue(Attribute attr, StructDLEntryPos pos)
static uint64_t calculateStructAlignment(const DataLayout &dataLayout, DataLayoutEntryListRef params, LLVMStructType type, StructDLEntryPos pos)
static SmallVector< Type > getReturnTypes(SmallVector< func::ReturnOp > returnOps)
Helper function that returns the return types (skipping casts) of the given func.return ops.
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
This base class exposes generic asm parser hooks, usable across the various derived parsers.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseOptionalRParen()=0
Parse a ) token if present.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
virtual ParseResult parseOptionalEllipsis()=0
Parse a ... token if present;.
This base class exposes generic asm printer hooks, usable across the various derived printers.
Attributes are known-constant values of operations.
The main mechanism for performing data layout queries.
std::optional< uint64_t > getTypeIndexBitwidth(Type t) const
Returns the bitwidth that should be used when performing index computations for the given pointer-lik...
llvm::TypeSize getTypeSize(Type t) const
Returns the size of the given type in the current scope.
uint64_t getTypePreferredAlignment(Type t) const
Returns the preferred of the given type in the current scope.
uint64_t getTypeABIAlignment(Type t) const
Returns the required alignment of the given type in the current scope.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
The DialectAsmParser has methods for interacting with the asm parser when parsing attributes and type...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
This class represents a diagnostic that is inflight and set to be reported.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
This class implements Optional functionality for ParseResult.
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
void printType(Type type, AsmPrinter &printer)
Prints an LLVM Dialect type.
Type parseType(DialectAsmParser &parser)
Parses an LLVM dialect type.
Type getVectorType(Type elementType, unsigned numElements, bool isScalable=false)
Creates an LLVM dialect-compatible vector type with the given element type and length.
llvm::TypeSize getPrimitiveTypeSizeInBits(Type type)
Returns the size of the given primitive LLVM dialect-compatible type (including vectors) in bits,...
void printPrettyLLVMType(AsmPrinter &p, Type type)
Print any MLIR type or a concise syntax for LLVM types.
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
ParseResult parsePrettyLLVMType(AsmParser &p, Type &type)
Parse any MLIR type or a concise syntax for LLVM types.
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
bool isCompatibleOuterType(Type type)
Returns true if the given outer type is compatible with the LLVM dialect without checking its potenti...
PtrDLEntryPos
The positions of different values in the data layout entry for pointers.
std::optional< uint64_t > extractPointerSpecValue(Attribute attr, PtrDLEntryPos pos)
Returns the value that corresponds to named position pos from the data layout entry attr assuming it'...
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
Operation * clone(OpBuilder &b, Operation *op, TypeRange newResultTypes, ValueRange newOperands)
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
Type parseType(llvm::StringRef typeStr, MLIRContext *context, size_t *numRead=nullptr, bool isKnownNullTerminated=false)
This parses a single MLIR type to an MLIR context if it was valid.
::llvm::MapVector<::mlir::StringAttr, ::mlir::DataLayoutEntryInterface > DataLayoutIdentifiedEntryMap
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...