31 return Opts.CompatInfo;
40 unsigned NSRN = 0, NPRN = 0;
42 const bool IsNamedArg =
45 I.Info = classifyArgumentType(
I.ABIType, FI.
isVariadic(), IsNamedArg,
53 ArgInfo classifyReturnType(
const Type *RetTy,
bool IsVariadicFn)
const;
54 ArgInfo classifyArgumentType(
const Type *Ty,
bool IsVariadicFn,
55 bool IsNamedArg,
unsigned CallingConvention,
56 unsigned &NSRN,
unsigned &NPRN)
const;
62 convertFixedToScalableVectorType(
const VectorType *VT)
const;
64 ArgInfo coerceIllegalVector(
const VectorType *VT,
unsigned &NSRN,
65 unsigned &NPRN)
const;
66 ArgInfo coerceAndExpandPureScalableAggregate(
67 const Type *Ty,
bool IsNamedArg,
unsigned NVec,
unsigned NPred,
68 const SmallVectorImpl<const Type *> &UnpaddedCoerceToSeq,
unsigned &NSRN,
69 unsigned &NPRN)
const;
71 bool isIllegalVectorType(
const Type *Ty)
const;
73 bool passAsAggregateType(
const Type *Ty)
const;
74 bool passAsPureScalableType(
const Type *Ty,
unsigned &NV,
unsigned &NP,
75 SmallVectorImpl<const Type *> &CoerceToSeq)
const;
77 void flattenType(
const Type *Ty,
78 SmallVectorImpl<const Type *> &Flattened)
const;
79 bool containsOnlyPointers(
const Type *Ty)
const;
81 bool isHomogeneousAggregateBaseType(
const Type *Ty)
const override;
82 bool isHomogeneousAggregateSmallEnough(
const Type *
Base,
85 bool isPermittedToBeHomogeneousAggregate(
const RecordType *RT)
const override;
88std::unique_ptr<TargetInfo>
90 return std::make_unique<AArch64TargetInfo>(TB, Opts);
96 <<
" is not yet implemented for AArch64 in the LLVM ABI library.\n";
99ArgInfo AArch64TargetInfo::classifyReturnType(
const Type *RetTy,
100 bool IsVariadicFn)
const {
105 if (VT->isFixedLengthSVEData() || VT->isFixedLengthSVEPredicate()) {
106 unsigned NSRN = 0, NPRN = 0;
107 return coerceIllegalVector(VT, NSRN, NPRN);
111 if (VT->getABISizeInBits() > 128)
115 if (!passAsAggregateType(RetTy)) {
117 if (IntTy->isBitInt())
118 if (RetTy->getSizeInBits().getFixedValue() > 128)
130 if (!RetTy->isSVESizelessType() && (RetTy->isEmptyRecord() ||
Size == 0))
136 !(Opts.IsILP32 && IsVariadicFn)) {
145 unsigned NSRN = 0, NPRN = 0;
146 unsigned NVec = 0, NPred = 0;
148 if (passAsPureScalableType(RetTy, NVec, NPred, UnpaddedCoerceToSeq) &&
150 return coerceAndExpandPureScalableAggregate(
151 RetTy,
true, NVec, NPred, UnpaddedCoerceToSeq, NSRN,
158 if (
Size <= 64 && !Opts.IsBigEndian) {
166 TB.getIntegerType(
Size, llvm::Align(8),
false));
169 uint64_t AlignBits = RetTy->getAlignment().value() * 8;
174 if (AlignBits < 128 &&
Size == 128) {
175 const Type *
I64 =
TB.getIntegerType(64, llvm::Align(8),
false);
179 TB.getIntegerType(
Size, llvm::Align(8),
false));
185ArgInfo AArch64TargetInfo::classifyArgumentType(
186 const Type *Ty,
bool IsVariadicFn,
bool IsNamedArg,
187 unsigned CallingConvention,
unsigned &NSRN,
unsigned &NPRN)
const {
192 if (IsVariadicFn && Opts.IsWindowsArm64EC) {
193 reportNYI(
"Arm64EC variadic argument handling");
198 if (isIllegalVectorType(Ty))
201 if (!passAsAggregateType(Ty)) {
203 if (IntTy->isBitInt())
204 if (Ty->getSizeInBits().getFixedValue() > 128)
217 if (VT->isSVEPredicate() || VT->isSVECount())
218 NPRN = std::min(NPRN + 1, 4u);
220 NSRN = std::min(NSRN + 1, 8u);
222 if (
TT->getVectorType()->isSVEPredicate())
223 NPRN = std::min(NPRN +
TT->getNumVectors(), 4u);
225 NSRN = std::min(NSRN +
TT->getNumVectors(), 8u);
226 }
else if (Ty->isFloat()) {
227 NSRN = std::min(NSRN + 1, 8u);
245 if (!Ty->isSVESizelessType() && (Ty->isEmptyRecord() ||
Size == 0)) {
249 if (!Opts.IsCXX || isDarwinPCS())
264 bool IsWinVariadic = IsWin64 && IsVariadicFn;
268 NSRN = std::min(NSRN + Members,
uint64_t(8));
269 uint64_t BaseAllocSizeInBits =
Base->getTypeAllocSize().getFixedValue() * 8;
270 const Type *CoerceTy =
271 TB.getArrayType(
Base, Members, Members * BaseAllocSizeInBits);
277 unsigned TyAlign = Ty->getUnadjustedAlignment().value();
278 TyAlign = (TyAlign >= 16) ? 16 : 8;
285 unsigned NVec = 0, NPred = 0;
287 if (passAsPureScalableType(Ty, NVec, NPred, UnpaddedCoerceToSeq) &&
289 return coerceAndExpandPureScalableAggregate(
290 Ty, IsNamedArg, NVec, NPred, UnpaddedCoerceToSeq, NSRN, NPRN);
296 if (
Size < 64 && !Opts.IsBigEndian &&
299 TB.getIntegerType(
Size, llvm::Align(8),
false));
305 AlignBits = Ty->getUnadjustedAlignment().value() * 8;
306 AlignBits = AlignBits < 128 ? 64 : 128;
309 uint64_t PointerWidth = Opts.IsILP32 ? 32 : 64;
310 AlignBits = std::max(Ty->getAlignment().value() * 8, PointerWidth);
315 if ((
Size == 64 ||
Size == 128) && AlignBits == 64 &&
316 containsOnlyPointers(Ty)) {
319 BaseTy =
TB.getPointerType(64, llvm::Align(8));
323 BaseTy =
TB.getIntegerType(AlignBits, llvm::Align(AlignBits / 8),
327 if (
Size == AlignBits)
339bool AArch64TargetInfo::containsOnlyPointers(
const Type *Ty)
const {
340 if (Ty->isEmptyRecord())
347 for (
const FieldInfo &
Base : RT->getBaseClasses())
348 if (!containsOnlyPointers(
Base.FieldType))
351 for (
const FieldInfo &
Field : RT->getFields()) {
354 if (AT->isMatrixType())
356 FT = AT->getElementType();
359 bool IsPlainPointer =
false;
361 IsPlainPointer = PT->getSizeInBits().getFixedValue() == 64 &&
362 PT->getAddrSpace() == 0 &&
363 !PT->hasAddressSpaceQualifier();
364 if (!IsPlainPointer && !containsOnlyPointers(FT))
370bool AArch64TargetInfo::passAsAggregateType(
const Type *Ty)
const {
375 assert((!TupleTy || TupleTy->getNumVectors() > 1) &&
376 "unexpected single vector tuple");
377 return TupleTy && !TupleTy->getVectorType()->isSVECount();
386const VectorType *AArch64TargetInfo::convertFixedToScalableVectorType(
391 if (VT->isFixedLengthSVEPredicate())
392 return TB.getScalablePredicateOrCountVectorType(
Align(2),
395 assert(VT->isFixedLengthSVEData() &&
"expected a fixed-length SVE vector!");
397 const Type *EltTy = VT->getElementType();
398 uint64_t EltBits = EltTy->getSizeInBits().getFixedValue();
400 "unexpected element type for SVE data vector!");
408 unsigned &NPRN)
const {
409 if (VT->isFixedLengthSVEPredicate()) {
414 VT->getElementType()->getSizeInBits().getFixedValue() == 8 &&
415 "unexpected element type for SVE predicate!");
416 NPRN = std::min(NPRN + 1, 4u);
421 if (VT->isFixedLengthSVEData()) {
422 NSRN = std::min(NSRN + 1, 8u);
428 if (Opts.IsAndroidOrOHOS && (
Size <= 16)) {
429 auto *ResType =
TB.getIntegerType(16, llvm::Align(2),
false);
432 const Type *
I32 =
TB.getIntegerType(32, llvm::Align(4),
false);
436 NSRN = std::min(NSRN + 1, 8u);
441 NSRN = std::min(NSRN + 1, 8u);
449bool AArch64TargetInfo::isIllegalVectorType(
const Type *Ty)
const {
454 if (VT->isFixedLengthSVEData() || VT->isFixedLengthSVEPredicate())
458 if (VT->isScalable())
462 unsigned NumElements = VT->getNumElements().getFixedValue();
470 if (Opts.IsILP32 && Opts.IsMachO)
473 return Size != 64 && (
Size != 128 || NumElements == 1);
481void AArch64TargetInfo::flattenType(
482 const Type *Ty, SmallVectorImpl<const Type *> &Flattened)
const {
484 Flattened.push_back(Ty);
489 uint64_t NElt = AT->getNumElements();
494 flattenType(AT->getElementType(), EltFlattened);
502 for (
const FieldInfo &
Field : RT->getFields())
503 flattenType(
Field.FieldType, Flattened);
507 Flattened.push_back(Ty);
510ArgInfo AArch64TargetInfo::coerceAndExpandPureScalableAggregate(
511 const Type *Ty,
bool IsNamedArg,
unsigned NVec,
unsigned NPred,
512 const SmallVectorImpl<const Type *> &UnpaddedCoerceToSeq,
unsigned &NSRN,
513 unsigned &NPRN)
const {
516 if (!IsNamedArg || NSRN + NVec > 8 || NPRN + NPred > 4)
523 if (Ty->isSVESizelessType())
526 assert(!UnpaddedCoerceToSeq.empty() &&
"pure scalable type has no members");
527 const Type *UnpaddedCoerceToType =
528 UnpaddedCoerceToSeq.size() == 1
529 ? UnpaddedCoerceToSeq[0]
542bool AArch64TargetInfo::passAsPureScalableType(
543 const Type *Ty,
unsigned &NVec,
unsigned &NPred,
544 SmallVectorImpl<const Type *> &CoerceToSeq)
const {
546 if (AT->isMatrixType())
549 uint64_t NElt = AT->getNumElements();
553 unsigned NV = 0, NP = 0;
555 if (!passAsPureScalableType(AT->getElementType(), NV, NP, EltCoerceToSeq))
558 if (CoerceToSeq.size() + NElt * EltCoerceToSeq.size() > 12)
578 if (RT->hasFlexibleArrayMember())
584 for (
const FieldInfo &
Base : RT->getBaseClasses()) {
585 if (
Base.FieldType->isEmptyRecord())
587 if (!passAsPureScalableType(
Base.FieldType, NVec, NPred, CoerceToSeq))
590 for (
const FieldInfo &
Field : RT->getFields()) {
593 if (!passAsPureScalableType(
Field.FieldType, NVec, NPred, CoerceToSeq))
601 if (!VT->isScalable() || VT->isSVECount())
604 unsigned N =
TT->getNumVectors();
605 if (CoerceToSeq.size() +
N > 12)
608 bool IsPred = VT->isSVEPredicate();
609 if (!IsPred && !VT->isSVEData())
616 for (
unsigned I = 0;
I <
N; ++
I)
617 CoerceToSeq.push_back(VT);
622 const Type *Coerced =
nullptr;
624 if (VT->isFixedLengthSVEPredicate()) {
626 Coerced = convertFixedToScalableVectorType(VT);
627 }
else if (VT->isFixedLengthSVEData()) {
628 Coerced = convertFixedToScalableVectorType(VT);
629 }
else if (VT->isScalable() && VT->isSVEPredicate()) {
632 }
else if (VT->isScalable() && VT->isSVEData()) {
638 if (CoerceToSeq.size() + 1 > 12)
645 CoerceToSeq.push_back(Coerced);
652bool AArch64TargetInfo::isHomogeneousAggregateBaseType(
const Type *Ty)
const {
663 if (VT->isScalable() || VT->isSVEData() || VT->isSVEPredicate())
667 if (VecSize == 64 || VecSize == 128)
673bool AArch64TargetInfo::isHomogeneousAggregateSmallEnough(
685bool AArch64TargetInfo::isPermittedToBeHomogeneousAggregate(
687 if (Opts.IsMicrosoftCXXABI && RT->isCXXRecord()) {
690 reportNYI(
"MicrosoftCXXABI homogeneous record classification");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
OptimizedStructLayoutField Field
This file defines the SmallVector class.
FunctionLoweringInfo::StatepointRelocationRecord RecordType
Target-specific ABI information and factory functions.
static constexpr ElementCount getScalable(ScalarTy MinVal)
static constexpr ElementCount getFixed(ScalarTy MinVal)
Represent a constant reference to a string, i.e.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
AArch64TargetInfo(TypeBuilder &TB, const AArch64ABIOptions &Opts)
void computeInfo(FunctionInfo &FI) const override
Populate FI with the target's ABI-lowering decisions for each argument and return value.
const ABICompatInfo & getABICompatInfo() const override
Return this target's ABI compatibility flags.
Helper class to encapsulate information about how a specific type should be passed to or returned fro...
static bool isPaddingForCoerceAndExpand(const Type *Ty)
True if Ty is an array of i8, the padding element of a coerce-and-expand type.
static ArgInfo getIgnore()
static ArgInfo getCoerceAndExpand(const Type *CoerceToType, const Type *UnpaddedCoerceToType)
static ArgInfo getExtend(const Type *T)
static ArgInfo getDirect(const Type *T=nullptr, unsigned Offset=0, MaybeAlign Align=std::nullopt, bool CanBeFlattened=true)
ArrayRef< ArgEntry > arguments() const
unsigned getNumRequiredArgs() const
CallingConv::ID getCallingConvention() const
ArgInfo & getReturnInfo()
const Type * getReturnType() const
virtual unsigned getAllocaAddrSpace() const
Address space in which indirect arguments are allocated (the target's alloca/stack space).
LLVM_ABI bool isHomogeneousAggregate(const Type *Ty, const Type *&Base, uint64_t &Members) const
Return true if Ty is an ELFv2-style homogeneous aggregate.
LLVM_ABI bool isPromotableInteger(const IntegerType *IT) const
virtual bool isZeroLengthBitfieldPermittedInHomogeneousAggregate() const
Return true if zero-length bitfields should be ignored when deciding whether an aggregate is homogene...
TargetInfo(TypeBuilder &Builder)
LLVM_ABI const Type * getStructOfTypes(ArrayRef< const Type * > Elems, bool Packed) const
A record with one field per element of Elems, each at offset 0.
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
LLVM_ABI const Type * convertTypeForMem(const Type *Ty) const
In-memory form of Ty.
TypeBuilder manages the lifecycle of ABI types using bump pointer allocation.
Represents the ABI-specific view of a type in LLVM.
This file defines the type system for the LLVMABI library, which mirrors ABI-relevant aspects of fron...
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ Win64
The C convention as implemented on Windows/x86-64 and AArch64.
static void reportNYI(StringRef Feature)
@ SVEPredicate
An AArch64 SVE predicate vector, such as svbool_t.
@ SVEData
An AArch64 SVE data vector, such as svint32_t.
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
@ RAA_Default
Pass it using the normal C aggregate rules for the ABI, potentially introducing extra copies and pass...
LLVM_ABI std::unique_ptr< TargetInfo > createAArch64TargetInfo(TypeBuilder &TB, const AArch64ABIOptions &Opts)
DiagnosticInfoOptimizationBase::Argument NV
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.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Helper struct shared between Function Specialization and SCCP Solver.
Target / language flags that affect AArch64 ABI classification.
Flags controlling ABI compatibility behaviour that applies to every target.