42 bool Has64BitPointers;
47 void postMerge(
unsigned AggregateSize,
Class &
Lo,
Class &
Hi)
const;
50 bool IsNamedArg,
bool IsRegCall =
false)
const;
52 const Type *getIntegerTypeAtOffset(
const Type *IRType,
unsigned IROffset,
54 unsigned SourceOffset,
55 bool InMemory =
false)
const;
57 const Type *getSSETypeAtOffset(
const Type *ABIType,
unsigned ABIOffset,
59 unsigned SourceOffset)
const;
60 bool isIllegalVectorType(
const Type *Ty)
const;
61 bool containsMatrixField(
const RecordType *RT)
const;
64 ArgInfo getIndirectReturnResult(
const Type *Ty)
const;
65 const Type *getFPTypeAtOffset(
const Type *Ty,
unsigned Offset)
const;
67 const Type *getByteVectorType(
const Type *Ty)
const;
70 ArgInfo getIndirectResult(
const Type *Ty,
unsigned FreeIntRegs)
const;
72 ArgInfo classifyReturnType(
const Type *RetTy)
const;
74 ArgInfo classifyArgumentType(
const Type *Ty,
unsigned FreeIntRegs,
75 unsigned &NeededInt,
unsigned &NeededSse,
76 bool IsNamedArg,
bool IsRegCall =
false)
const;
78 bool shouldExtendReturnType(
const IntegerType *RetTy)
const;
84 Has64BitPointers(Has64BitPtrs), X86CompatInfo(Compat) {}
104 if (Fields.
empty()) {
108 const Type *StorageType =
nullptr;
110 for (
const auto &
Field : Fields) {
111 if (
Field.IsBitField &&
Field.IsUnnamedBitfield &&
112 Field.BitFieldWidth == 0) {
119 StorageType = FieldType;
134 (FieldType->getAlignment() == StorageType->
getAlignment() &&
137 StorageType = FieldType;
143bool X86_64TargetInfo::shouldExtendReturnType(
const IntegerType *RetTy)
const {
149 bool IsDarwin =
false;
156void X86_64TargetInfo::postMerge(
unsigned AggregateSize, Class &
Lo,
213 "Invalid accumulated classification during merge.");
234bool X86_64TargetInfo::containsMatrixField(
const RecordType *RT)
const {
235 for (
const auto &
Field : RT->getFields()) {
239 if (AT->isMatrixType())
245 if (containsMatrixField(NestedRT))
251void X86_64TargetInfo::classify(
const Type *
T,
uint64_t OffsetBase, Class &
Lo,
252 Class &
Hi,
bool IsNamedArg,
253 bool IsRegCall)
const {
255 Class &Current = OffsetBase < 64 ?
Lo :
Hi;
264 auto BitWidth =
IT->getSizeInBits().getFixedValue();
278 const auto *FltSem = FT->getSemantics();
296 if (
T->isPointer()) {
302 if (MPT->isFunctionPointer()) {
303 if (Has64BitPointers) {
306 uint64_t EbFuncPtr = OffsetBase / 64;
307 uint64_t EbThisAdj = (OffsetBase + 64 - 1) / 64;
308 if (EbFuncPtr != EbThisAdj) {
321 assert(VT->isFixedLength() &&
"x86-64 has no scalable vectors");
337 }
else if (
Size == 64) {
348 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
360 if (OffsetBase && OffsetBase != 64)
362 }
else if (
Size == 128 ||
365 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
368 ElemBits == 128 && !
IT->isBitInt())
399 else if (
Size <= 128)
402 const auto *FltSem = EFT->getSemantics();
421 uint64_t EbImag = (OffsetBase + ElementSize) / 64;
433 if (AT->isMatrixType())
443 if (!IsRegCall &&
Size > 512)
452 if (OffsetBase % ElemAlign)
459 uint64_t ArraySize = AT->getNumElements();
471 Class FieldLo, FieldHi;
472 classify(ElementType,
Offset, FieldLo, FieldHi, IsNamedArg);
473 Lo = merge(
Lo, FieldLo);
474 Hi = merge(
Hi, FieldHi);
486 if (containsMatrixField(RT)) {
503 if (RT->hasFlexibleArrayMember())
510 if (RT->isCXXRecord()) {
511 for (
const auto &
Base : RT->getBaseClasses()) {
518 Class FieldLo, FieldHi;
520 classify(
Base.FieldType,
Offset, FieldLo, FieldHi, IsNamedArg);
521 Lo = merge(
Lo, FieldLo);
522 Hi = merge(
Hi, FieldHi);
525 (
Size > 128 && (
Size !=
Base.FieldType->getABISizeInBits() ||
539 for (
const auto &
Field : RT->getFields()) {
547 ?
Field.BitFieldWidth == 0
548 :
Field.IsUnnamedBitfield))
559 bool IsInMemory =
Offset % (
Field.FieldType->getAlignment().value() * 8);
560 if (!BitField && IsInMemory) {
566 Class FieldLo, FieldHi;
574 assert(EbHi == EbLo &&
"Invalid classification, type > 16 bytes.");
582 classify(
Field.FieldType,
Offset, FieldLo, FieldHi, IsNamedArg);
585 Lo = merge(
Lo, FieldLo);
586 Hi = merge(
Hi, FieldHi);
599X86_64TargetInfo::classifyArgumentType(
const Type *Ty,
unsigned FreeIntRegs,
600 unsigned &NeededInt,
unsigned &NeededSSE,
601 bool IsNamedArg,
bool IsRegCall)
const {
606 classify(Ty, 0,
Lo,
Hi, IsNamedArg, IsRegCall);
614 const Type *ResType =
nullptr;
623 "Unknown missing lo part");
635 return getIndirectResult(Ty, FreeIntRegs);
648 ResType = getIntegerTypeAtOffset(Ty, 0, Ty, 0);
652 if (
Hi ==
NoClass && ResType->isInteger()) {
657 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
668 ResType = getSSETypeAtOffset(Ty, 0, Ty, 0);
673 const Type *HighPart =
nullptr;
689 HighPart = getIntegerTypeAtOffset(Ty, 8, Ty, 8);
700 HighPart = getSSETypeAtOffset(Ty, 8, Ty, 8);
710 assert(
Lo ==
Sse &&
"Unexpected SseUp classification");
711 ResType = getByteVectorType(Ty);
719 ResType = createPairType(ResType, HighPart);
724ArgInfo X86_64TargetInfo::classifyReturnType(
const Type *RetTy)
const {
729 classify(RetTy, 0,
Lo,
Hi,
true);
735 const Type *ResType =
nullptr;
743 "Unknown missing lo part");
752 return getIndirectReturnResult(RetTy);
757 ResType = getIntegerTypeAtOffset(RetTy, 0, RetTy, 0);
760 if (
Hi ==
NoClass && ResType->isInteger()) {
764 : ArgInfo::getDirect(RetTy);
766 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
775 ResType = getSSETypeAtOffset(RetTy, 0, RetTy, 0);
790 const Type *X87Type =
792 FieldInfo Fields[] = {FieldInfo(X87Type, 0), FieldInfo(X87Type, 80)};
799 const Type *HighPart =
nullptr;
812 HighPart = getIntegerTypeAtOffset(RetTy, 8, RetTy, 8);
818 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
829 assert(
Lo ==
Sse &&
"Unexpected SseUp classification.");
830 ResType = getByteVectorType(RetTy);
841 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
852 ResType = createPairType(ResType, HighPart);
862const Type *X86_64TargetInfo::createPairType(
const Type *
Lo,
869 llvm::Align HiAlign =
Hi->getAlignment();
870 unsigned HiStart =
alignTo(LoSize, HiAlign);
872 assert(HiStart != 0 && HiStart <= 8 &&
"Invalid x86-64 argument pair!");
878 const Type *AdjustedLo =
Lo;
893 else if (
Lo->isInteger() ||
Lo->isPointer())
894 AdjustedLo =
TB.getIntegerType(64,
Align(8),
false);
896 assert((
Lo->isInteger() ||
Lo->isPointer()) &&
897 "Invalid/unknown low type in pair");
898 unsigned AdjustedLoSize = AdjustedLo->getSizeInBits().getFixedValue() / 8;
899 HiStart =
alignTo(AdjustedLoSize, HiAlign);
903 FieldInfo Fields[] = {FieldInfo(AdjustedLo, 0), FieldInfo(
Hi, HiStart * 8)};
906 assert((8 * 8) == Fields[1].OffsetInBits &&
907 "High part must be at offset 8 bytes");
910 Fields[1].OffsetInBits +
Hi->getSizeInBits().getFixedValue();
918 unsigned TySize = Ty->getABISizeInBits();
919 if (TySize <= StartBit)
924 const Type *EltTy = AT->getElementType();
927 for (
unsigned I = 0;
I < AT->getNumElements(); ++
I) {
928 unsigned EltOffset =
I * EltSize;
929 if (EltOffset >= EndBit)
932 unsigned EltStart = (EltOffset < StartBit) ? StartBit - EltOffset : 0;
943 if (RT->isCXXRecord()) {
944 for (
unsigned I = 0;
I < RT->getNumBaseClasses(); ++
I) {
946 if (
Base.OffsetInBits >= EndBit)
950 (
Base.OffsetInBits < StartBit) ? StartBit -
Base.OffsetInBits : 0;
952 EndBit -
Base.OffsetInBits))
957 for (
unsigned I = 0;
I < RT->getNumFields(); ++
I) {
959 if (
Field.OffsetInBits >= EndBit)
962 unsigned FieldStart =
963 (
Field.OffsetInBits < StartBit) ? StartBit -
Field.OffsetInBits : 0;
965 EndBit -
Field.OffsetInBits))
975const Type *X86_64TargetInfo::getIntegerTypeAtOffset(
const Type *ABIType,
977 const Type *SourceTy,
978 unsigned SourceOffset,
979 bool InMemory)
const {
981 const Type *WorkingType = ABIType;
982 if (InMemory && ABIType->isInteger()) {
984 unsigned OriginalBitWidth =
IT->getSizeInBits().getFixedValue();
986 unsigned WidenedBitWidth = OriginalBitWidth;
987 if (OriginalBitWidth <= 8) {
993 if (WidenedBitWidth != OriginalBitWidth) {
994 WorkingType =
TB.getIntegerType(WidenedBitWidth,
ABIType->getAlignment(),
1000 if (InMemory &&
ABIType->isVector()) {
1003 if (
IT &&
IT->isBool())
1004 WorkingType =
TB.getIntegerType(
1005 std::max<uint64_t>(VT->getNumElements().getFixedValue(), 8),
1006 ABIType->getAlignment(),
false);
1010 if (ABIOffset == 0) {
1015 if ((WorkingType->isPointer() && Has64BitPointers) ||
1016 (WorkingType->isInteger() &&
1026 if ((WorkingType->isInteger() &&
1031 (WorkingType->isPointer() && !Has64BitPointers)) {
1033 unsigned BitWidth = WorkingType->isPointer()
1038 SourceOffset * 8 + 64))
1044 if (RTy->isUnion()) {
1047 if (ABIOffset * 8 < ReducedType->getABISizeInBits())
1048 return getIntegerTypeAtOffset(ReducedType, ABIOffset, SourceTy,
1049 SourceOffset,
true);
1054 SourceOffset * 8 + 64))
1055 return TB.getIntegerType(8,
Align(1),
false);
1056 unsigned RemainingBytes =
1058 return TB.getIntegerType(std::min(RemainingBytes, 8U) * 8,
Align(1),
1062 if (
const FieldInfo *Element =
1063 RTy->getElementContainingOffset(ABIOffset * 8)) {
1065 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1066 return getIntegerTypeAtOffset(Element->FieldType,
1067 ABIOffset - ElementOffsetBytes, SourceTy,
1068 SourceOffset,
true);
1073 const Type *EltTy = ATy->getElementType();
1074 unsigned EltSize = EltTy->getABISizeInBits() / 8;
1076 unsigned EltOffset = (ABIOffset / EltSize) * EltSize;
1077 return getIntegerTypeAtOffset(EltTy, ABIOffset - EltOffset, SourceTy,
1078 SourceOffset,
true);
1089 unsigned TySizeInBytes =
llvm::divideCeil(SourceTy->getABISizeInBits(), 8);
1090 assert(TySizeInBytes != SourceOffset &&
"Empty field?");
1091 unsigned AvailableSize = TySizeInBytes - SourceOffset;
1092 return TB.getIntegerType(std::min(AvailableSize, 8U) * 8,
Align(1),
false);
1096const Type *X86_64TargetInfo::getFPTypeAtOffset(
const Type *Ty,
1099 if (
Offset == 0 && Ty->isFloat())
1104 unsigned ElementSize =
ElementType->getABISizeInBits() / 8;
1113 if (
const FieldInfo *Element = RT->getElementContainingOffset(
Offset * 8)) {
1114 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1115 return getFPTypeAtOffset(Element->FieldType,
Offset - ElementOffsetBytes);
1121 const Type *EltTy = AT->getElementType();
1122 unsigned EltSize = EltTy->getABISizeInBits() / 8;
1125 unsigned EltIndex =
Offset / EltSize;
1127 return getFPTypeAtOffset(EltTy,
Offset - (EltIndex * EltSize));
1145const Type *X86_64TargetInfo::getSSETypeAtOffset(
const Type *ABIType,
1147 const Type *SourceTy,
1148 unsigned SourceOffset)
const {
1151 if (RTy->isUnion()) {
1154 return getSSETypeAtOffset(ReducedType, ABIOffset, SourceTy,
1160 auto Is16bitFpTy = [](
const Type *
T) {
1166 const Type *T0 = getFPTypeAtOffset(ABIType, ABIOffset);
1171 unsigned SourceSize = (SourceTy->getABISizeInBits() / 8) - SourceOffset;
1174 const Type *
T1 =
nullptr;
1175 unsigned T0Size = T0->getABISizeInBits() / 8;
1176 if (SourceSize > T0Size)
1177 T1 = getFPTypeAtOffset(ABIType, ABIOffset + T0Size);
1179 if (
T1 ==
nullptr) {
1180 if (Is16bitFpTy(T0) && SourceSize > 4)
1181 T1 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1191 if (Is16bitFpTy(T0) && Is16bitFpTy(
T1)) {
1192 const Type *T2 =
nullptr;
1194 T2 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1201 if (Is16bitFpTy(T0) || Is16bitFpTy(
T1))
1211const Type *X86_64TargetInfo::getByteVectorType(
const Type *Ty)
const {
1222 VT->getElementType()->isInteger() &&
1224 unsigned Size = VT->getABISizeInBits();
1225 return TB.getVectorType(
TB.getIntegerType(64,
Align(8),
false),
1237 unsigned Size = Ty->getABISizeInBits();
1244bool X86_64TargetInfo::isIllegalVectorType(
const Type *Ty)
const {
1254 const Type *EltTy = VecTy->getElementType();
1257 if (IntTy->getSizeInBits().getFixedValue() == 128 && !IntTy->isBitInt())
1264ArgInfo X86_64TargetInfo::getIndirectResult(
const Type *Ty,
1265 unsigned FreeIntRegs)
const {
1289 uint64_t AlignVal = std::max<uint64_t>(Ty->getAlignment().value(), 8u);
1312 if (FreeIntRegs == 0) {
1317 if (AlignVal == 8 &&
Size <= 64) {
1319 TB.getIntegerType(
Size, llvm::Align(8),
false);
1327ArgInfo X86_64TargetInfo::getIndirectReturnResult(
const Type *Ty)
const {
1331 if (IntTy->isBitInt())
1333 if (shouldExtendReturnType(IntTy))
1342void X86_64TargetInfo::computeInfo(
FunctionInfo &FI)
const {
1348 switch (CallingConv) {
1353 "calling convention not supported by the LLVMABI X86_64 classifier");
1356 unsigned FreeIntRegs = 6;
1357 unsigned FreeSSERegs = 8;
1358 unsigned NeededInt = 0, NeededSSE = 0;
1361 const Type *RetTy = FI.getReturnType();
1362 FI.getReturnInfo() = classifyReturnType(RetTy);
1365 if (FI.getReturnInfo().isIndirect())
1368 unsigned NumRequiredArgs = FI.getNumRequiredArgs();
1371 for (
auto IT = FI.arg_begin(), IE = FI.arg_end();
IT != IE; ++
IT, ++ArgNo) {
1372 bool IsNamedArg = ArgNo < NumRequiredArgs;
1373 const Type *ArgTy =
IT->ABIType;
1377 ArgInfo AI = classifyArgumentType(ArgTy, FreeIntRegs, NeededInt, NeededSSE,
1384 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
1385 FreeIntRegs -= NeededInt;
1386 FreeSSERegs -= NeededSSE;
1387 AI.setNeededRegs(NeededInt, NeededSSE);
1392 IT->Info = getIndirectResult(ArgTy, FreeIntRegs);
1397std::unique_ptr<TargetInfo>
1400 return std::make_unique<X86_64TargetInfo>(TB, AVXLevel, Has64BitPointers,
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static LoopDeletionResult merge(LoopDeletionResult A, LoopDeletionResult B)
OptimizedStructLayoutField Field
FunctionLoweringInfo::StatepointRelocationRecord RecordType
Target-specific ABI information and factory functions.
static const fltSemantics & IEEEsingle()
static const fltSemantics & BFloat()
static const fltSemantics & IEEEquad()
static const fltSemantics & IEEEdouble()
static const fltSemantics & x87DoubleExtended()
static const fltSemantics & IEEEhalf()
Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
Check if the array is empty.
static constexpr ElementCount getFixed(ScalarTy MinVal)
Class to represent integer types.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
Helper class to encapsulate information about how a specific type should be passed to or returned fro...
static ArgInfo getIgnore()
static ArgInfo getExtend(const Type *T)
static ArgInfo getIndirect(Align Align, bool ByVal, unsigned AddrSpace=0, bool Realign=false)
Realign: the caller couldn't guarantee sufficient alignment - the callee must copy the argument to a ...
static ArgInfo getDirect(const Type *T=nullptr, unsigned Offset=0, MaybeAlign Align=std::nullopt, bool CanBeFlattened=true)
const fltSemantics * getSemantics() const
ArrayRef< FieldInfo > getFields() const
bool isTransparentUnion() const
LLVM_ABI const Type * isSingleElementStruct(const Type *Ty) const
Returns the scalar a single-element struct reduces to, else null.
virtual unsigned getAllocaAddrSpace() const
Address space in which indirect arguments are allocated (the target's alloca/stack space).
LLVM_ABI bool isPromotableInteger(const IntegerType *IT) const
TargetInfo(TypeBuilder &Builder)
LLVM_ABI bool maybeCommonClassifyReturnType(FunctionInfo &FI) const
Apply rules for classifying return types that are common to all targets.
LLVM_ABI bool isAggregateTypeForABI(const Type *Ty) const
LLVM_ABI const Type * useFirstFieldIfTransparentUnion(const Type *Ty) const
If Ty is a transparent union, return its first field type; otherwise return Ty unchanged.
LLVM_ABI ArgInfo getNaturalAlignIndirect(const Type *Ty, unsigned AddrSpace, bool ByVal=true) const
LLVM_ABI RecordArgABI getRecordArgABI(const RecordType *RT) const
TypeBuilder manages the lifecycle of ABI types using bump pointer allocation.
Represents the ABI-specific view of a type in LLVM.
TypeSize getTypeAllocSize() const
TypeSize getSizeInBits() const
LLVM_ABI uint64_t getABISizeInBits() const
Returns the size in bits that the source language gives this type, including any padding.
Align getAlignment() const
X86_64TargetInfo(TypeBuilder &TypeBuilder, X86AVXABILevel AVXABILevel, bool Has64BitPtrs, const X86ABICompatInfo &Compat)
bool has64BitPointers() const
const X86ABICompatInfo & getX86ABICompatInfo() const
const ABICompatInfo & getABICompatInfo() const override
Return this target's ABI compatibility flags.
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
This file defines the type system for the LLVMABI library, which mirrors ABI-relevant aspects of fron...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI std::unique_ptr< TargetInfo > createX86_64TargetInfo(TypeBuilder &TB, X86AVXABILevel AVXLevel, bool Has64BitPointers, const X86ABICompatInfo &Compat)
static unsigned getNativeVectorSizeForAVXABI(X86AVXABILevel AVXLevel)
X86AVXABILevel
The AVX ABI level for X86 targets.
static const Type * reduceUnionForX8664(const RecordType *UnionType, TypeBuilder &TB)
static bool bitsContainNoUserData(const Type *Ty, unsigned StartBit, unsigned EndBit)
static bool isFloatTypeWithSemantics(const Type *Ty, const fltSemantics &Semantics)
Helper to check if a floating point type matches specific semantics.
@ RAA_Indirect
Pass it as a pointer to temporary memory.
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
ElementType
The element type of an SRV or UAV resource.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Flags controlling ABI compatibility behaviour that applies to every target.
Flags controlling X86-specific ABI compatibility behaviour.