41 uint64_t NumBits =
IT->getSizeInBits().getFixedValue();
45 std::max<uint64_t>(8, std::min<uint64_t>(64,
llvm::bit_ceil(NumBits)));
56 if (Width & (Width - 1))
69 return Ty->getSizeInBits().getFixedValue();
79 bool Has64BitPointers;
83 void postMerge(
unsigned AggregateSize,
Class &
Lo,
Class &
Hi)
const;
86 bool IsNamedArg,
bool IsRegCall =
false)
const;
88 const Type *getIntegerTypeAtOffset(
const Type *IRType,
unsigned IROffset,
90 unsigned SourceOffset,
91 bool InMemory =
false)
const;
93 const Type *getSSETypeAtOffset(
const Type *ABIType,
unsigned ABIOffset,
95 unsigned SourceOffset)
const;
96 bool isIllegalVectorType(
const Type *Ty)
const;
97 bool containsMatrixField(
const RecordType *RT)
const;
100 ArgInfo getIndirectReturnResult(
const Type *Ty)
const;
101 const Type *getFPTypeAtOffset(
const Type *Ty,
unsigned Offset)
const;
103 const Type *isSingleElementStruct(
const Type *Ty)
const;
104 const Type *getByteVectorType(
const Type *Ty)
const;
107 ArgInfo getIndirectResult(
const Type *Ty,
unsigned FreeIntRegs)
const;
109 ArgInfo classifyReturnType(
const Type *RetTy)
const;
111 ArgInfo classifyArgumentType(
const Type *Ty,
unsigned FreeIntRegs,
112 unsigned &NeededInt,
unsigned &NeededSse,
113 bool IsNamedArg,
bool IsRegCall =
false)
const;
119 Has64BitPointers(Has64BitPtrs) {}
133 if (Fields.
empty()) {
137 const Type *StorageType =
nullptr;
139 for (
const auto &
Field : Fields) {
140 if (
Field.IsBitField &&
Field.IsUnnamedBitfield &&
141 Field.BitFieldWidth == 0) {
148 StorageType = FieldType;
159 FieldType->getSizeInBits().getFixedValue()))
164 (FieldType->getAlignment() == StorageType->
getAlignment() &&
167 StorageType = FieldType;
173void X86_64TargetInfo::postMerge(
unsigned AggregateSize, Class &
Lo,
230 "Invalid accumulated classification during merge.");
251bool X86_64TargetInfo::containsMatrixField(
const RecordType *RT)
const {
252 for (
const auto &
Field : RT->getFields()) {
256 if (AT->isMatrixType())
262 if (containsMatrixField(NestedRT))
268void X86_64TargetInfo::classify(
const Type *
T,
uint64_t OffsetBase, Class &
Lo,
269 Class &
Hi,
bool IsNamedArg,
270 bool IsRegCall)
const {
272 Class &Current = OffsetBase < 64 ?
Lo :
Hi;
281 auto BitWidth =
IT->getSizeInBits().getFixedValue();
295 const auto *FltSem = FT->getSemantics();
313 if (
T->isPointer()) {
319 if (MPT->isFunctionPointer()) {
320 if (Has64BitPointers) {
323 uint64_t EbFuncPtr = OffsetBase / 64;
324 uint64_t EbThisAdj = (OffsetBase + 64 - 1) / 64;
325 if (EbFuncPtr != EbThisAdj) {
338 auto Size = VT->getSizeInBits().getFixedValue();
353 }
else if (
Size == 64) {
364 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
376 if (OffsetBase && OffsetBase != 64)
378 }
else if (
Size == 128 ||
381 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
384 ElemBits == 128 && !
IT->isBitInt())
415 else if (
Size <= 128)
418 const auto *FltSem = EFT->getSemantics();
437 uint64_t EbImag = (OffsetBase + ElementSize) / 64;
449 if (AT->isMatrixType())
459 if (!IsRegCall &&
Size > 512)
468 if (OffsetBase % ElemAlign)
475 uint64_t ArraySize = AT->getNumElements();
487 Class FieldLo, FieldHi;
488 classify(ElementType,
Offset, FieldLo, FieldHi, IsNamedArg);
489 Lo = merge(
Lo, FieldLo);
490 Hi = merge(
Hi, FieldHi);
502 if (containsMatrixField(RT)) {
519 if (RT->hasFlexibleArrayMember())
526 if (RT->isCXXRecord()) {
527 for (
const auto &
Base : RT->getBaseClasses()) {
534 Class FieldLo, FieldHi;
536 classify(
Base.FieldType,
Offset, FieldLo, FieldHi, IsNamedArg);
537 Lo = merge(
Lo, FieldLo);
538 Hi = merge(
Hi, FieldHi);
542 (
Size !=
Base.FieldType->getSizeInBits().getFixedValue() ||
556 for (
const auto &
Field : RT->getFields()) {
564 ?
Field.BitFieldWidth == 0
565 :
Field.IsUnnamedBitfield))
570 Size !=
Field.FieldType->getSizeInBits().getFixedValue()) ||
577 bool IsInMemory =
Offset % (
Field.FieldType->getAlignment().value() * 8);
578 if (!BitField && IsInMemory) {
584 Class FieldLo, FieldHi;
592 assert(EbHi == EbLo &&
"Invalid classification, type > 16 bytes.");
600 classify(
Field.FieldType,
Offset, FieldLo, FieldHi, IsNamedArg);
603 Lo = merge(
Lo, FieldLo);
604 Hi = merge(
Hi, FieldHi);
617X86_64TargetInfo::classifyArgumentType(
const Type *Ty,
unsigned FreeIntRegs,
618 unsigned &NeededInt,
unsigned &NeededSSE,
619 bool IsNamedArg,
bool IsRegCall)
const {
624 classify(Ty, 0,
Lo,
Hi, IsNamedArg, IsRegCall);
632 const Type *ResType =
nullptr;
641 "Unknown missing lo part");
653 return getIndirectResult(Ty, FreeIntRegs);
666 ResType = getIntegerTypeAtOffset(Ty, 0, Ty, 0);
670 if (
Hi ==
NoClass && ResType->isInteger()) {
675 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
686 ResType = getSSETypeAtOffset(Ty, 0, Ty, 0);
691 const Type *HighPart =
nullptr;
707 HighPart = getIntegerTypeAtOffset(Ty, 8, Ty, 8);
718 HighPart = getSSETypeAtOffset(Ty, 8, Ty, 8);
728 assert(
Lo ==
Sse &&
"Unexpected SseUp classification");
729 ResType = getByteVectorType(Ty);
737 ResType = createPairType(ResType, HighPart);
742ArgInfo X86_64TargetInfo::classifyReturnType(
const Type *RetTy)
const {
747 classify(RetTy, 0,
Lo,
Hi,
true);
753 const Type *ResType =
nullptr;
761 "Unknown missing lo part");
770 return getIndirectReturnResult(RetTy);
775 ResType = getIntegerTypeAtOffset(RetTy, 0, RetTy, 0);
778 if (
Hi ==
NoClass && ResType->isInteger()) {
784 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
793 ResType = getSSETypeAtOffset(RetTy, 0, RetTy, 0);
808 const Type *X87Type =
810 FieldInfo Fields[] = {FieldInfo(X87Type, 0), FieldInfo(X87Type, 80)};
816 const Type *HighPart =
nullptr;
829 HighPart = getIntegerTypeAtOffset(RetTy, 8, RetTy, 8);
835 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
846 assert(
Lo ==
Sse &&
"Unexpected SseUp classification.");
847 ResType = getByteVectorType(RetTy);
858 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
869 ResType = createPairType(ResType, HighPart);
879const Type *X86_64TargetInfo::createPairType(
const Type *
Lo,
886 llvm::Align HiAlign =
Hi->getAlignment();
887 unsigned HiStart =
alignTo(LoSize, HiAlign);
889 assert(HiStart != 0 && HiStart <= 8 &&
"Invalid x86-64 argument pair!");
895 const Type *AdjustedLo =
Lo;
910 else if (
Lo->isInteger() ||
Lo->isPointer())
911 AdjustedLo = TB.getIntegerType(64,
Align(8),
false);
913 assert((
Lo->isInteger() ||
Lo->isPointer()) &&
914 "Invalid/unknown low type in pair");
915 unsigned AdjustedLoSize = AdjustedLo->getSizeInBits().getFixedValue() / 8;
916 HiStart =
alignTo(AdjustedLoSize, HiAlign);
920 FieldInfo Fields[] = {FieldInfo(AdjustedLo, 0), FieldInfo(
Hi, HiStart * 8)};
923 assert((8 * 8) == Fields[1].OffsetInBits &&
924 "High part must be at offset 8 bytes");
927 Fields[1].OffsetInBits +
Hi->getSizeInBits().getFixedValue();
935 unsigned TySize = Ty->getSizeInBits().getFixedValue();
936 if (TySize <= StartBit)
941 const Type *EltTy = AT->getElementType();
944 for (
unsigned I = 0;
I < AT->getNumElements(); ++
I) {
945 unsigned EltOffset =
I * EltSize;
946 if (EltOffset >= EndBit)
949 unsigned EltStart = (EltOffset < StartBit) ? StartBit - EltOffset : 0;
960 if (RT->isCXXRecord()) {
961 for (
unsigned I = 0;
I < RT->getNumBaseClasses(); ++
I) {
963 if (
Base.OffsetInBits >= EndBit)
967 (
Base.OffsetInBits < StartBit) ? StartBit -
Base.OffsetInBits : 0;
969 EndBit -
Base.OffsetInBits))
974 for (
unsigned I = 0;
I < RT->getNumFields(); ++
I) {
976 if (
Field.OffsetInBits >= EndBit)
979 unsigned FieldStart =
980 (
Field.OffsetInBits < StartBit) ? StartBit -
Field.OffsetInBits : 0;
982 EndBit -
Field.OffsetInBits))
992const Type *X86_64TargetInfo::getIntegerTypeAtOffset(
const Type *ABIType,
994 const Type *SourceTy,
995 unsigned SourceOffset,
996 bool InMemory)
const {
998 const Type *WorkingType = ABIType;
999 if (InMemory && ABIType->isInteger()) {
1001 unsigned OriginalBitWidth =
IT->getSizeInBits().getFixedValue();
1003 unsigned WidenedBitWidth = OriginalBitWidth;
1004 if (OriginalBitWidth <= 8) {
1005 WidenedBitWidth = 8;
1010 if (WidenedBitWidth != OriginalBitWidth) {
1011 WorkingType = TB.getIntegerType(WidenedBitWidth,
ABIType->getAlignment(),
1017 if (ABIOffset == 0) {
1022 if ((WorkingType->isPointer() && Has64BitPointers) ||
1023 (WorkingType->isInteger() &&
1033 if ((WorkingType->isInteger() &&
1038 (WorkingType->isPointer() && !Has64BitPointers)) {
1040 unsigned BitWidth = WorkingType->isPointer()
1045 SourceOffset * 8 + 64))
1051 if (RTy->isUnion()) {
1054 return getIntegerTypeAtOffset(ReducedType, ABIOffset, SourceTy,
1055 SourceOffset,
true);
1057 if (
const FieldInfo *Element =
1058 RTy->getElementContainingOffset(ABIOffset * 8)) {
1060 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1061 return getIntegerTypeAtOffset(Element->FieldType,
1062 ABIOffset - ElementOffsetBytes, SourceTy,
1063 SourceOffset,
true);
1068 const Type *EltTy = ATy->getElementType();
1069 unsigned EltSize = EltTy->getSizeInBits() / 8;
1071 unsigned EltOffset = (ABIOffset / EltSize) * EltSize;
1072 return getIntegerTypeAtOffset(EltTy, ABIOffset - EltOffset, SourceTy,
1073 SourceOffset,
true);
1084 unsigned TySizeInBytes =
1089 alignTo(SourceTy->getSizeInBits().getFixedValue(), 64) / 8;
1091 assert(TySizeInBytes != SourceOffset &&
"Empty field?");
1092 unsigned AvailableSize = TySizeInBytes - SourceOffset;
1093 return TB.getIntegerType(std::min(AvailableSize, 8U) * 8,
Align(1),
false);
1097const Type *X86_64TargetInfo::getFPTypeAtOffset(
const Type *Ty,
1100 if (
Offset == 0 && Ty->isFloat())
1105 unsigned ElementSize =
ElementType->getSizeInBits().getFixedValue() / 8;
1114 if (
const FieldInfo *Element = RT->getElementContainingOffset(
Offset * 8)) {
1115 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1116 return getFPTypeAtOffset(Element->FieldType,
Offset - ElementOffsetBytes);
1122 const Type *EltTy = AT->getElementType();
1123 unsigned EltSize = EltTy->getSizeInBits() / 8;
1124 unsigned EltIndex =
Offset / EltSize;
1126 return getFPTypeAtOffset(EltTy,
Offset - (EltIndex * EltSize));
1144const Type *X86_64TargetInfo::getSSETypeAtOffset(
const Type *ABIType,
1146 const Type *SourceTy,
1147 unsigned SourceOffset)
const {
1150 if (RTy->isUnion()) {
1153 return getSSETypeAtOffset(ReducedType, ABIOffset, SourceTy,
1159 auto Is16bitFpTy = [](
const Type *
T) {
1165 const Type *T0 = getFPTypeAtOffset(ABIType, ABIOffset);
1170 unsigned SourceSize =
1171 (SourceTy->getSizeInBits().getFixedValue() / 8) - SourceOffset;
1174 const Type *
T1 =
nullptr;
1176 alignTo(T0->getSizeInBits().getFixedValue(), T0->getAlignment().value()) /
1178 if (SourceSize > T0Size)
1179 T1 = getFPTypeAtOffset(ABIType, ABIOffset + T0Size);
1181 if (
T1 ==
nullptr) {
1182 if (Is16bitFpTy(T0) && SourceSize > 4)
1183 T1 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1193 if (Is16bitFpTy(T0) && Is16bitFpTy(
T1)) {
1194 const Type *T2 =
nullptr;
1196 T2 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1203 if (Is16bitFpTy(T0) || Is16bitFpTy(
T1))
1213const Type *X86_64TargetInfo::getByteVectorType(
const Type *Ty)
const {
1216 if (
const Type *InnerTy = isSingleElementStruct(Ty))
1224 VT->getElementType()->isInteger() &&
1226 unsigned Size = VT->getSizeInBits().getFixedValue();
1227 return TB.getVectorType(TB.getIntegerType(64,
Align(8),
false),
1239 unsigned Size = Ty->getSizeInBits().getFixedValue();
1247const Type *X86_64TargetInfo::isSingleElementStruct(
const Type *Ty)
const {
1252 if (RT->hasFlexibleArrayMember())
1255 const Type *Found =
nullptr;
1257 for (
const auto &
Base : RT->getBaseClasses()) {
1258 const Type *BaseTy =
Base.FieldType;
1261 if (!BaseRT || BaseRT->isEmpty())
1264 const Type *Elem = isSingleElementStruct(BaseTy);
1270 for (
const auto &FI : RT->getFields()) {
1274 const Type *FTy = FI.FieldType;
1277 if (AT->getNumElements() != 1)
1279 FTy = AT->getElementType();
1284 Elem = isSingleElementStruct(InnerRT);
1294 if (Found->getSizeInBits() != Ty->getSizeInBits())
1300bool X86_64TargetInfo::isIllegalVectorType(
const Type *Ty)
const {
1302 uint64_t Size = VecTy->getSizeInBits().getFixedValue();
1310 const Type *EltTy = VecTy->getElementType();
1313 if (IntTy->getSizeInBits().getFixedValue() == 128)
1320ArgInfo X86_64TargetInfo::getIndirectResult(
const Type *Ty,
1321 unsigned FreeIntRegs)
const {
1344 uint64_t AlignVal = std::max<uint64_t>(Ty->getAlignment().value(), 8u);
1367 if (FreeIntRegs == 0) {
1375 if (AlignVal == 8 &&
Size <= 64) {
1377 TB.getIntegerType(
Size, llvm::Align(8),
false);
1385ArgInfo X86_64TargetInfo::getIndirectReturnResult(
const Type *Ty)
const {
1389 if (IntTy->isBitInt())
1400void X86_64TargetInfo::computeInfo(
FunctionInfo &FI)
const {
1406 switch (CallingConv) {
1411 "calling convention not supported by the LLVMABI X86_64 classifier");
1414 unsigned FreeIntRegs = 6;
1415 unsigned FreeSSERegs = 8;
1416 unsigned NeededInt = 0, NeededSSE = 0;
1419 const Type *RetTy = FI.getReturnType();
1420 FI.getReturnInfo() = classifyReturnType(RetTy);
1423 if (FI.getReturnInfo().isIndirect())
1426 unsigned NumRequiredArgs = FI.getNumRequiredArgs();
1429 for (
auto IT = FI.arg_begin(), IE = FI.arg_end();
IT != IE; ++
IT, ++ArgNo) {
1430 bool IsNamedArg = ArgNo < NumRequiredArgs;
1431 const Type *ArgTy =
IT->ABIType;
1435 ArgInfo AI = classifyArgumentType(ArgTy, FreeIntRegs, NeededInt, NeededSSE,
1442 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
1443 FreeIntRegs -= NeededInt;
1444 FreeSSERegs -= NeededSSE;
1448 IT->Info = getIndirectResult(ArgTy, FreeIntRegs);
1453std::unique_ptr<TargetInfo>
1456 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)
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 getDirect(const Type *T=nullptr, unsigned Offset=0, MaybeAlign Align=std::nullopt)
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 ...
const fltSemantics * getSemantics() const
ArrayRef< FieldInfo > getFields() const
bool isTransparentUnion() const
LLVM_ABI ArgInfo getNaturalAlignIndirect(const Type *Ty, bool ByVal=true) const
const ABICompatInfo & getABICompatInfo() const
LLVM_ABI bool isPromotableInteger(const IntegerType *IT) const
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 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
Align getAlignment() const
ElementCount getNumElements() const
const Type * getElementType() const
X86_64TargetInfo(TypeBuilder &TypeBuilder, X86AVXABILevel AVXABILevel, bool Has64BitPtrs, const ABICompatInfo &Compat)
bool has64BitPointers() const
constexpr ScalarTy getFixedValue() const
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
This class provides various memory handling functions that manipulate MemoryBlock instances.
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.
static uint64_t getClangTypeWidthInBits(const Type *Ty)
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)
LLVM_ABI std::unique_ptr< TargetInfo > createX86_64TargetInfo(TypeBuilder &TB, X86AVXABILevel AVXLevel, bool Has64BitPointers, const ABICompatInfo &Compat)
static uint64_t getClangVectorWidthInBits(const VectorType *VT)
static uint64_t getClangIntegerWidthInBits(const IntegerType *IT)
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 target-specific ABI compatibility behaviour.