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())
142#include "mlir/Dialect/LLVMIR/LLVMTypeInterfaces.cpp.inc"
144#define GET_TYPEDEF_CLASSES
145#include "mlir/Dialect/LLVMIR/LLVMTypes.cpp.inc"
151bool LLVMArrayType::isValidElementType(
Type type) {
152 return !llvm::isa<LLVMVoidType, LLVMLabelType, LLVMMetadataType,
153 LLVMFunctionType, LLVMTokenType>(type);
156LLVMArrayType LLVMArrayType::get(
Type elementType, uint64_t numElements) {
157 assert(elementType &&
"expected non-null subtype");
158 return Base::get(elementType.
getContext(), elementType, numElements);
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;
182LLVMArrayType::getTypeSizeInBits(
const DataLayout &dataLayout,
185 getTypeSize(dataLayout, params));
188llvm::TypeSize LLVMArrayType::getTypeSize(
const DataLayout &dataLayout,
195uint64_t LLVMArrayType::getABIAlignment(
const DataLayout &dataLayout,
201LLVMArrayType::getPreferredAlignment(
const DataLayout &dataLayout,
210bool LLVMFunctionType::isValidArgumentType(
Type type) {
211 return !llvm::isa<LLVMVoidType, LLVMFunctionType>(type);
214bool LLVMFunctionType::isValidResultType(Type type) {
215 return !llvm::isa<LLVMFunctionType, LLVMMetadataType, LLVMLabelType>(type);
218LLVMFunctionType LLVMFunctionType::get(Type
result, ArrayRef<Type> arguments,
220 assert(
result &&
"expected non-null result");
221 return Base::get(
result.getContext(),
result, arguments, isVarArg);
226 Type
result, ArrayRef<Type> arguments,
228 assert(
result &&
"expected non-null result");
233LLVMFunctionType LLVMFunctionType::clone(
TypeRange inputs,
235 if (results.size() != 1 || !isValidResultType(results[0]))
237 if (!llvm::all_of(inputs, isValidArgumentType))
239 return get(results[0], llvm::to_vector(inputs), isVarArg());
242ArrayRef<Type> LLVMFunctionType::getReturnTypes()
const {
243 return static_cast<detail::LLVMFunctionTypeStorage *
>(getImpl())->returnType;
248 Type
result, ArrayRef<Type> arguments,
bool) {
249 if (!isValidResultType(
result))
252 for (Type arg : arguments)
253 if (!isValidArgumentType(arg))
254 return emitError() <<
"invalid function argument type: " << arg;
268 auto spec = cast<DenseIntElementsAttr>(attr);
269 auto idx =
static_cast<int64_t>(pos);
270 if (idx >= spec.size())
272 return spec.getValues<uint64_t>()[idx];
279static std::optional<uint64_t>
284 for (DataLayoutEntryInterface entry : params) {
285 if (!entry.isTypeEntry())
287 if (cast<LLVMPointerType>(cast<Type>(entry.getKey())).getAddressSpace() ==
288 type.getAddressSpace()) {
289 currentEntry = entry.getValue();
306 if (type.getAddressSpace() == 0) {
316LLVMPointerType::getTypeSizeInBits(
const DataLayout &dataLayout,
318 if (std::optional<uint64_t> size =
320 return llvm::TypeSize::getFixed(*size);
327uint64_t LLVMPointerType::getABIAlignment(
const DataLayout &dataLayout,
329 if (std::optional<uint64_t> alignment =
337LLVMPointerType::getPreferredAlignment(
const DataLayout &dataLayout,
339 if (std::optional<uint64_t> alignment =
346std::optional<uint64_t>
347LLVMPointerType::getIndexBitwidth(
const DataLayout &dataLayout,
349 if (std::optional<uint64_t> indexBitwidth =
351 return *indexBitwidth;
356bool LLVMPointerType::areCompatible(
358 DataLayoutSpecInterface newSpec,
360 for (DataLayoutEntryInterface newEntry : newLayout) {
361 if (!newEntry.isTypeEntry())
366 llvm::cast<LLVMPointerType>(llvm::cast<Type>(newEntry.getKey()));
368 llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
369 if (
auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
370 return llvm::cast<LLVMPointerType>(type).getAddressSpace() ==
371 newType.getAddressSpace();
375 if (it == oldLayout.end()) {
376 llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
377 if (
auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
378 return llvm::cast<LLVMPointerType>(type).getAddressSpace() == 0;
383 if (it != oldLayout.end()) {
388 Attribute newSpec = llvm::cast<DenseIntElementsAttr>(newEntry.getValue());
391 if (size != newSize || abi < newAbi || abi % newAbi != 0)
398 Location loc)
const {
399 for (DataLayoutEntryInterface entry : entries) {
400 if (!entry.isTypeEntry())
402 auto key = llvm::cast<Type>(entry.getKey());
403 auto values = llvm::dyn_cast<DenseIntElementsAttr>(entry.getValue());
404 if (!values || (values.size() != 3 && values.size() != 4)) {
406 <<
"expected layout attribute for " << key
407 <<
" to be a dense integer elements attribute with 3 or 4 "
410 if (!values.getElementType().isInteger(64))
411 return emitError(loc) <<
"expected i64 parameters for " << key;
415 return emitError(loc) <<
"preferred alignment is expected to be at least "
416 "as large as ABI alignment";
426bool LLVMStructType::isValidElementType(Type type) {
427 return !llvm::isa<LLVMVoidType, LLVMLabelType, LLVMMetadataType,
428 LLVMFunctionType, LLVMTokenType>(type);
431LLVMStructType LLVMStructType::getIdentified(MLIRContext *context,
433 return Base::get(context, name,
false);
436LLVMStructType LLVMStructType::getIdentifiedChecked(
439 return Base::getChecked(
emitError, context, name,
false);
442LLVMStructType LLVMStructType::getNewIdentified(MLIRContext *context,
444 ArrayRef<Type> elements,
446 std::string stringName = name.str();
447 unsigned counter = 0;
449 auto type = LLVMStructType::getIdentified(context, stringName);
450 if (type.isInitialized() ||
failed(type.setBody(elements, isPacked))) {
452 stringName = (Twine(name) +
"." + std::to_string(counter)).str();
459LLVMStructType LLVMStructType::getLiteral(MLIRContext *context,
460 ArrayRef<Type> types,
bool isPacked) {
461 return Base::get(context, types, isPacked);
466 MLIRContext *context, ArrayRef<Type> types,
468 return Base::getChecked(
emitError, context, types, isPacked);
471LLVMStructType LLVMStructType::getOpaque(StringRef name, MLIRContext *context) {
472 return Base::get(context, name,
true);
477 MLIRContext *context, StringRef name) {
478 return Base::getChecked(
emitError, context, name,
true);
481LogicalResult LLVMStructType::setBody(ArrayRef<Type> types,
bool isPacked) {
482 assert(isIdentified() &&
"can only set bodies of identified structs");
483 assert(llvm::all_of(types, LLVMStructType::isValidElementType) &&
484 "expected valid body types");
485 return Base::mutate(types, isPacked);
488bool LLVMStructType::isPacked()
const {
return getImpl()->isPacked(); }
489bool LLVMStructType::isIdentified()
const {
return getImpl()->isIdentified(); }
490bool LLVMStructType::isOpaque()
const {
491 return getImpl()->isIdentified() &&
492 (getImpl()->isOpaque() || !getImpl()->isInitialized());
494bool LLVMStructType::isInitialized() {
return getImpl()->isInitialized(); }
495StringRef LLVMStructType::getName()
const {
return getImpl()->getIdentifier(); }
496ArrayRef<Type> LLVMStructType::getBody()
const {
497 return isIdentified() ? getImpl()->getIdentifiedStructBody()
498 : getImpl()->getTypeList();
502LLVMStructType::verifyInvariants(
function_ref<InFlightDiagnostic()>, StringRef,
509 ArrayRef<Type> types,
bool) {
511 if (!isValidElementType(t))
512 return emitError() <<
"invalid LLVM structure element type: " << t;
518LLVMStructType::getTypeSizeInBits(
const DataLayout &dataLayout,
520 auto structSize = llvm::TypeSize::getFixed(0);
521 uint64_t structAlignment = 1;
522 for (Type element : getBody()) {
523 uint64_t elementAlignment =
527 structSize = llvm::alignTo(structSize, elementAlignment);
532 structAlignment = std::max(elementAlignment, structAlignment);
536 structSize = llvm::alignTo(structSize, structAlignment);
544static std::optional<uint64_t>
546 StructDLEntryPos pos) {
547 const auto *currentEntry =
548 llvm::find_if(params, [](DataLayoutEntryInterface entry) {
549 return entry.isTypeEntry();
551 if (currentEntry == params.end())
554 auto attr = llvm::cast<DenseIntElementsAttr>(currentEntry->getValue());
555 if (pos == StructDLEntryPos::Preferred &&
556 attr.size() <=
static_cast<int64_t>(StructDLEntryPos::Preferred))
558 pos = StructDLEntryPos::Abi;
560 return attr.getValues<uint64_t>()[
static_cast<size_t>(pos)];
566 StructDLEntryPos pos) {
568 if (pos == StructDLEntryPos::Abi && type.isPacked()) {
574 uint64_t structAlignment = 1;
575 for (
Type iter : type.getBody()) {
581 if (std::optional<uint64_t> entryResult =
583 return std::max(*entryResult /
kBitsInByte, structAlignment);
585 return structAlignment;
588uint64_t LLVMStructType::getABIAlignment(
const DataLayout &dataLayout,
591 StructDLEntryPos::Abi);
595LLVMStructType::getPreferredAlignment(
const DataLayout &dataLayout,
598 StructDLEntryPos::Preferred);
602 return llvm::cast<DenseIntElementsAttr>(attr)
603 .getValues<uint64_t>()[
static_cast<size_t>(pos)];
606bool LLVMStructType::areCompatible(
608 DataLayoutSpecInterface newSpec,
610 for (DataLayoutEntryInterface newEntry : newLayout) {
611 if (!newEntry.isTypeEntry())
614 const auto *previousEntry =
615 llvm::find_if(oldLayout, [](DataLayoutEntryInterface entry) {
616 return entry.isTypeEntry();
618 if (previousEntry == oldLayout.end())
622 StructDLEntryPos::Abi);
625 if (abi < newAbi || abi % newAbi != 0)
632 Location loc)
const {
633 for (DataLayoutEntryInterface entry : entries) {
634 if (!entry.isTypeEntry())
637 auto key = llvm::cast<LLVMStructType>(llvm::cast<Type>(entry.getKey()));
638 auto values = llvm::dyn_cast<DenseIntElementsAttr>(entry.getValue());
639 if (!values || (values.size() != 2 && values.size() != 1)) {
641 <<
"expected layout attribute for "
642 << llvm::cast<Type>(entry.getKey())
643 <<
" to be a dense integer elements attribute of 1 or 2 elements";
645 if (!values.getElementType().isInteger(64))
646 return emitError(loc) <<
"expected i64 entries for " << key;
648 if (key.isIdentified() || !key.getBody().empty()) {
649 return emitError(loc) <<
"unexpected layout attribute for struct " << key;
652 if (values.size() == 1)
657 return emitError(loc) <<
"preferred alignment is expected to be at least "
658 "as large as ABI alignment";
661 return mlir::success();
671bool LLVM::LLVMTargetExtType::hasProperty(Property prop)
const {
673 uint64_t properties = 0;
677 (LLVMTargetExtType::HasZeroInit | LLVM::LLVMTargetExtType::CanBeGlobal);
679 return (properties & prop) == prop;
682bool LLVM::LLVMTargetExtType::supportsMemOps()
const {
697const llvm::fltSemantics &LLVMPPCFP128Type::getFloatSemantics()
const {
698 return APFloat::PPCDoubleDouble();
709 auto ptrTy = dyn_cast<PtrLikeTypeInterface>(type);
712 return !ptrTy.hasPtrMetadata() && ptrTy.getElementType() ==
nullptr &&
713 isa<LLVMAddrSpaceAttrInterface>(ptrTy.getMemorySpace());
742 if (
auto intType = llvm::dyn_cast<IntegerType>(type))
743 return intType.isSignless();
746 if (
auto vecType = llvm::dyn_cast<VectorType>(type))
747 return vecType.getRank() == 1;
753 if (!compatibleTypes.insert(type).second)
756 auto isCompatible = [&](
Type type) {
762 .Case<LLVMStructType>([&](
auto structType) {
763 return llvm::all_of(structType.getBody(), isCompatible);
765 .Case<LLVMFunctionType>([&](
auto funcType) {
766 return isCompatible(funcType.getReturnType()) &&
767 llvm::all_of(funcType.getParams(), isCompatible);
769 .Case<IntegerType>([](
auto intType) {
return intType.isSignless(); })
770 .Case<VectorType>([&](
auto vecType) {
771 return vecType.getRank() == 1 &&
772 isCompatible(vecType.getElementType());
774 .Case<LLVMPointerType>([&](
auto pointerType) {
return true; })
775 .Case<LLVMTargetExtType>([&](
auto extType) {
776 return llvm::all_of(extType.getTypeParams(), isCompatible);
781 >([&](
auto containerType) {
782 return isCompatible(containerType.getElementType());
797 >([](
Type) {
return true; })
799 .Case<PtrLikeTypeInterface>(
804 compatibleTypes.erase(type);
809bool LLVMDialect::isCompatibleType(
Type type) {
810 if (
auto *llvmDialect =
819 return LLVMDialect::isCompatibleType(type);
825 !isa<LLVM::LLVMVoidType, LLVM::LLVMFunctionType>(type)) &&
827 !(isa<LLVM::LLVMStructType>(type) &&
828 cast<LLVM::LLVMStructType>(type).isOpaque()) &&
830 !(isa<LLVM::LLVMTargetExtType>(type) &&
831 !cast<LLVM::LLVMTargetExtType>(type).supportsMemOps());
835 return llvm::isa<BFloat16Type, Float16Type, Float32Type, Float64Type,
836 Float80Type, Float128Type, LLVMPPCFP128Type>(type);
840 if (
auto vecType = llvm::dyn_cast<VectorType>(type)) {
841 if (vecType.getRank() != 1)
843 Type elementType = vecType.getElementType();
844 if (
auto intType = llvm::dyn_cast<IntegerType>(elementType))
845 return intType.isSignless();
846 return llvm::isa<BFloat16Type, Float16Type, Float32Type, Float64Type,
847 Float80Type, Float128Type, LLVMPointerType>(elementType) ||
854 auto vecTy = dyn_cast<VectorType>(type);
855 assert(vecTy &&
"incompatible with LLVM vector type");
856 if (vecTy.isScalable())
857 return llvm::ElementCount::getScalable(vecTy.getNumElements());
858 return llvm::ElementCount::getFixed(vecTy.getNumElements());
862 assert(llvm::isa<VectorType>(vectorType) &&
863 "expected LLVM-compatible vector type");
864 return llvm::cast<VectorType>(vectorType).isScalable();
869 assert(VectorType::isValidElementType(elementType) &&
870 "incompatible element type");
871 return VectorType::get(numElements, elementType, {isScalable});
875 const llvm::ElementCount &numElements) {
876 if (numElements.isScalable())
877 return getVectorType(elementType, numElements.getKnownMinValue(),
879 return getVectorType(elementType, numElements.getFixedValue(),
885 "expected a type compatible with the LLVM dialect");
888 .Case<BFloat16Type, Float16Type>(
889 [](
Type) {
return llvm::TypeSize::getFixed(16); })
890 .Case<Float32Type>([](
Type) {
return llvm::TypeSize::getFixed(32); })
891 .Case<Float64Type>([](
Type) {
return llvm::TypeSize::getFixed(64); })
892 .Case<Float80Type>([](
Type) {
return llvm::TypeSize::getFixed(80); })
893 .Case<Float128Type>([](
Type) {
return llvm::TypeSize::getFixed(128); })
894 .Case<IntegerType>([](IntegerType intTy) {
895 return llvm::TypeSize::getFixed(intTy.getWidth());
897 .Case<LLVMPPCFP128Type>(
898 [](
Type) {
return llvm::TypeSize::getFixed(128); })
899 .Case<VectorType>([](VectorType t) {
901 "unexpected incompatible with LLVM vector type");
902 llvm::TypeSize elementSize =
904 return llvm::TypeSize(elementSize.getFixedValue() * t.getNumElements(),
905 elementSize.isScalable());
907 .Default([](
Type ty) {
908 assert((llvm::isa<LLVMVoidType, LLVMLabelType, LLVMMetadataType,
909 LLVMTokenType, LLVMStructType, LLVMArrayType,
910 LLVMPointerType, LLVMFunctionType, LLVMTargetExtType>(
912 "unexpected missing support for primitive type");
913 return llvm::TypeSize::getFixed(0);
921void LLVMDialect::registerTypes() {
923#define GET_TYPEDEF_LIST
924#include "mlir/Dialect/LLVMIR/LLVMTypes.cpp.inc"
932void LLVMDialect::printType(Type type, DialectAsmPrinter &os)
const {
static Type getElementType(Type type)
Determine the element type of type.
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 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 constexpr llvm::StringRef kSpirvPrefix
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 bool isCompatiblePtrType(Type type)
Check whether type is a compatible ptr type.
static OptionalParseResult generatedTypeParser(AsmParser &parser, StringRef *mnemonic, Type &value)
These are unused for now.
static ParseResult parseFunctionTypes(AsmParser &p, SmallVector< Type > ¶ms, bool &isVarArg)
constexpr static const uint64_t kBitsInByte
static constexpr llvm::StringRef kArmSVCount
static LogicalResult generatedTypePrinter(Type def, AsmPrinter &printer)
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)
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 class represents a diagnostic that is inflight and set to be reported.
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
This class implements Optional functionality for ParseResult.
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 isLoadableType(Type type)
Returns true if the given type is a loadable type compatible with the LLVM dialect.
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.
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
::llvm::MapVector<::mlir::StringAttr, ::mlir::DataLayoutEntryInterface > DataLayoutIdentifiedEntryMap
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::ArrayRef< DataLayoutEntryInterface > DataLayoutEntryListRef
llvm::function_ref< Fn > function_ref