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;
80 bool isHomogeneousAggregateBaseType(
const Type *Ty)
const override;
81 bool isHomogeneousAggregateSmallEnough(
const Type *
Base,
84 bool isPermittedToBeHomogeneousAggregate(
const RecordType *RT)
const override;
87std::unique_ptr<TargetInfo>
89 return std::make_unique<AArch64TargetInfo>(TB, Opts);
95 <<
" is not yet implemented for AArch64 in the LLVM ABI library.\n";
98ArgInfo AArch64TargetInfo::classifyReturnType(
const Type *RetTy,
99 bool IsVariadicFn)
const {
104 if (VT->isFixedLengthSVEData() || VT->isFixedLengthSVEPredicate()) {
105 unsigned NSRN = 0, NPRN = 0;
106 return coerceIllegalVector(VT, NSRN, NPRN);
110 if (VT->getABISizeInBits() > 128)
114 if (!passAsAggregateType(RetTy)) {
116 if (IntTy->isBitInt())
117 if (RetTy->getSizeInBits().getFixedValue() > 128)
129 if (!RetTy->isSVESizelessType() && (RetTy->isEmptyRecord() ||
Size == 0))
135 !(Opts.IsILP32 && IsVariadicFn)) {
144 unsigned NSRN = 0, NPRN = 0;
145 unsigned NVec = 0, NPred = 0;
147 if (passAsPureScalableType(RetTy, NVec, NPred, UnpaddedCoerceToSeq) &&
149 return coerceAndExpandPureScalableAggregate(
150 RetTy,
true, NVec, NPred, UnpaddedCoerceToSeq, NSRN,
154 reportNYI(
"Aggregate return type handling");
158ArgInfo AArch64TargetInfo::classifyArgumentType(
159 const Type *Ty,
bool IsVariadicFn,
bool IsNamedArg,
160 unsigned CallingConvention,
unsigned &NSRN,
unsigned &NPRN)
const {
165 if (IsVariadicFn && Opts.IsWindowsArm64EC) {
166 reportNYI(
"Arm64EC variadic argument handling");
171 if (isIllegalVectorType(Ty))
174 if (!passAsAggregateType(Ty)) {
176 if (IntTy->isBitInt())
177 if (Ty->getSizeInBits().getFixedValue() > 128)
190 if (VT->isSVEPredicate() || VT->isSVECount())
191 NPRN = std::min(NPRN + 1, 4u);
193 NSRN = std::min(NSRN + 1, 8u);
195 if (
TT->getVectorType()->isSVEPredicate())
196 NPRN = std::min(NPRN +
TT->getNumVectors(), 4u);
198 NSRN = std::min(NSRN +
TT->getNumVectors(), 8u);
199 }
else if (Ty->isFloat()) {
200 NSRN = std::min(NSRN + 1, 8u);
218 if (!Ty->isSVESizelessType() && (Ty->isEmptyRecord() ||
Size == 0)) {
222 if (!Opts.IsCXX || isDarwinPCS())
237 bool IsWinVariadic = IsWin64 && IsVariadicFn;
241 NSRN = std::min(NSRN + Members,
uint64_t(8));
242 uint64_t BaseAllocSizeInBits =
Base->getTypeAllocSize().getFixedValue() * 8;
243 const Type *CoerceTy =
244 TB.getArrayType(
Base, Members, Members * BaseAllocSizeInBits);
250 unsigned TyAlign = Ty->getUnadjustedAlignment().value();
251 TyAlign = (TyAlign >= 16) ? 16 : 8;
258 unsigned NVec = 0, NPred = 0;
260 if (passAsPureScalableType(Ty, NVec, NPred, UnpaddedCoerceToSeq) &&
262 return coerceAndExpandPureScalableAggregate(
263 Ty, IsNamedArg, NVec, NPred, UnpaddedCoerceToSeq, NSRN, NPRN);
266 reportNYI(
"Aggregate argument type handling");
270bool AArch64TargetInfo::passAsAggregateType(
const Type *Ty)
const {
275 assert((!TupleTy || TupleTy->getNumVectors() > 1) &&
276 "unexpected single vector tuple");
277 return TupleTy && !TupleTy->getVectorType()->isSVECount();
286const VectorType *AArch64TargetInfo::convertFixedToScalableVectorType(
291 if (VT->isFixedLengthSVEPredicate())
292 return TB.getScalablePredicateOrCountVectorType(
Align(2),
295 assert(VT->isFixedLengthSVEData() &&
"expected a fixed-length SVE vector!");
297 const Type *EltTy = VT->getElementType();
298 uint64_t EltBits = EltTy->getSizeInBits().getFixedValue();
300 "unexpected element type for SVE data vector!");
308 unsigned &NPRN)
const {
309 if (VT->isFixedLengthSVEPredicate()) {
314 VT->getElementType()->getSizeInBits().getFixedValue() == 8 &&
315 "unexpected element type for SVE predicate!");
316 NPRN = std::min(NPRN + 1, 4u);
321 if (VT->isFixedLengthSVEData()) {
322 NSRN = std::min(NSRN + 1, 8u);
328 if (Opts.IsAndroidOrOHOS && (
Size <= 16)) {
329 auto *ResType =
TB.getIntegerType(16, llvm::Align(2),
false);
332 const Type *
I32 =
TB.getIntegerType(32, llvm::Align(4),
false);
336 NSRN = std::min(NSRN + 1, 8u);
341 NSRN = std::min(NSRN + 1, 8u);
349bool AArch64TargetInfo::isIllegalVectorType(
const Type *Ty)
const {
354 if (VT->isFixedLengthSVEData() || VT->isFixedLengthSVEPredicate())
358 if (VT->isScalable())
362 unsigned NumElements = VT->getNumElements().getFixedValue();
370 if (Opts.IsILP32 && Opts.IsMachO)
373 return Size != 64 && (
Size != 128 || NumElements == 1);
381void AArch64TargetInfo::flattenType(
382 const Type *Ty, SmallVectorImpl<const Type *> &Flattened)
const {
384 Flattened.push_back(Ty);
389 uint64_t NElt = AT->getNumElements();
394 flattenType(AT->getElementType(), EltFlattened);
402 for (
const FieldInfo &
Field : RT->getFields())
403 flattenType(
Field.FieldType, Flattened);
407 Flattened.push_back(Ty);
410ArgInfo AArch64TargetInfo::coerceAndExpandPureScalableAggregate(
411 const Type *Ty,
bool IsNamedArg,
unsigned NVec,
unsigned NPred,
412 const SmallVectorImpl<const Type *> &UnpaddedCoerceToSeq,
unsigned &NSRN,
413 unsigned &NPRN)
const {
416 if (!IsNamedArg || NSRN + NVec > 8 || NPRN + NPred > 4)
423 if (Ty->isSVESizelessType())
426 assert(!UnpaddedCoerceToSeq.empty() &&
"pure scalable type has no members");
427 const Type *UnpaddedCoerceToType =
428 UnpaddedCoerceToSeq.size() == 1
429 ? UnpaddedCoerceToSeq[0]
442bool AArch64TargetInfo::passAsPureScalableType(
443 const Type *Ty,
unsigned &NVec,
unsigned &NPred,
444 SmallVectorImpl<const Type *> &CoerceToSeq)
const {
446 if (AT->isMatrixType())
449 uint64_t NElt = AT->getNumElements();
453 unsigned NV = 0, NP = 0;
455 if (!passAsPureScalableType(AT->getElementType(), NV, NP, EltCoerceToSeq))
458 if (CoerceToSeq.size() + NElt * EltCoerceToSeq.size() > 12)
478 if (RT->hasFlexibleArrayMember())
484 for (
const FieldInfo &
Base : RT->getBaseClasses()) {
485 if (
Base.FieldType->isEmptyRecord())
487 if (!passAsPureScalableType(
Base.FieldType, NVec, NPred, CoerceToSeq))
490 for (
const FieldInfo &
Field : RT->getFields()) {
493 if (!passAsPureScalableType(
Field.FieldType, NVec, NPred, CoerceToSeq))
501 if (!VT->isScalable() || VT->isSVECount())
504 unsigned N =
TT->getNumVectors();
505 if (CoerceToSeq.size() +
N > 12)
508 bool IsPred = VT->isSVEPredicate();
509 if (!IsPred && !VT->isSVEData())
516 for (
unsigned I = 0;
I <
N; ++
I)
517 CoerceToSeq.push_back(VT);
522 const Type *Coerced =
nullptr;
524 if (VT->isFixedLengthSVEPredicate()) {
526 Coerced = convertFixedToScalableVectorType(VT);
527 }
else if (VT->isFixedLengthSVEData()) {
528 Coerced = convertFixedToScalableVectorType(VT);
529 }
else if (VT->isScalable() && VT->isSVEPredicate()) {
532 }
else if (VT->isScalable() && VT->isSVEData()) {
538 if (CoerceToSeq.size() + 1 > 12)
545 CoerceToSeq.push_back(Coerced);
552bool AArch64TargetInfo::isHomogeneousAggregateBaseType(
const Type *Ty)
const {
563 if (VT->isScalable() || VT->isSVEData() || VT->isSVEPredicate())
567 if (VecSize == 64 || VecSize == 128)
573bool AArch64TargetInfo::isHomogeneousAggregateSmallEnough(
585bool AArch64TargetInfo::isPermittedToBeHomogeneousAggregate(
587 if (Opts.IsMicrosoftCXXABI && RT->isCXXRecord()) {
590 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.
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.