41 uint64_t NumBits =
IT->getSizeInBits().getFixedValue();
45 std::max<uint64_t>(8, std::min<uint64_t>(64,
llvm::bit_ceil(NumBits)));
67 return Ty->getSizeInBits().getFixedValue();
76 bool Has64BitPointers;
81 void postMerge(
unsigned AggregateSize,
Class &
Lo,
Class &
Hi)
const;
84 bool IsNamedArg,
bool IsRegCall =
false)
const;
86 const Type *getIntegerTypeAtOffset(
const Type *IRType,
unsigned IROffset,
88 unsigned SourceOffset,
89 bool InMemory =
false)
const;
91 const Type *getSSETypeAtOffset(
const Type *ABIType,
unsigned ABIOffset,
93 unsigned SourceOffset)
const;
94 bool isIllegalVectorType(
const Type *Ty)
const;
95 bool containsMatrixField(
const RecordType *RT)
const;
98 ArgInfo getIndirectReturnResult(
const Type *Ty)
const;
99 const Type *getFPTypeAtOffset(
const Type *Ty,
unsigned Offset)
const;
101 const Type *isSingleElementStruct(
const Type *Ty)
const;
102 const Type *getByteVectorType(
const Type *Ty)
const;
105 ArgInfo getIndirectResult(
const Type *Ty,
unsigned FreeIntRegs)
const;
107 ArgInfo classifyReturnType(
const Type *RetTy)
const;
109 ArgInfo classifyArgumentType(
const Type *Ty,
unsigned FreeIntRegs,
110 unsigned &NeededInt,
unsigned &NeededSse,
111 bool IsNamedArg,
bool IsRegCall =
false)
const;
117 Has64BitPointers(Has64BitPtrs), X86CompatInfo(Compat) {}
122 return X86CompatInfo;
137 if (Fields.
empty()) {
141 const Type *StorageType =
nullptr;
143 for (
const auto &
Field : Fields) {
144 if (
Field.IsBitField &&
Field.IsUnnamedBitfield &&
145 Field.BitFieldWidth == 0) {
152 StorageType = FieldType;
163 FieldType->getSizeInBits().getFixedValue()))
168 (FieldType->getAlignment() == StorageType->
getAlignment() &&
171 StorageType = FieldType;
177void X86_64TargetInfo::postMerge(
unsigned AggregateSize, Class &
Lo,
234 "Invalid accumulated classification during merge.");
255bool X86_64TargetInfo::containsMatrixField(
const RecordType *RT)
const {
256 for (
const auto &
Field : RT->getFields()) {
260 if (AT->isMatrixType())
266 if (containsMatrixField(NestedRT))
272void X86_64TargetInfo::classify(
const Type *
T,
uint64_t OffsetBase, Class &
Lo,
273 Class &
Hi,
bool IsNamedArg,
274 bool IsRegCall)
const {
276 Class &Current = OffsetBase < 64 ?
Lo :
Hi;
285 auto BitWidth =
IT->getSizeInBits().getFixedValue();
299 const auto *FltSem = FT->getSemantics();
317 if (
T->isPointer()) {
323 if (MPT->isFunctionPointer()) {
324 if (Has64BitPointers) {
327 uint64_t EbFuncPtr = OffsetBase / 64;
328 uint64_t EbThisAdj = (OffsetBase + 64 - 1) / 64;
329 if (EbFuncPtr != EbThisAdj) {
342 auto Size = VT->getSizeInBits().getFixedValue();
357 }
else if (
Size == 64) {
368 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
380 if (OffsetBase && OffsetBase != 64)
382 }
else if (
Size == 128 ||
385 uint64_t ElemBits =
IT->getSizeInBits().getFixedValue();
388 ElemBits == 128 && !
IT->isBitInt())
419 else if (
Size <= 128)
422 const auto *FltSem = EFT->getSemantics();
441 uint64_t EbImag = (OffsetBase + ElementSize) / 64;
453 if (AT->isMatrixType())
463 if (!IsRegCall &&
Size > 512)
472 if (OffsetBase % ElemAlign)
479 uint64_t ArraySize = AT->getNumElements();
491 Class FieldLo, FieldHi;
492 classify(ElementType,
Offset, FieldLo, FieldHi, IsNamedArg);
493 Lo = merge(
Lo, FieldLo);
494 Hi = merge(
Hi, FieldHi);
506 if (containsMatrixField(RT)) {
523 if (RT->hasFlexibleArrayMember())
530 if (RT->isCXXRecord()) {
531 for (
const auto &
Base : RT->getBaseClasses()) {
538 Class FieldLo, FieldHi;
540 classify(
Base.FieldType,
Offset, FieldLo, FieldHi, IsNamedArg);
541 Lo = merge(
Lo, FieldLo);
542 Hi = merge(
Hi, FieldHi);
546 (
Size !=
Base.FieldType->getSizeInBits().getFixedValue() ||
560 for (
const auto &
Field : RT->getFields()) {
568 ?
Field.BitFieldWidth == 0
569 :
Field.IsUnnamedBitfield))
574 Size !=
Field.FieldType->getSizeInBits().getFixedValue()) ||
581 bool IsInMemory =
Offset % (
Field.FieldType->getAlignment().value() * 8);
582 if (!BitField && IsInMemory) {
588 Class FieldLo, FieldHi;
596 assert(EbHi == EbLo &&
"Invalid classification, type > 16 bytes.");
604 classify(
Field.FieldType,
Offset, FieldLo, FieldHi, IsNamedArg);
607 Lo = merge(
Lo, FieldLo);
608 Hi = merge(
Hi, FieldHi);
621X86_64TargetInfo::classifyArgumentType(
const Type *Ty,
unsigned FreeIntRegs,
622 unsigned &NeededInt,
unsigned &NeededSSE,
623 bool IsNamedArg,
bool IsRegCall)
const {
628 classify(Ty, 0,
Lo,
Hi, IsNamedArg, IsRegCall);
636 const Type *ResType =
nullptr;
645 "Unknown missing lo part");
657 return getIndirectResult(Ty, FreeIntRegs);
670 ResType = getIntegerTypeAtOffset(Ty, 0, Ty, 0);
674 if (
Hi ==
NoClass && ResType->isInteger()) {
679 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
690 ResType = getSSETypeAtOffset(Ty, 0, Ty, 0);
695 const Type *HighPart =
nullptr;
711 HighPart = getIntegerTypeAtOffset(Ty, 8, Ty, 8);
722 HighPart = getSSETypeAtOffset(Ty, 8, Ty, 8);
732 assert(
Lo ==
Sse &&
"Unexpected SseUp classification");
733 ResType = getByteVectorType(Ty);
741 ResType = createPairType(ResType, HighPart);
746ArgInfo X86_64TargetInfo::classifyReturnType(
const Type *RetTy)
const {
751 classify(RetTy, 0,
Lo,
Hi,
true);
757 const Type *ResType =
nullptr;
765 "Unknown missing lo part");
774 return getIndirectReturnResult(RetTy);
779 ResType = getIntegerTypeAtOffset(RetTy, 0, RetTy, 0);
782 if (
Hi ==
NoClass && ResType->isInteger()) {
788 if (ResType->isInteger() && ResType->getSizeInBits() == 128) {
797 ResType = getSSETypeAtOffset(RetTy, 0, RetTy, 0);
812 const Type *X87Type =
814 FieldInfo Fields[] = {FieldInfo(X87Type, 0), FieldInfo(X87Type, 80)};
821 const Type *HighPart =
nullptr;
834 HighPart = getIntegerTypeAtOffset(RetTy, 8, RetTy, 8);
840 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
851 assert(
Lo ==
Sse &&
"Unexpected SseUp classification.");
852 ResType = getByteVectorType(RetTy);
863 HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8);
874 ResType = createPairType(ResType, HighPart);
884const Type *X86_64TargetInfo::createPairType(
const Type *
Lo,
891 llvm::Align HiAlign =
Hi->getAlignment();
892 unsigned HiStart =
alignTo(LoSize, HiAlign);
894 assert(HiStart != 0 && HiStart <= 8 &&
"Invalid x86-64 argument pair!");
900 const Type *AdjustedLo =
Lo;
915 else if (
Lo->isInteger() ||
Lo->isPointer())
916 AdjustedLo =
TB.getIntegerType(64,
Align(8),
false);
918 assert((
Lo->isInteger() ||
Lo->isPointer()) &&
919 "Invalid/unknown low type in pair");
920 unsigned AdjustedLoSize = AdjustedLo->getSizeInBits().getFixedValue() / 8;
921 HiStart =
alignTo(AdjustedLoSize, HiAlign);
925 FieldInfo Fields[] = {FieldInfo(AdjustedLo, 0), FieldInfo(
Hi, HiStart * 8)};
928 assert((8 * 8) == Fields[1].OffsetInBits &&
929 "High part must be at offset 8 bytes");
932 Fields[1].OffsetInBits +
Hi->getSizeInBits().getFixedValue();
940 unsigned TySize = Ty->getSizeInBits().getFixedValue();
941 if (TySize <= StartBit)
946 const Type *EltTy = AT->getElementType();
949 for (
unsigned I = 0;
I < AT->getNumElements(); ++
I) {
950 unsigned EltOffset =
I * EltSize;
951 if (EltOffset >= EndBit)
954 unsigned EltStart = (EltOffset < StartBit) ? StartBit - EltOffset : 0;
965 if (RT->isCXXRecord()) {
966 for (
unsigned I = 0;
I < RT->getNumBaseClasses(); ++
I) {
968 if (
Base.OffsetInBits >= EndBit)
972 (
Base.OffsetInBits < StartBit) ? StartBit -
Base.OffsetInBits : 0;
974 EndBit -
Base.OffsetInBits))
979 for (
unsigned I = 0;
I < RT->getNumFields(); ++
I) {
981 if (
Field.OffsetInBits >= EndBit)
984 unsigned FieldStart =
985 (
Field.OffsetInBits < StartBit) ? StartBit -
Field.OffsetInBits : 0;
987 EndBit -
Field.OffsetInBits))
997const Type *X86_64TargetInfo::getIntegerTypeAtOffset(
const Type *ABIType,
999 const Type *SourceTy,
1000 unsigned SourceOffset,
1001 bool InMemory)
const {
1003 const Type *WorkingType = ABIType;
1004 if (InMemory && ABIType->isInteger()) {
1006 unsigned OriginalBitWidth =
IT->getSizeInBits().getFixedValue();
1008 unsigned WidenedBitWidth = OriginalBitWidth;
1009 if (OriginalBitWidth <= 8) {
1010 WidenedBitWidth = 8;
1015 if (WidenedBitWidth != OriginalBitWidth) {
1016 WorkingType =
TB.getIntegerType(WidenedBitWidth,
ABIType->getAlignment(),
1022 if (ABIOffset == 0) {
1027 if ((WorkingType->isPointer() && Has64BitPointers) ||
1028 (WorkingType->isInteger() &&
1038 if ((WorkingType->isInteger() &&
1043 (WorkingType->isPointer() && !Has64BitPointers)) {
1045 unsigned BitWidth = WorkingType->isPointer()
1050 SourceOffset * 8 + 64))
1056 if (RTy->isUnion()) {
1059 if (ABIOffset * 8 < ReducedType->getSizeInBits().getFixedValue())
1060 return getIntegerTypeAtOffset(ReducedType, ABIOffset, SourceTy,
1061 SourceOffset,
true);
1066 SourceOffset * 8 + 64))
1067 return TB.getIntegerType(8,
Align(1),
false);
1068 unsigned RemainingBytes =
1071 return TB.getIntegerType(std::min(RemainingBytes, 8U) * 8,
Align(1),
1075 if (
const FieldInfo *Element =
1076 RTy->getElementContainingOffset(ABIOffset * 8)) {
1078 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1079 return getIntegerTypeAtOffset(Element->FieldType,
1080 ABIOffset - ElementOffsetBytes, SourceTy,
1081 SourceOffset,
true);
1086 const Type *EltTy = ATy->getElementType();
1087 unsigned EltSize = EltTy->getSizeInBits() / 8;
1089 unsigned EltOffset = (ABIOffset / EltSize) * EltSize;
1090 return getIntegerTypeAtOffset(EltTy, ABIOffset - EltOffset, SourceTy,
1091 SourceOffset,
true);
1102 unsigned TySizeInBytes =
1107 alignTo(SourceTy->getSizeInBits().getFixedValue(), 64) / 8;
1109 assert(TySizeInBytes != SourceOffset &&
"Empty field?");
1110 unsigned AvailableSize = TySizeInBytes - SourceOffset;
1111 return TB.getIntegerType(std::min(AvailableSize, 8U) * 8,
Align(1),
false);
1115const Type *X86_64TargetInfo::getFPTypeAtOffset(
const Type *Ty,
1118 if (
Offset == 0 && Ty->isFloat())
1123 unsigned ElementSize =
ElementType->getSizeInBits().getFixedValue() / 8;
1132 if (
const FieldInfo *Element = RT->getElementContainingOffset(
Offset * 8)) {
1133 unsigned ElementOffsetBytes = Element->OffsetInBits / 8;
1134 return getFPTypeAtOffset(Element->FieldType,
Offset - ElementOffsetBytes);
1140 const Type *EltTy = AT->getElementType();
1141 unsigned EltSize = EltTy->getSizeInBits() / 8;
1142 unsigned EltIndex =
Offset / EltSize;
1144 return getFPTypeAtOffset(EltTy,
Offset - (EltIndex * EltSize));
1162const Type *X86_64TargetInfo::getSSETypeAtOffset(
const Type *ABIType,
1164 const Type *SourceTy,
1165 unsigned SourceOffset)
const {
1168 if (RTy->isUnion()) {
1171 return getSSETypeAtOffset(ReducedType, ABIOffset, SourceTy,
1177 auto Is16bitFpTy = [](
const Type *
T) {
1183 const Type *T0 = getFPTypeAtOffset(ABIType, ABIOffset);
1188 unsigned SourceSize =
1189 (SourceTy->getSizeInBits().getFixedValue() / 8) - SourceOffset;
1192 const Type *
T1 =
nullptr;
1194 alignTo(T0->getSizeInBits().getFixedValue(), T0->getAlignment().value()) /
1196 if (SourceSize > T0Size)
1197 T1 = getFPTypeAtOffset(ABIType, ABIOffset + T0Size);
1199 if (
T1 ==
nullptr) {
1200 if (Is16bitFpTy(T0) && SourceSize > 4)
1201 T1 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1211 if (Is16bitFpTy(T0) && Is16bitFpTy(
T1)) {
1212 const Type *T2 =
nullptr;
1214 T2 = getFPTypeAtOffset(ABIType, ABIOffset + 4);
1221 if (Is16bitFpTy(T0) || Is16bitFpTy(
T1))
1231const Type *X86_64TargetInfo::getByteVectorType(
const Type *Ty)
const {
1234 if (
const Type *InnerTy = isSingleElementStruct(Ty))
1242 VT->getElementType()->isInteger() &&
1244 unsigned Size = VT->getSizeInBits().getFixedValue();
1245 return TB.getVectorType(
TB.getIntegerType(64,
Align(8),
false),
1257 unsigned Size = Ty->getSizeInBits().getFixedValue();
1265const Type *X86_64TargetInfo::isSingleElementStruct(
const Type *Ty)
const {
1270 if (RT->hasFlexibleArrayMember())
1273 const Type *Found =
nullptr;
1275 for (
const auto &
Base : RT->getBaseClasses()) {
1276 const Type *BaseTy =
Base.FieldType;
1279 if (!BaseRT || BaseRT->isEmpty())
1282 const Type *Elem = isSingleElementStruct(BaseTy);
1288 for (
const auto &FI : RT->getFields()) {
1292 const Type *FTy = FI.FieldType;
1295 if (AT->getNumElements() != 1)
1297 FTy = AT->getElementType();
1302 Elem = isSingleElementStruct(InnerRT);
1312 if (Found->getSizeInBits() != Ty->getSizeInBits())
1318bool X86_64TargetInfo::isIllegalVectorType(
const Type *Ty)
const {
1320 uint64_t Size = VecTy->getSizeInBits().getFixedValue();
1328 const Type *EltTy = VecTy->getElementType();
1331 if (IntTy->getSizeInBits().getFixedValue() == 128)
1338ArgInfo X86_64TargetInfo::getIndirectResult(
const Type *Ty,
1339 unsigned FreeIntRegs)
const {
1362 uint64_t AlignVal = std::max<uint64_t>(Ty->getAlignment().value(), 8u);
1385 if (FreeIntRegs == 0) {
1393 if (AlignVal == 8 &&
Size <= 64) {
1395 TB.getIntegerType(
Size, llvm::Align(8),
false);
1403ArgInfo X86_64TargetInfo::getIndirectReturnResult(
const Type *Ty)
const {
1407 if (IntTy->isBitInt())
1418void X86_64TargetInfo::computeInfo(
FunctionInfo &FI)
const {
1424 switch (CallingConv) {
1429 "calling convention not supported by the LLVMABI X86_64 classifier");
1432 unsigned FreeIntRegs = 6;
1433 unsigned FreeSSERegs = 8;
1434 unsigned NeededInt = 0, NeededSSE = 0;
1437 const Type *RetTy = FI.getReturnType();
1438 FI.getReturnInfo() = classifyReturnType(RetTy);
1441 if (FI.getReturnInfo().isIndirect())
1444 unsigned NumRequiredArgs = FI.getNumRequiredArgs();
1447 for (
auto IT = FI.arg_begin(), IE = FI.arg_end();
IT != IE; ++
IT, ++ArgNo) {
1448 bool IsNamedArg = ArgNo < NumRequiredArgs;
1449 const Type *ArgTy =
IT->ABIType;
1453 ArgInfo AI = classifyArgumentType(ArgTy, FreeIntRegs, NeededInt, NeededSSE,
1460 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
1461 FreeIntRegs -= NeededInt;
1462 FreeSSERegs -= NeededSSE;
1466 IT->Info = getIndirectResult(ArgTy, FreeIntRegs);
1471std::unique_ptr<TargetInfo>
1474 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 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 ArgInfo getNaturalAlignIndirect(const Type *Ty, bool ByVal=true) const
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 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 X86ABICompatInfo &Compat)
bool has64BitPointers() const
const X86ABICompatInfo & getX86ABICompatInfo() const
const ABICompatInfo & getABICompatInfo() const override
Return this target's ABI compatibility flags.
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.
LLVM_ABI std::unique_ptr< TargetInfo > createX86_64TargetInfo(TypeBuilder &TB, X86AVXABILevel AVXLevel, bool Has64BitPointers, const X86ABICompatInfo &Compat)
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)
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 ABI compatibility behaviour that applies to every target.
Flags controlling X86-specific ABI compatibility behaviour.