| //===- X86.cpp ------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/ABI/FunctionInfo.h" |
| #include "llvm/ABI/TargetInfo.h" |
| #include "llvm/ABI/Types.h" |
| #include "llvm/Support/Alignment.h" |
| #include "llvm/Support/Casting.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/MathExtras.h" |
| #include "llvm/Support/TypeSize.h" |
| #include <algorithm> |
| #include <cassert> |
| #include <cstdint> |
| |
| namespace llvm { |
| namespace abi { |
| |
| static unsigned getNativeVectorSizeForAVXABI(X86AVXABILevel AVXLevel) { |
| switch (AVXLevel) { |
| case X86AVXABILevel::AVX512: |
| return 512; |
| case X86AVXABILevel::AVX: |
| return 256; |
| case X86AVXABILevel::None: |
| return 128; |
| } |
| llvm_unreachable("Unknown AVXLevel"); |
| } |
| |
| // The width of an integer's storage container, mirroring Clang's |
| // ASTContext::getTypeSize. For a plain integer this is its bit width; for a |
| // _BitInt(N) it is N rounded up to the type's alignment. The x86-64 _BitInt |
| // max alignment is 64, so this clamp is target-specific and kept file-local. |
| static uint64_t getClangIntegerWidthInBits(const IntegerType *IT) { |
| uint64_t NumBits = IT->getSizeInBits().getFixedValue(); |
| if (!IT->isBitInt()) |
| return NumBits; |
| uint64_t BitAlign = |
| std::max<uint64_t>(8, std::min<uint64_t>(64, llvm::bit_ceil(NumBits))); |
| return llvm::alignTo(NumBits, BitAlign); |
| } |
| |
| static uint64_t getClangVectorWidthInBits(const VectorType *VT) { |
| const Type *EltTy = VT->getElementType(); |
| uint64_t EltWidth = EltTy->getSizeInBits().getFixedValue(); |
| if (const auto *IT = dyn_cast<IntegerType>(EltTy)) |
| EltWidth = getClangIntegerWidthInBits(IT); |
| uint64_t Width = |
| std::max<uint64_t>(8, EltWidth * VT->getNumElements().getKnownMinValue()); |
| if (Width & (Width - 1)) |
| Width = llvm::alignTo(Width, llvm::bit_ceil(Width)); |
| return Width; |
| } |
| |
| // The storage-container width of a type, mirroring Clang's getTypeSize. Used on |
| // the stack path so a _BitInt or illegal vector coerces to the integer covering |
| // its storage, not its raw iN width. |
| static uint64_t getClangTypeWidthInBits(const Type *Ty) { |
| if (const auto *VT = dyn_cast<VectorType>(Ty)) |
| return getClangVectorWidthInBits(VT); |
| if (const auto *IT = dyn_cast<IntegerType>(Ty)) |
| return getClangIntegerWidthInBits(IT); |
| return Ty->getSizeInBits().getFixedValue(); |
| } |
| |
| class X86_64TargetInfo : public TargetInfo { |
| public: |
| enum Class { Integer, Sse, SseUp, X87, X87Up, ComplexX87, NoClass, Memory }; |
| |
| private: |
| TypeBuilder &TB; |
| X86AVXABILevel AVXLevel; |
| bool Has64BitPointers; |
| |
| static Class merge(Class Accum, Class Field); |
| |
| void postMerge(unsigned AggregateSize, Class &Lo, Class &Hi) const; |
| |
| void classify(const Type *T, uint64_t OffsetBase, Class &Lo, Class &Hi, |
| bool IsNamedArg, bool IsRegCall = false) const; |
| |
| const Type *getIntegerTypeAtOffset(const Type *IRType, unsigned IROffset, |
| const Type *SourceTy, |
| unsigned SourceOffset, |
| bool InMemory = false) const; |
| |
| const Type *getSSETypeAtOffset(const Type *ABIType, unsigned ABIOffset, |
| const Type *SourceTy, |
| unsigned SourceOffset) const; |
| bool isIllegalVectorType(const Type *Ty) const; |
| bool containsMatrixField(const RecordType *RT) const; |
| |
| void computeInfo(FunctionInfo &FI) const override; |
| ArgInfo getIndirectReturnResult(const Type *Ty) const; |
| const Type *getFPTypeAtOffset(const Type *Ty, unsigned Offset) const; |
| |
| const Type *isSingleElementStruct(const Type *Ty) const; |
| const Type *getByteVectorType(const Type *Ty) const; |
| |
| const Type *createPairType(const Type *Lo, const Type *Hi) const; |
| ArgInfo getIndirectResult(const Type *Ty, unsigned FreeIntRegs) const; |
| |
| ArgInfo classifyReturnType(const Type *RetTy) const; |
| |
| ArgInfo classifyArgumentType(const Type *Ty, unsigned FreeIntRegs, |
| unsigned &NeededInt, unsigned &NeededSse, |
| bool IsNamedArg, bool IsRegCall = false) const; |
| |
| public: |
| X86_64TargetInfo(TypeBuilder &TypeBuilder, X86AVXABILevel AVXABILevel, |
| bool Has64BitPtrs, const ABICompatInfo &Compat) |
| : TargetInfo(Compat), TB(TypeBuilder), AVXLevel(AVXABILevel), |
| Has64BitPointers(Has64BitPtrs) {} |
| |
| bool has64BitPointers() const { return Has64BitPointers; } |
| }; |
| |
| static bool bitsContainNoUserData(const Type *Ty, unsigned StartBit, |
| unsigned EndBit); |
| |
| // Gets the "best" type to represent the union. |
| static const Type *reduceUnionForX8664(const RecordType *UnionType, |
| TypeBuilder &TB) { |
| assert(UnionType->isUnion() && "Expected union type"); |
| |
| ArrayRef<FieldInfo> Fields = UnionType->getFields(); |
| if (Fields.empty()) { |
| return nullptr; |
| } |
| |
| const Type *StorageType = nullptr; |
| |
| for (const auto &Field : Fields) { |
| if (Field.IsBitField && Field.IsUnnamedBitfield && |
| Field.BitFieldWidth == 0) { |
| continue; |
| } |
| |
| const Type *FieldType = Field.FieldType; |
| |
| if (UnionType->isTransparentUnion() && !StorageType) { |
| StorageType = FieldType; |
| break; |
| } |
| |
| // A member that holds no user data supplies no bytes for a coercion to |
| // read, so it must not become the storage type however wide or aligned it |
| // is declared. Clang compares lowered types instead, where an empty class |
| // is a byte array whose i8 leaf lets getIntegerTypeAtOffset narrow the |
| // coercion. A record mapped here holds no fields, so there is no such |
| // leaf and the eightbyte would be sized from the union. |
| if (bitsContainNoUserData(FieldType, 0, |
| FieldType->getSizeInBits().getFixedValue())) |
| continue; |
| |
| if (!StorageType || |
| FieldType->getAlignment() > StorageType->getAlignment() || |
| (FieldType->getAlignment() == StorageType->getAlignment() && |
| TypeSize::isKnownGT(FieldType->getSizeInBits(), |
| StorageType->getSizeInBits()))) { |
| StorageType = FieldType; |
| } |
| } |
| return StorageType; |
| } |
| |
| void X86_64TargetInfo::postMerge(unsigned AggregateSize, Class &Lo, |
| Class &Hi) const { |
| // AMD64-ABI 3.2.3p2: Rule 5. Then a post merger cleanup is done: |
| // |
| // (a) If one of the classes is Memory, the whole argument is passed in |
| // memory. |
| // |
| // (b) If X87Up is not preceded by X87, the whole argument is passed in |
| // memory. |
| // |
| // (c) If the size of the aggregate exceeds two eightbytes and the first |
| // eightbyte isn't SSE or any other eightbyte isn't SSEUP, the whole |
| // argument is passed in memory. NOTE: This is necessary to keep the |
| // ABI working for processors that don't support the __m256 type. |
| // |
| // (d) If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE. |
| // |
| // Some of these are enforced by the merging logic. Others can arise |
| // only with unions; for example: |
| // union { _Complex double; unsigned; } |
| // |
| // Note that clauses (b) and (c) were added in 0.98. |
| |
| if (Hi == Memory) |
| Lo = Memory; |
| if (Hi == X87Up && Lo != X87 && getABICompatInfo().HonorsRevision98) |
| Lo = Memory; |
| if (AggregateSize > 128 && (Lo != Sse || Hi != SseUp)) |
| Lo = Memory; |
| if (Hi == SseUp && Lo != Sse) |
| Hi = Sse; |
| } |
| X86_64TargetInfo::Class X86_64TargetInfo::merge(Class Accum, Class Field) { |
| // AMD64-ABI 3.2.3p2: Rule 4. Each field of an object is |
| // classified recursively so that always two fields are |
| // considered. The resulting class is calculated according to |
| // the classes of the fields in the eightbyte: |
| // |
| // (a) If both classes are equal, this is the resulting class. |
| // |
| // (b) If one of the classes is NO_CLASS, the resulting class is |
| // the other class. |
| // |
| // (c) If one of the classes is MEMORY, the result is the MEMORY |
| // class. |
| // |
| // (d) If one of the classes is INTEGER, the result is the |
| // INTEGER. |
| // |
| // (e) If one of the classes is X87, X87Up, COMPLEX_X87 class, |
| // MEMORY is used as class. |
| // |
| // (f) Otherwise class SSE is used. |
| |
| // Accum should never be memory (we should have returned) or |
| // ComplexX87 (because this cannot be passed in a structure). |
| assert((Accum != Memory && Accum != ComplexX87) && |
| "Invalid accumulated classification during merge."); |
| |
| if (Accum == Field || Field == NoClass) |
| return Accum; |
| if (Field == Memory) |
| return Memory; |
| if (Accum == NoClass) |
| return Field; |
| if (Accum == Integer || Field == Integer) |
| return Integer; |
| if (Field == X87 || Field == X87Up || Field == ComplexX87 || Accum == X87 || |
| Accum == X87Up) |
| return Memory; |
| |
| return Sse; |
| } |
| |
| // A record with a matrix-extension field is passed in memory. clang has no |
| // matrix-specific ABI code: a matrix falls through X86_64ABIInfo::classify to |
| // the default MEMORY class. We model matrices as arrays, so this check |
| // reproduces that record-with-matrix -> MEMORY result. |
| bool X86_64TargetInfo::containsMatrixField(const RecordType *RT) const { |
| for (const auto &Field : RT->getFields()) { |
| const Type *FieldType = Field.FieldType; |
| |
| if (const auto *AT = dyn_cast<ArrayType>(FieldType)) { |
| if (AT->isMatrixType()) |
| return true; |
| continue; |
| } |
| |
| if (const auto *NestedRT = dyn_cast<RecordType>(FieldType)) |
| if (containsMatrixField(NestedRT)) |
| return true; |
| } |
| return false; |
| } |
| |
| void X86_64TargetInfo::classify(const Type *T, uint64_t OffsetBase, Class &Lo, |
| Class &Hi, bool IsNamedArg, |
| bool IsRegCall) const { |
| Lo = Hi = NoClass; |
| Class &Current = OffsetBase < 64 ? Lo : Hi; |
| Current = Memory; |
| |
| if (T->isVoid()) { |
| Current = NoClass; |
| return; |
| } |
| |
| if (const auto *IT = dyn_cast<IntegerType>(T)) { |
| auto BitWidth = IT->getSizeInBits().getFixedValue(); |
| |
| if (BitWidth == 128 || |
| (IT->isBitInt() && BitWidth > 64 && BitWidth <= 128)) { |
| Lo = Integer; |
| Hi = Integer; |
| } else if (BitWidth <= 64) { |
| Current = Integer; |
| } |
| |
| return; |
| } |
| |
| if (const auto *FT = dyn_cast<FloatType>(T)) { |
| const auto *FltSem = FT->getSemantics(); |
| |
| if (FltSem == &llvm::APFloat::IEEEsingle() || |
| FltSem == &llvm::APFloat::IEEEdouble() || |
| FltSem == &llvm::APFloat::IEEEhalf() || |
| FltSem == &llvm::APFloat::BFloat()) { |
| Current = Sse; |
| } else if (FltSem == &llvm::APFloat::IEEEquad()) { |
| Lo = Sse; |
| Hi = SseUp; |
| } else if (FltSem == &llvm::APFloat::x87DoubleExtended()) { |
| Lo = X87; |
| Hi = X87Up; |
| } else { |
| Current = Sse; |
| } |
| return; |
| } |
| if (T->isPointer()) { |
| Current = Integer; |
| return; |
| } |
| |
| if (const auto *MPT = dyn_cast<MemberPointerType>(T)) { |
| if (MPT->isFunctionPointer()) { |
| if (Has64BitPointers) { |
| Lo = Hi = Integer; |
| } else { |
| uint64_t EbFuncPtr = OffsetBase / 64; |
| uint64_t EbThisAdj = (OffsetBase + 64 - 1) / 64; |
| if (EbFuncPtr != EbThisAdj) { |
| Lo = Hi = Integer; |
| } else { |
| Current = Integer; |
| } |
| } |
| } else { |
| Current = Integer; |
| } |
| return; |
| } |
| |
| if (const auto *VT = dyn_cast<VectorType>(T)) { |
| auto Size = VT->getSizeInBits().getFixedValue(); |
| const Type *ElementType = VT->getElementType(); |
| |
| if (Size == 1 || Size == 8 || Size == 16 || Size == 32) { |
| // gcc passes the following as integer: |
| // 4 bytes - <4 x char>, <2 x short>, <1 x int>, <1 x float> |
| // 2 bytes - <2 x char>, <1 x short> |
| // 1 byte - <1 x char> |
| Current = Integer; |
| // If this type crosses an eightbyte boundary, it should be |
| // split. |
| uint64_t EbLo = (OffsetBase) / 64; |
| uint64_t EbHi = (OffsetBase + Size - 1) / 64; |
| if (EbLo != EbHi) |
| Hi = Lo; |
| } else if (Size == 64) { |
| if (const auto *FT = dyn_cast<FloatType>(ElementType)) { |
| // gcc passes <1 x double> in memory. :( |
| if (FT->getSemantics() == &llvm::APFloat::IEEEdouble()) |
| return; |
| } |
| |
| // gcc passes <1 x long long> as SSE but clang used to unconditionally |
| // pass them as integer. For platforms where clang is the de facto |
| // platform compiler, we must continue to use integer. |
| if (const auto *IT = dyn_cast<IntegerType>(ElementType)) { |
| uint64_t ElemBits = IT->getSizeInBits().getFixedValue(); |
| if (!getABICompatInfo().ClassifyIntegerMMXAsSSE && ElemBits == 64 && |
| !IT->isBitInt()) { |
| Current = Integer; |
| } else { |
| Current = Sse; |
| } |
| } else { |
| Current = Sse; |
| } |
| // If this type crosses an eightbyte boundary, it should be |
| // split. |
| if (OffsetBase && OffsetBase != 64) |
| Hi = Lo; |
| } else if (Size == 128 || |
| (IsNamedArg && Size <= getNativeVectorSizeForAVXABI(AVXLevel))) { |
| if (const auto *IT = dyn_cast<IntegerType>(ElementType)) { |
| uint64_t ElemBits = IT->getSizeInBits().getFixedValue(); |
| // gcc passes 256 and 512 bit <X x __int128> vectors in memory. :( |
| if (getABICompatInfo().PassInt128VectorsInMem && Size != 128 && |
| ElemBits == 128 && !IT->isBitInt()) |
| return; |
| } |
| |
| // Arguments of 256-bits are split into four eightbyte chunks. The |
| // least significant one belongs to class SSE and all the others to class |
| // SSEUP. The original Lo and Hi design considers that types can't be |
| // greater than 128-bits, so a 64-bit split in Hi and Lo makes sense. |
| // This design isn't correct for 256-bits, but since there're no cases |
| // where the upper parts would need to be inspected, avoid adding |
| // complexity and just consider Hi to match the 64-256 part. |
| // |
| // Note that per 3.5.7 of AMD64-ABI, 256-bit args are only passed in |
| // registers if they are "named", i.e. not part of the "..." of a |
| // variadic function. |
| // |
| // Similarly, per 3.2.3. of the AVX512 draft, 512-bits ("named") args are |
| // split into eight eightbyte chunks, one SSE and seven SSEUP. |
| Lo = Sse; |
| Hi = SseUp; |
| } |
| return; |
| } |
| |
| if (const auto *CT = dyn_cast<ComplexType>(T)) { |
| const Type *ElementType = CT->getElementType(); |
| uint64_t Size = T->getSizeInBits().getFixedValue(); |
| |
| if (isa<IntegerType>(ElementType)) { |
| if (Size <= 64) |
| Current = Integer; |
| else if (Size <= 128) |
| Lo = Hi = Integer; |
| } else if (const auto *EFT = dyn_cast<FloatType>(ElementType)) { |
| const auto *FltSem = EFT->getSemantics(); |
| if (FltSem == &llvm::APFloat::IEEEhalf() || |
| FltSem == &llvm::APFloat::IEEEsingle() || |
| FltSem == &llvm::APFloat::BFloat()) |
| Current = Sse; |
| else if (FltSem == &llvm::APFloat::IEEEquad()) |
| Current = Memory; |
| else if (FltSem == &llvm::APFloat::x87DoubleExtended()) |
| Current = ComplexX87; |
| else if (FltSem == &llvm::APFloat::IEEEdouble()) |
| Lo = Hi = Sse; |
| else |
| llvm_unreachable("Unexpected long double representation!"); |
| } |
| |
| uint64_t ElementSize = ElementType->getSizeInBits().getFixedValue(); |
| // If this complex type crosses an eightbyte boundary then it |
| // should be split. |
| uint64_t EbReal = OffsetBase / 64; |
| uint64_t EbImag = (OffsetBase + ElementSize) / 64; |
| if (Hi == NoClass && EbReal != EbImag) |
| Hi = Lo; |
| |
| return; |
| } |
| |
| if (const auto *AT = dyn_cast<ArrayType>(T)) { |
| // A matrix type is modeled as an array but, like Clang, is treated as a |
| // non-aggregate scalar: it matches no class here and stays in the Memory |
| // class, so classify*Type later returns it Direct (coerced to its |
| // flattened vector) rather than classifying it field-by-field. |
| if (AT->isMatrixType()) |
| return; |
| |
| // Arrays are treated like structures. |
| uint64_t Size = AT->getSizeInBits().getFixedValue(); |
| |
| // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger |
| // than eight eightbytes, ..., it has class MEMORY. |
| // regcall ABI doesn't have limitation to an object. The only limitation |
| // is the free registers, which will be checked in computeInfo. |
| if (!IsRegCall && Size > 512) |
| return; |
| |
| // AMD64-ABI 3.2.3p2: Rule 1. If ..., or it contains unaligned |
| // fields, it has class MEMORY. |
| // |
| // Only need to check alignment of array base. |
| const Type *ElementType = AT->getElementType(); |
| uint64_t ElemAlign = ElementType->getAlignment().value() * 8; |
| if (OffsetBase % ElemAlign) |
| return; |
| |
| // Otherwise implement simplified merge. We could be smarter about |
| // this, but it isn't worth it and would be harder to verify. |
| Current = NoClass; |
| uint64_t EltSize = ElementType->getSizeInBits().getFixedValue(); |
| uint64_t ArraySize = AT->getNumElements(); |
| |
| // The only case a 256-bit wide vector could be used is when the array |
| // contains a single 256-bit element. Since Lo and Hi logic isn't extended |
| // to work for sizes wider than 128, early check and fallback to memory. |
| // |
| if (Size > 128 && |
| (Size != EltSize || Size > getNativeVectorSizeForAVXABI(AVXLevel))) |
| return; |
| |
| for (uint64_t I = 0, Offset = OffsetBase; I < ArraySize; |
| ++I, Offset += EltSize) { |
| Class FieldLo, FieldHi; |
| classify(ElementType, Offset, FieldLo, FieldHi, IsNamedArg); |
| Lo = merge(Lo, FieldLo); |
| Hi = merge(Hi, FieldHi); |
| if (Lo == Memory || Hi == Memory) |
| break; |
| } |
| postMerge(Size, Lo, Hi); |
| assert((Hi != SseUp || Lo == Sse) && "Invalid SseUp array classification."); |
| return; |
| } |
| |
| if (const auto *RT = dyn_cast<RecordType>(T)) { |
| uint64_t Size = RT->getSizeInBits().getFixedValue(); |
| |
| if (containsMatrixField(RT)) { |
| Lo = Memory; |
| return; |
| } |
| |
| // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger |
| // than eight eightbytes, ..., it has class MEMORY. |
| if (Size > 512) |
| return; |
| |
| // AMD64-ABI 3.2.3p2: Rule 2. If a C++ object has either a non-trivial |
| // copy constructor or a non-trivial destructor, it is passed by invisible |
| // reference. |
| if (getRecordArgABI(RT)) |
| return; |
| |
| // Assume variable sized types are passed in memory. |
| if (RT->hasFlexibleArrayMember()) |
| return; |
| |
| // Reset Lo class, this will be recomputed. |
| Current = NoClass; |
| |
| // If this is a C++ record, classify the bases first. |
| if (RT->isCXXRecord()) { |
| for (const auto &Base : RT->getBaseClasses()) { |
| |
| // Classify this field. |
| // |
| // AMD64-ABI 3.2.3p2: Rule 3. If the size of the aggregate exceeds a |
| // single eightbyte, each is classified separately. Each eightbyte gets |
| // initialized to class NO_CLASS. |
| Class FieldLo, FieldHi; |
| uint64_t Offset = OffsetBase + Base.OffsetInBits; |
| classify(Base.FieldType, Offset, FieldLo, FieldHi, IsNamedArg); |
| Lo = merge(Lo, FieldLo); |
| Hi = merge(Hi, FieldHi); |
| |
| if (getABICompatInfo().ReturnCXXRecordGreaterThan128InMem && |
| (Size > 128 && |
| (Size != Base.FieldType->getSizeInBits().getFixedValue() || |
| Size > getNativeVectorSizeForAVXABI(AVXLevel)))) |
| Lo = Memory; |
| |
| if (Lo == Memory || Hi == Memory) { |
| postMerge(Size, Lo, Hi); |
| return; |
| } |
| } |
| } |
| |
| // Classify the fields one at a time, merging the results. |
| |
| bool IsUnion = RT->isUnion() && !getABICompatInfo().Clang11Compat; |
| for (const auto &Field : RT->getFields()) { |
| uint64_t Offset = OffsetBase + Field.OffsetInBits; |
| bool BitField = Field.IsBitField; |
| |
| // Ignore padding bit-fields. Normally only zero-length bit-fields are |
| // padding, but under Clang 23 compatibility every unnamed bit-field is, |
| // faithfully reproducing Clang 23. |
| if (BitField && (getABICompatInfo().ClassifyUnnamedBitFields |
| ? Field.BitFieldWidth == 0 |
| : Field.IsUnnamedBitfield)) |
| continue; |
| |
| if (Size > 128 && |
| ((!IsUnion && |
| Size != Field.FieldType->getSizeInBits().getFixedValue()) || |
| Size > getNativeVectorSizeForAVXABI(AVXLevel))) { |
| Lo = Memory; |
| postMerge(Size, Lo, Hi); |
| return; |
| } |
| |
| bool IsInMemory = Offset % (Field.FieldType->getAlignment().value() * 8); |
| if (!BitField && IsInMemory) { |
| Lo = Memory; |
| postMerge(Size, Lo, Hi); |
| return; |
| } |
| |
| Class FieldLo, FieldHi; |
| |
| if (BitField) { |
| uint64_t BitFieldSize = Field.BitFieldWidth; |
| uint64_t EbLo = Offset / 64; |
| uint64_t EbHi = (Offset + BitFieldSize - 1) / 64; |
| |
| if (EbLo) { |
| assert(EbHi == EbLo && "Invalid classification, type > 16 bytes."); |
| FieldLo = NoClass; |
| FieldHi = Integer; |
| } else { |
| FieldLo = Integer; |
| FieldHi = EbHi ? Integer : NoClass; |
| } |
| } else { |
| classify(Field.FieldType, Offset, FieldLo, FieldHi, IsNamedArg); |
| } |
| |
| Lo = merge(Lo, FieldLo); |
| Hi = merge(Hi, FieldHi); |
| if (Lo == Memory || Hi == Memory) |
| break; |
| } |
| postMerge(Size, Lo, Hi); |
| return; |
| } |
| |
| Lo = Memory; |
| Hi = NoClass; |
| } |
| |
| ArgInfo |
| X86_64TargetInfo::classifyArgumentType(const Type *Ty, unsigned FreeIntRegs, |
| unsigned &NeededInt, unsigned &NeededSSE, |
| bool IsNamedArg, bool IsRegCall) const { |
| |
| Ty = useFirstFieldIfTransparentUnion(Ty); |
| |
| X86_64TargetInfo::Class Lo, Hi; |
| classify(Ty, 0, Lo, Hi, IsNamedArg, IsRegCall); |
| |
| // Check some invariants |
| assert((Hi != Memory || Lo == Memory) && "Invalid memory classification."); |
| assert((Hi != SseUp || Lo == Sse) && "Invalid SseUp classification."); |
| |
| NeededInt = 0; |
| NeededSSE = 0; |
| const Type *ResType = nullptr; |
| |
| switch (Lo) { |
| case NoClass: |
| if (Hi == NoClass) |
| return ArgInfo::getIgnore(); |
| // If the low part is just padding, it takes no register, leave ResType |
| // null. |
| assert((Hi == Sse || Hi == Integer || Hi == X87Up) && |
| "Unknown missing lo part"); |
| break; |
| |
| // AMD64-ABI 3.2.3p3: Rule 1. If the class is MEMORY, pass the argument |
| // on the stack. |
| case Memory: |
| // AMD64-ABI 3.2.3p3: Rule 5. If the class is X87, X87Up or |
| // COMPLEX_X87, it is passed in memory. |
| case X87: |
| case ComplexX87: |
| if (getRecordArgABI(Ty) == RAA_Indirect) |
| ++NeededInt; |
| return getIndirectResult(Ty, FreeIntRegs); |
| |
| case SseUp: |
| case X87Up: |
| llvm_unreachable("Invalid classification for lo word."); |
| |
| // AMD64-ABI 3.2.3p3: Rule 2. If the class is INTEGER, the next |
| // available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8 |
| // and %r9 is used. |
| case Integer: |
| ++NeededInt; |
| |
| // Pick an 8-byte type based on the preferred type. |
| ResType = getIntegerTypeAtOffset(Ty, 0, Ty, 0); |
| |
| // If we have a sign or zero extended integer, make sure to return Extend |
| // so that the parameter gets the right LLVM IR attributes. |
| if (Hi == NoClass && ResType->isInteger()) { |
| if (Ty->isInteger() && isPromotableInteger(cast<IntegerType>(Ty))) |
| return ArgInfo::getExtend(Ty); |
| } |
| |
| if (ResType->isInteger() && ResType->getSizeInBits() == 128) { |
| assert(Hi == Integer); |
| ++NeededInt; |
| return ArgInfo::getDirect(ResType); |
| } |
| break; |
| |
| // AMD64-ABI 3.2.3p3: Rule 3. If the class is SSE, the next |
| // available SSE register is used, the registers are taken in the |
| // order from %xmm0 to %xmm7. |
| case Sse: |
| ResType = getSSETypeAtOffset(Ty, 0, Ty, 0); |
| ++NeededSSE; |
| break; |
| } |
| |
| const Type *HighPart = nullptr; |
| switch (Hi) { |
| // Memory was handled previously, ComplexX87 and X87 should |
| // never occur as hi classes, and X87Up must be preceded by X87, |
| // which is passed in memory. |
| case Memory: |
| case X87: |
| case ComplexX87: |
| llvm_unreachable("Invalid classification for hi word."); |
| |
| case NoClass: |
| break; |
| |
| case Integer: |
| ++NeededInt; |
| // Pick an 8-byte type based on the preferred type. |
| HighPart = getIntegerTypeAtOffset(Ty, 8, Ty, 8); |
| |
| if (Lo == NoClass) // Pass HighPart at offset 8 in memory. |
| return ArgInfo::getDirect(HighPart, 8); |
| break; |
| |
| // X87Up generally doesn't occur here (long double is passed in |
| // memory), except in situations involving unions. |
| case X87Up: |
| case Sse: |
| ++NeededSSE; |
| HighPart = getSSETypeAtOffset(Ty, 8, Ty, 8); |
| |
| if (Lo == NoClass) // Pass HighPart at offset 8 in memory. |
| return ArgInfo::getDirect(HighPart, 8); |
| break; |
| |
| // AMD64-ABI 3.2.3p3: Rule 4. If the class is SSEUP, the |
| // eightbyte is passed in the upper half of the last used SSE |
| // register. This only happens when 128-bit vectors are passed. |
| case SseUp: |
| assert(Lo == Sse && "Unexpected SseUp classification"); |
| ResType = getByteVectorType(Ty); |
| break; |
| } |
| |
| // If a high part was specified, merge it together with the low part. It is |
| // known to pass in the high eightbyte of the result. We do this by forming a |
| // first class struct aggregate with the high and low part: {low, high} |
| if (HighPart) |
| ResType = createPairType(ResType, HighPart); |
| |
| return ArgInfo::getDirect(ResType); |
| } |
| |
| ArgInfo X86_64TargetInfo::classifyReturnType(const Type *RetTy) const { |
| // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the |
| // classification algorithm. |
| |
| X86_64TargetInfo::Class Lo, Hi; |
| classify(RetTy, 0, Lo, Hi, /*isNamedArg*/ true); |
| |
| // Check some invariants |
| assert((Hi != Memory || Lo == Memory) && "Invalid memory classification."); |
| assert((Hi != SseUp || Lo == Sse) && "Invalid SseUp classification."); |
| |
| const Type *ResType = nullptr; |
| switch (Lo) { |
| case NoClass: |
| if (Hi == NoClass) |
| return ArgInfo::getIgnore(); |
| // If the low part is just padding, it takes no register, leave ResType |
| // null. |
| assert((Hi == Sse || Hi == Integer || Hi == X87Up) && |
| "Unknown missing lo part"); |
| break; |
| case SseUp: |
| case X87Up: |
| llvm_unreachable("Invalid classification for lo word."); |
| |
| // AMD64-ABI 3.2.3p4: Rule 2. Types of class memory are returned via |
| // hidden argument. |
| case Memory: |
| return getIndirectReturnResult(RetTy); |
| |
| // AMD64-ABI 3.2.3p4: Rule 3. If the class is INTEGER, the next |
| // available register of the sequence %rax, %rdx is used. |
| case Integer: |
| ResType = getIntegerTypeAtOffset(RetTy, 0, RetTy, 0); |
| // If we have a sign or zero extended integer, make sure to return Extend |
| // so that the parameter gets the right LLVM IR attributes. |
| if (Hi == NoClass && ResType->isInteger()) { |
| if (const IntegerType *IntTy = dyn_cast<IntegerType>(RetTy)) { |
| if (isPromotableInteger(IntTy)) |
| return ArgInfo::getExtend(RetTy); |
| } |
| } |
| if (ResType->isInteger() && ResType->getSizeInBits() == 128) { |
| assert(Hi == Integer); |
| return ArgInfo::getDirect(ResType); |
| } |
| break; |
| |
| // AMD64-ABI 3.2.3p4: Rule 4. If the class is SSE, the next |
| // available SSE register of the sequence %xmm0, %xmm1 is used. |
| case Sse: |
| ResType = getSSETypeAtOffset(RetTy, 0, RetTy, 0); |
| break; |
| |
| // AMD64-ABI 3.2.3p4: Rule 6. If the class is X87, the value is |
| // returned on the X87 stack in %st0 as 80-bit x87 number. |
| case X87: |
| ResType = TB.getFloatType(APFloat::x87DoubleExtended(), Align(16)); |
| break; |
| |
| // AMD64-ABI 3.2.3p4: Rule 8. If the class is COMPLEX_X87, the real |
| // part of the value is returned in %st0 and the imaginary part in |
| // %st1. |
| case ComplexX87: |
| assert(Hi == ComplexX87 && "Unexpected ComplexX87 classification."); |
| { |
| const Type *X87Type = |
| TB.getFloatType(APFloat::x87DoubleExtended(), Align(16)); |
| FieldInfo Fields[] = {FieldInfo(X87Type, 0), FieldInfo(X87Type, 80)}; |
| ResType = TB.getRecordType(Fields, TypeSize::getFixed(160), Align(16)); |
| } |
| break; |
| } |
| |
| const Type *HighPart = nullptr; |
| switch (Hi) { |
| // Memory was handled previously and X87 should |
| // never occur as a hi class. |
| case Memory: |
| case X87: |
| llvm_unreachable("Invalid classification for hi word."); |
| |
| case ComplexX87: |
| case NoClass: |
| break; |
| |
| case Integer: |
| HighPart = getIntegerTypeAtOffset(RetTy, 8, RetTy, 8); |
| if (Lo == NoClass) |
| return ArgInfo::getDirect(HighPart, 8); |
| break; |
| |
| case Sse: |
| HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8); |
| if (Lo == NoClass) |
| return ArgInfo::getDirect(HighPart, 8); |
| break; |
| |
| // AMD64-ABI 3.2.3p4: Rule 5. If the class is SSEUP, the eightbyte |
| // is passed in the next available eightbyte chunk if the last used |
| // vector register. |
| // |
| // SSEUP should always be preceded by SSE, just widen. |
| case SseUp: |
| assert(Lo == Sse && "Unexpected SseUp classification."); |
| ResType = getByteVectorType(RetTy); |
| break; |
| |
| // AMD64-ABI 3.2.3p4: Rule 7. If the class is X87Up, the value is |
| // returned together with the previous X87 value in %st0. |
| case X87Up: |
| // If X87Up is preceded by X87, we don't need to do |
| // anything. However, in some cases with unions it may not be |
| // preceded by X87. In such situations we follow gcc and pass the |
| // extra bits in an SSE reg. |
| if (Lo != X87) { |
| HighPart = getSSETypeAtOffset(RetTy, 8, RetTy, 8); |
| if (Lo == NoClass) // Return HighPart at offset 8 in memory. |
| return ArgInfo::getDirect(HighPart, 8); |
| } |
| break; |
| } |
| |
| // If a high part was specified, merge it together with the low part. It is |
| // known to pass in the high eightbyte of the result. We do this by forming a |
| // first class struct aggregate with the high and low part: {low, high} |
| if (HighPart) |
| ResType = createPairType(ResType, HighPart); |
| |
| return ArgInfo::getDirect(ResType); |
| } |
| |
| /// Given a high and low type that can ideally |
| /// be used as elements of a two register pair to pass or return, return a |
| /// first class aggregate to represent them. For example, if the low part of |
| /// a by-value argument should be passed as i32* and the high part as float, |
| /// return {i32*, float}. |
| const Type *X86_64TargetInfo::createPairType(const Type *Lo, |
| const Type *Hi) const { |
| // In order to correctly satisfy the ABI, we need to the high part to start |
| // at offset 8. If the high and low parts we inferred are both 4-byte types |
| // (e.g. i32 and i32) then the resultant struct type ({i32,i32}) won't have |
| // the second element at offset 8. Check for this: |
| unsigned LoSize = (unsigned)Lo->getTypeAllocSize(); |
| llvm::Align HiAlign = Hi->getAlignment(); |
| unsigned HiStart = alignTo(LoSize, HiAlign); |
| |
| assert(HiStart != 0 && HiStart <= 8 && "Invalid x86-64 argument pair!"); |
| |
| // To handle this, we have to increase the size of the low part so that the |
| // second element will start at an 8 byte offset. We can't increase the size |
| // of the second element because it might make us access off the end of the |
| // struct. |
| const Type *AdjustedLo = Lo; |
| if (HiStart != 8) { |
| // There are usually two sorts of types the ABI generation code can produce |
| // for the low part of a pair that aren't 8 bytes in size: half, float or |
| // i8/i16/i32. This can also include pointers when they are 32-bit (X32 and |
| // NaCl). |
| // Promote these to a larger type. |
| if (Lo->isFloat()) { |
| const FloatType *FT = cast<FloatType>(Lo); |
| if (FT->getSemantics() == &APFloat::IEEEhalf() || |
| FT->getSemantics() == &APFloat::IEEEsingle() || |
| FT->getSemantics() == &APFloat::BFloat()) |
| AdjustedLo = TB.getFloatType(APFloat::IEEEdouble(), Align(8)); |
| } |
| // Promote integers and pointers to i64 |
| else if (Lo->isInteger() || Lo->isPointer()) |
| AdjustedLo = TB.getIntegerType(64, Align(8), /*Signed=*/false); |
| else |
| assert((Lo->isInteger() || Lo->isPointer()) && |
| "Invalid/unknown low type in pair"); |
| unsigned AdjustedLoSize = AdjustedLo->getSizeInBits().getFixedValue() / 8; |
| HiStart = alignTo(AdjustedLoSize, HiAlign); |
| } |
| |
| // Create the pair struct |
| FieldInfo Fields[] = {FieldInfo(AdjustedLo, 0), FieldInfo(Hi, HiStart * 8)}; |
| |
| // Verify the high part is at offset 8 |
| assert((8 * 8) == Fields[1].OffsetInBits && |
| "High part must be at offset 8 bytes"); |
| |
| uint64_t PairSizeInBits = |
| Fields[1].OffsetInBits + Hi->getSizeInBits().getFixedValue(); |
| return TB.getRecordType(Fields, TypeSize::getFixed(PairSizeInBits), Align(8), |
| StructPacking::Default); |
| } |
| |
| static bool bitsContainNoUserData(const Type *Ty, unsigned StartBit, |
| unsigned EndBit) { |
| // If range is completely beyond type size, it's definitely padding |
| unsigned TySize = Ty->getSizeInBits().getFixedValue(); |
| if (TySize <= StartBit) |
| return true; |
| |
| // Handle arrays - check each element |
| if (const ArrayType *AT = dyn_cast<ArrayType>(Ty)) { |
| const Type *EltTy = AT->getElementType(); |
| unsigned EltSize = EltTy->getSizeInBits().getFixedValue(); |
| |
| for (unsigned I = 0; I < AT->getNumElements(); ++I) { |
| unsigned EltOffset = I * EltSize; |
| if (EltOffset >= EndBit) |
| break; |
| |
| unsigned EltStart = (EltOffset < StartBit) ? StartBit - EltOffset : 0; |
| if (!bitsContainNoUserData(EltTy, EltStart, EndBit - EltOffset)) |
| return false; |
| } |
| return true; |
| } |
| |
| // Handle records - check all fields and base classes. getUnionType places a |
| // union's members at offset zero, so the field loop covers a union too. |
| if (const RecordType *RT = dyn_cast<RecordType>(Ty)) { |
| // Check base classes first (for C++ records) |
| if (RT->isCXXRecord()) { |
| for (unsigned I = 0; I < RT->getNumBaseClasses(); ++I) { |
| const FieldInfo &Base = RT->getBaseClasses()[I]; |
| if (Base.OffsetInBits >= EndBit) |
| continue; |
| |
| unsigned BaseStart = |
| (Base.OffsetInBits < StartBit) ? StartBit - Base.OffsetInBits : 0; |
| if (!bitsContainNoUserData(Base.FieldType, BaseStart, |
| EndBit - Base.OffsetInBits)) |
| return false; |
| } |
| } |
| |
| for (unsigned I = 0; I < RT->getNumFields(); ++I) { |
| const FieldInfo &Field = RT->getFields()[I]; |
| if (Field.OffsetInBits >= EndBit) |
| break; |
| |
| unsigned FieldStart = |
| (Field.OffsetInBits < StartBit) ? StartBit - Field.OffsetInBits : 0; |
| if (!bitsContainNoUserData(Field.FieldType, FieldStart, |
| EndBit - Field.OffsetInBits)) |
| return false; |
| } |
| return true; |
| } |
| |
| // For any other type - assume all bits are user data |
| return false; |
| } |
| |
| const Type *X86_64TargetInfo::getIntegerTypeAtOffset(const Type *ABIType, |
| unsigned ABIOffset, |
| const Type *SourceTy, |
| unsigned SourceOffset, |
| bool InMemory) const { |
| |
| const Type *WorkingType = ABIType; |
| if (InMemory && ABIType->isInteger()) { |
| const auto *IT = cast<IntegerType>(ABIType); |
| unsigned OriginalBitWidth = IT->getSizeInBits().getFixedValue(); |
| |
| unsigned WidenedBitWidth = OriginalBitWidth; |
| if (OriginalBitWidth <= 8) { |
| WidenedBitWidth = 8; |
| } else { |
| WidenedBitWidth = llvm::bit_ceil(OriginalBitWidth); |
| } |
| |
| if (WidenedBitWidth != OriginalBitWidth) { |
| WorkingType = TB.getIntegerType(WidenedBitWidth, ABIType->getAlignment(), |
| IT->isSigned()); |
| } |
| } |
| // If we're dealing with an un-offset ABI type, then it means that we're |
| // returning an 8-byte unit starting with it. See if we can safely use it. |
| if (ABIOffset == 0) { |
| // Pointers and int64's always fill the 8-byte unit. Return WorkingType, |
| // which is the in-memory-widened type (e.g. a _BitInt(37) field widened to |
| // i64): returning the raw ABIType here would coerce the eightbyte to the |
| // narrow iN instead of the storage integer clang uses. |
| if ((WorkingType->isPointer() && Has64BitPointers) || |
| (WorkingType->isInteger() && |
| cast<IntegerType>(WorkingType)->getSizeInBits() == 64)) |
| return WorkingType; |
| |
| // If we have a 1/2/4-byte integer, we can use it only if the rest of the |
| // goodness in the source type is just tail padding. This is allowed to |
| // kick in for struct {double,int} on the int, but not on |
| // struct{double,int,int} because we wouldn't return the second int. We |
| // have to do this analysis on the source type because we can't depend on |
| // unions being lowered a specific way etc. |
| if ((WorkingType->isInteger() && |
| (cast<IntegerType>(WorkingType)->getSizeInBits() == 1 || |
| cast<IntegerType>(WorkingType)->getSizeInBits() == 8 || |
| cast<IntegerType>(WorkingType)->getSizeInBits() == 16 || |
| cast<IntegerType>(WorkingType)->getSizeInBits() == 32)) || |
| (WorkingType->isPointer() && !Has64BitPointers)) { |
| |
| unsigned BitWidth = WorkingType->isPointer() |
| ? 32 |
| : cast<IntegerType>(WorkingType)->getSizeInBits(); |
| |
| if (bitsContainNoUserData(SourceTy, SourceOffset * 8 + BitWidth, |
| SourceOffset * 8 + 64)) |
| return WorkingType; |
| } |
| } |
| |
| if (const auto *RTy = dyn_cast<RecordType>(ABIType)) { |
| if (RTy->isUnion()) { |
| const Type *ReducedType = reduceUnionForX8664(RTy, TB); |
| if (ReducedType) |
| return getIntegerTypeAtOffset(ReducedType, ABIOffset, SourceTy, |
| SourceOffset, true); |
| } |
| if (const FieldInfo *Element = |
| RTy->getElementContainingOffset(ABIOffset * 8)) { |
| |
| unsigned ElementOffsetBytes = Element->OffsetInBits / 8; |
| return getIntegerTypeAtOffset(Element->FieldType, |
| ABIOffset - ElementOffsetBytes, SourceTy, |
| SourceOffset, true); |
| } |
| } |
| |
| if (const auto *ATy = dyn_cast<ArrayType>(ABIType)) { |
| const Type *EltTy = ATy->getElementType(); |
| unsigned EltSize = EltTy->getSizeInBits() / 8; |
| if (EltSize > 0) { |
| unsigned EltOffset = (ABIOffset / EltSize) * EltSize; |
| return getIntegerTypeAtOffset(EltTy, ABIOffset - EltOffset, SourceTy, |
| SourceOffset, true); |
| } |
| } |
| |
| // If we have a 128-bit integer, we can pass it safely using an i128 |
| // so we return that |
| if (ABIType->isInteger() && ABIType->getSizeInBits() == 128) { |
| assert(ABIOffset == 0); |
| return ABIType; |
| } |
| |
| unsigned TySizeInBytes = |
| llvm::divideCeil(SourceTy->getSizeInBits().getFixedValue(), 8); |
| if (auto *IT = dyn_cast<IntegerType>(SourceTy)) { |
| if (IT->isBitInt()) |
| TySizeInBytes = |
| alignTo(SourceTy->getSizeInBits().getFixedValue(), 64) / 8; |
| } |
| assert(TySizeInBytes != SourceOffset && "Empty field?"); |
| unsigned AvailableSize = TySizeInBytes - SourceOffset; |
| return TB.getIntegerType(std::min(AvailableSize, 8U) * 8, Align(1), false); |
| } |
| /// Returns the floating point type at the specified offset within a type, or |
| /// nullptr if no floating point type is found at that offset. |
| const Type *X86_64TargetInfo::getFPTypeAtOffset(const Type *Ty, |
| unsigned Offset) const { |
| // Check for direct match at offset 0 |
| if (Offset == 0 && Ty->isFloat()) |
| return Ty; |
| |
| if (const ComplexType *CT = dyn_cast<ComplexType>(Ty)) { |
| const Type *ElementType = CT->getElementType(); |
| unsigned ElementSize = ElementType->getSizeInBits().getFixedValue() / 8; |
| |
| if (Offset == 0 || Offset == ElementSize) |
| return ElementType; |
| return nullptr; |
| } |
| |
| // Handle struct types by checking each field |
| if (const RecordType *RT = dyn_cast<RecordType>(Ty)) { |
| if (const FieldInfo *Element = RT->getElementContainingOffset(Offset * 8)) { |
| unsigned ElementOffsetBytes = Element->OffsetInBits / 8; |
| return getFPTypeAtOffset(Element->FieldType, Offset - ElementOffsetBytes); |
| } |
| } |
| |
| // Handle array types |
| if (const ArrayType *AT = dyn_cast<ArrayType>(Ty)) { |
| const Type *EltTy = AT->getElementType(); |
| unsigned EltSize = EltTy->getSizeInBits() / 8; |
| unsigned EltIndex = Offset / EltSize; |
| |
| return getFPTypeAtOffset(EltTy, Offset - (EltIndex * EltSize)); |
| } |
| |
| // No floating point type found at this offset |
| return nullptr; |
| } |
| |
| /// Helper to check if a floating point type matches specific semantics |
| static bool isFloatTypeWithSemantics(const Type *Ty, |
| const fltSemantics &Semantics) { |
| if (!Ty->isFloat()) |
| return false; |
| const FloatType *FT = cast<FloatType>(Ty); |
| return FT->getSemantics() == &Semantics; |
| } |
| |
| /// GetSSETypeAtOffset - Return a type that will be passed by the backend in the |
| /// low 8 bytes of an XMM register, corresponding to the SSE class. |
| const Type *X86_64TargetInfo::getSSETypeAtOffset(const Type *ABIType, |
| unsigned ABIOffset, |
| const Type *SourceTy, |
| unsigned SourceOffset) const { |
| |
| if (const auto *RTy = dyn_cast<RecordType>(ABIType)) { |
| if (RTy->isUnion()) { |
| const Type *ReducedType = reduceUnionForX8664(RTy, TB); |
| if (ReducedType) { |
| return getSSETypeAtOffset(ReducedType, ABIOffset, SourceTy, |
| SourceOffset); |
| } |
| } |
| } |
| |
| auto Is16bitFpTy = [](const Type *T) { |
| return isFloatTypeWithSemantics(T, APFloat::IEEEhalf()) || |
| isFloatTypeWithSemantics(T, APFloat::BFloat()); |
| }; |
| |
| // Get the floating point type at the requested offset |
| const Type *T0 = getFPTypeAtOffset(ABIType, ABIOffset); |
| if (!T0 || isFloatTypeWithSemantics(T0, APFloat::IEEEdouble())) |
| return TB.getFloatType(APFloat::IEEEdouble(), Align(8)); |
| |
| // Calculate remaining source size in bytes |
| unsigned SourceSize = |
| (SourceTy->getSizeInBits().getFixedValue() / 8) - SourceOffset; |
| |
| // Try to get adjacent FP type |
| const Type *T1 = nullptr; |
| unsigned T0Size = |
| alignTo(T0->getSizeInBits().getFixedValue(), T0->getAlignment().value()) / |
| 8; |
| if (SourceSize > T0Size) |
| T1 = getFPTypeAtOffset(ABIType, ABIOffset + T0Size); |
| |
| if (T1 == nullptr) { |
| if (Is16bitFpTy(T0) && SourceSize > 4) |
| T1 = getFPTypeAtOffset(ABIType, ABIOffset + 4); |
| |
| if (T1 == nullptr) |
| return T0; |
| } |
| // Handle vector cases |
| if (isFloatTypeWithSemantics(T0, APFloat::IEEEsingle()) && |
| isFloatTypeWithSemantics(T1, APFloat::IEEEsingle())) |
| return TB.getVectorType(T0, ElementCount::getFixed(2), Align(8)); |
| |
| if (Is16bitFpTy(T0) && Is16bitFpTy(T1)) { |
| const Type *T2 = nullptr; |
| if (SourceSize > 4) |
| T2 = getFPTypeAtOffset(ABIType, ABIOffset + 4); |
| if (!T2) |
| return TB.getVectorType(T0, ElementCount::getFixed(2), Align(8)); |
| return TB.getVectorType(T0, ElementCount::getFixed(4), Align(8)); |
| } |
| |
| // Mixed half-float cases |
| if (Is16bitFpTy(T0) || Is16bitFpTy(T1)) |
| return TB.getVectorType(TB.getFloatType(APFloat::IEEEhalf(), Align(2)), |
| ElementCount::getFixed(4), Align(8)); |
| |
| // Default to double |
| return TB.getFloatType(APFloat::IEEEdouble(), Align(8)); |
| } |
| |
| /// The ABI specifies that a value should be passed in a full vector XMM/YMM |
| /// register. Pick an LLVM IR type that will be passed as a vector register. |
| const Type *X86_64TargetInfo::getByteVectorType(const Type *Ty) const { |
| // Wrapper structs/arrays that only contain vectors are passed just like |
| // vectors; strip them off if present. |
| if (const Type *InnerTy = isSingleElementStruct(Ty)) |
| Ty = InnerTy; |
| |
| // Handle vector types |
| if (const VectorType *VT = dyn_cast<VectorType>(Ty)) { |
| // Don't pass vXi128 vectors in their native type, the backend can't |
| // legalize them. |
| if (getABICompatInfo().PassInt128VectorsInMem && |
| VT->getElementType()->isInteger() && |
| cast<IntegerType>(VT->getElementType())->getSizeInBits() == 128) { |
| unsigned Size = VT->getSizeInBits().getFixedValue(); |
| return TB.getVectorType(TB.getIntegerType(64, Align(8), /*Signed=*/false), |
| ElementCount::getFixed(Size / 64), |
| Align(Size / 8)); |
| } |
| return VT; |
| } |
| |
| // Handle fp128 |
| if (isFloatTypeWithSemantics(Ty, APFloat::IEEEquad())) |
| return Ty; |
| |
| // We couldn't find the preferred IR vector type for 'Ty'. |
| unsigned Size = Ty->getSizeInBits().getFixedValue(); |
| assert((Size == 128 || Size == 256 || Size == 512) && "Invalid vector size"); |
| |
| return TB.getVectorType(TB.getFloatType(APFloat::IEEEdouble(), Align(8)), |
| ElementCount::getFixed(Size / 64), Align(Size / 8)); |
| } |
| |
| // Returns the single element if this is a single-element struct wrapper |
| const Type *X86_64TargetInfo::isSingleElementStruct(const Type *Ty) const { |
| const auto *RT = dyn_cast<RecordType>(Ty); |
| if (!RT) |
| return nullptr; |
| |
| if (RT->hasFlexibleArrayMember()) |
| return nullptr; |
| |
| const Type *Found = nullptr; |
| |
| for (const auto &Base : RT->getBaseClasses()) { |
| const Type *BaseTy = Base.FieldType; |
| auto *BaseRT = dyn_cast<RecordType>(BaseTy); |
| |
| if (!BaseRT || BaseRT->isEmpty()) |
| continue; |
| |
| const Type *Elem = isSingleElementStruct(BaseTy); |
| if (!Elem || Found) |
| return nullptr; |
| Found = Elem; |
| } |
| |
| for (const auto &FI : RT->getFields()) { |
| if (FI.isEmpty()) |
| continue; |
| |
| const Type *FTy = FI.FieldType; |
| |
| while (auto *AT = dyn_cast<ArrayType>(FTy)) { |
| if (AT->getNumElements() != 1) |
| break; |
| FTy = AT->getElementType(); |
| } |
| |
| const Type *Elem; |
| if (auto *InnerRT = dyn_cast<RecordType>(FTy)) |
| Elem = isSingleElementStruct(InnerRT); |
| else |
| Elem = FTy; |
| if (!Elem || Found) |
| return nullptr; |
| Found = Elem; |
| } |
| |
| if (!Found) |
| return nullptr; |
| if (Found->getSizeInBits() != Ty->getSizeInBits()) |
| return nullptr; |
| |
| return Found; |
| } |
| |
| bool X86_64TargetInfo::isIllegalVectorType(const Type *Ty) const { |
| if (const auto *VecTy = dyn_cast<VectorType>(Ty)) { |
| uint64_t Size = VecTy->getSizeInBits().getFixedValue(); |
| unsigned LargestVector = getNativeVectorSizeForAVXABI(AVXLevel); |
| |
| // Vectors <= 64 bits or > largest supported vector size are illegal |
| if (Size <= 64 || Size > LargestVector) |
| return true; |
| |
| // Check for 128-bit integer element vectors that should be passed in memory |
| const Type *EltTy = VecTy->getElementType(); |
| if (getABICompatInfo().PassInt128VectorsInMem && EltTy->isInteger()) { |
| const auto *IntTy = cast<IntegerType>(EltTy); |
| if (IntTy->getSizeInBits().getFixedValue() == 128) |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| ArgInfo X86_64TargetInfo::getIndirectResult(const Type *Ty, |
| unsigned FreeIntRegs) const { |
| // If this is a scalar LLVM value then assume LLVM will pass it in the right |
| // place naturally. |
| // |
| // This assumption is optimistic, as there could be free registers available |
| // when we need to pass this argument in memory, and LLVM could try to pass |
| // the argument in the free register. This does not seem to happen currently, |
| // but this code would be much safer if we could mark the argument with |
| // 'onstack'. See PR12193. |
| if (!isAggregateTypeForABI(Ty) && !isIllegalVectorType(Ty) && |
| !(Ty->isInteger() && cast<IntegerType>(Ty)->isBitInt())) { |
| return (Ty->isInteger() && isPromotableInteger(cast<IntegerType>(Ty)) |
| ? ArgInfo::getExtend(Ty) |
| : ArgInfo::getDirect()); |
| } |
| |
| // Check if this is a record type that needs special handling |
| if (auto RecordRAA = getRecordArgABI(Ty)) |
| return getNaturalAlignIndirect(Ty, RecordRAA == |
| RecordArgABI::RAA_DirectInMemory); |
| |
| // Compute the byval alignment. We specify the alignment of the byval in all |
| // cases so that the mid-level optimizer knows the alignment of the byval. |
| uint64_t AlignVal = std::max<uint64_t>(Ty->getAlignment().value(), 8u); |
| |
| // Attempt to avoid passing indirect results using byval when possible. This |
| // is important for good codegen. |
| // |
| // We do this by coercing the value into a scalar type which the backend can |
| // handle naturally (i.e., without using byval). |
| // |
| // For simplicity, we currently only do this when we have exhausted all of the |
| // free integer registers. Doing this when there are free integer registers |
| // would require more care, as we would have to ensure that the coerced value |
| // did not claim the unused register. That would require either reording the |
| // arguments to the function (so that any subsequent inreg values came first), |
| // or only doing this optimization when there were no following arguments that |
| // might be inreg. |
| // |
| // We currently expect it to be rare (particularly in well written code) for |
| // arguments to be passed on the stack when there are still free integer |
| // registers available (this would typically imply large structs being passed |
| // by value), so this seems like a fair tradeoff for now. |
| // |
| // We can revisit this if the backend grows support for 'onstack' parameter |
| // attributes. See PR12193. |
| if (FreeIntRegs == 0) { |
| // Use the storage-container width (like Clang's getTypeSize) so a stack |
| // _BitInt or illegal vector coerces to the integer covering its storage, |
| // not its raw iN width. |
| uint64_t Size = getClangTypeWidthInBits(Ty); |
| |
| // If this type fits in an eightbyte, coerce it into the matching integral |
| // type, which will end up on the stack (with alignment 8). |
| if (AlignVal == 8 && Size <= 64) { |
| const Type *IntTy = |
| TB.getIntegerType(Size, llvm::Align(8), /*Signed=*/false); |
| return ArgInfo::getDirect(IntTy); |
| } |
| } |
| |
| return ArgInfo::getIndirect(llvm::Align(AlignVal), /*ByVal=*/true); |
| } |
| |
| ArgInfo X86_64TargetInfo::getIndirectReturnResult(const Type *Ty) const { |
| if (!isAggregateTypeForABI(Ty)) { |
| // Bit-precise integers are returned indirectly regardless of size. |
| if (const auto *IntTy = dyn_cast<IntegerType>(Ty)) { |
| if (IntTy->isBitInt()) |
| return getNaturalAlignIndirect(IntTy, /*ByVal=*/true); |
| if (isPromotableInteger(IntTy)) |
| return ArgInfo::getExtend(Ty); |
| } |
| return ArgInfo::getDirect(); |
| } |
| |
| return getNaturalAlignIndirect(Ty, /*ByVal=*/true); |
| } |
| |
| void X86_64TargetInfo::computeInfo(FunctionInfo &FI) const { |
| CallingConv::ID CallingConv = FI.getCallingConvention(); |
| |
| // Only the standard SysV (C) calling convention is classified here. Any other |
| // convention must be added explicitly once it has been verified against this |
| // classifier rather than silently taking the SysV path. |
| switch (CallingConv) { |
| case CallingConv::C: |
| break; |
| default: |
| llvm_unreachable( |
| "calling convention not supported by the LLVMABI X86_64 classifier"); |
| } |
| |
| unsigned FreeIntRegs = 6; |
| unsigned FreeSSERegs = 8; |
| unsigned NeededInt = 0, NeededSSE = 0; |
| |
| if (!maybeCommonClassifyReturnType(FI)) { |
| const Type *RetTy = FI.getReturnType(); |
| FI.getReturnInfo() = classifyReturnType(RetTy); |
| } |
| |
| if (FI.getReturnInfo().isIndirect()) |
| --FreeIntRegs; |
| |
| unsigned NumRequiredArgs = FI.getNumRequiredArgs(); |
| |
| unsigned ArgNo = 0; |
| for (auto IT = FI.arg_begin(), IE = FI.arg_end(); IT != IE; ++IT, ++ArgNo) { |
| bool IsNamedArg = ArgNo < NumRequiredArgs; |
| const Type *ArgTy = IT->ABIType; |
| NeededInt = 0; |
| NeededSSE = 0; |
| |
| ArgInfo AI = classifyArgumentType(ArgTy, FreeIntRegs, NeededInt, NeededSSE, |
| IsNamedArg); |
| |
| // AMD64-ABI 3.2.3p3: If there are no registers available for any |
| // eightbyte of an argument, the whole argument is passed on the |
| // stack. If registers have already been assigned for some |
| // eightbytes of such an argument, the assignments get reverted. |
| if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) { |
| FreeIntRegs -= NeededInt; |
| FreeSSERegs -= NeededSSE; |
| IT->Info = AI; |
| } else { |
| // Not enough registers, pass on stack |
| IT->Info = getIndirectResult(ArgTy, FreeIntRegs); |
| } |
| } |
| } |
| |
| std::unique_ptr<TargetInfo> |
| createX86_64TargetInfo(TypeBuilder &TB, X86AVXABILevel AVXLevel, |
| bool Has64BitPointers, const ABICompatInfo &Compat) { |
| return std::make_unique<X86_64TargetInfo>(TB, AVXLevel, Has64BitPointers, |
| Compat); |
| } |
| |
| } // namespace abi |
| } // namespace llvm |