1//===- AArch64.cpp - AArch64 ABI Implementation ---------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ABI/FunctionInfo.h"
10#include "llvm/ABI/TargetInfo.h"
11#include "llvm/ABI/Types.h"
12#include "llvm/ADT/STLExtras.h"
13#include "llvm/ADT/SmallVector.h"
14#include "llvm/Support/Casting.h"
15#include "llvm/Support/ErrorHandling.h"
16#include "llvm/Support/MathExtras.h"
17#include "llvm/Support/TypeSize.h"
18#include "llvm/Support/WithColor.h"
19#include <algorithm>
20#include <cstdint>
21
22namespace llvm {
23namespace abi {
24
25class AArch64TargetInfo : public TargetInfo {
26public:
27 AArch64TargetInfo(TypeBuilder &TB, const AArch64ABIOptions &Opts)
28 : TargetInfo(TB), Opts(Opts) {}
29
30 const ABICompatInfo &getABICompatInfo() const override {
31 return Opts.CompatInfo;
32 }
33
34 void computeInfo(FunctionInfo &FI) const override {
35 if (!maybeCommonClassifyReturnType(FI))
36 FI.getReturnInfo() =
37 classifyReturnType(RetTy: FI.getReturnType(), IsVariadicFn: FI.isVariadic());
38
39 unsigned ArgNo = 0;
40 unsigned NSRN = 0, NPRN = 0;
41 for (auto &I : FI.arguments()) {
42 const bool IsNamedArg =
43 !FI.isVariadic() || ArgNo < FI.getNumRequiredArgs();
44 ++ArgNo;
45 I.Info = classifyArgumentType(Ty: I.ABIType, IsVariadicFn: FI.isVariadic(), IsNamedArg,
46 CallingConvention: FI.getCallingConvention(), NSRN, NPRN);
47 }
48 }
49
50private:
51 AArch64ABIOptions Opts;
52
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;
57
58 bool isDarwinPCS() const { return Opts.Kind == AArch64ABIKind::DarwinPCS; }
59 bool isSoftFloat() const { return Opts.Kind == AArch64ABIKind::AAPCSSoft; }
60
61 const VectorType *
62 convertFixedToScalableVectorType(const VectorType *VT) const;
63
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;
70
71 bool isIllegalVectorType(const Type *Ty) const;
72
73 bool passAsAggregateType(const Type *Ty) const;
74 bool passAsPureScalableType(const Type *Ty, unsigned &NV, unsigned &NP,
75 SmallVectorImpl<const Type *> &CoerceToSeq) const;
76
77 void flattenType(const Type *Ty,
78 SmallVectorImpl<const Type *> &Flattened) const;
79 bool containsOnlyPointers(const Type *Ty) const;
80
81 bool isHomogeneousAggregateBaseType(const Type *Ty) const override;
82 bool isHomogeneousAggregateSmallEnough(const Type *Base,
83 uint64_t Members) const override;
84 bool isZeroLengthBitfieldPermittedInHomogeneousAggregate() const override;
85 bool isPermittedToBeHomogeneousAggregate(const RecordType *RT) const override;
86};
87
88std::unique_ptr<TargetInfo>
89createAArch64TargetInfo(TypeBuilder &TB, const AArch64ABIOptions &Opts) {
90 return std::make_unique<AArch64TargetInfo>(args&: TB, args: Opts);
91}
92
93static void reportNYI(StringRef Feature) {
94 WithColor::warning()
95 << Feature
96 << " is not yet implemented for AArch64 in the LLVM ABI library.\n";
97}
98
99ArgInfo AArch64TargetInfo::classifyReturnType(const Type *RetTy,
100 bool IsVariadicFn) const {
101 if (RetTy->isVoid())
102 return ArgInfo::getIgnore();
103
104 if (const auto *VT = dyn_cast<VectorType>(Val: RetTy)) {
105 if (VT->isFixedLengthSVEData() || VT->isFixedLengthSVEPredicate()) {
106 unsigned NSRN = 0, NPRN = 0;
107 return coerceIllegalVector(VT, NSRN, NPRN);
108 }
109
110 // Large vector types should be returned via memory.
111 if (VT->getABISizeInBits() > 128)
112 return getNaturalAlignIndirect(Ty: RetTy, AddrSpace: getAllocaAddrSpace());
113 }
114
115 if (!passAsAggregateType(Ty: RetTy)) {
116 if (const auto *IntTy = dyn_cast<IntegerType>(Val: RetTy)) {
117 if (IntTy->isBitInt())
118 if (RetTy->getSizeInBits().getFixedValue() > 128)
119 return getNaturalAlignIndirect(Ty: RetTy, AddrSpace: getAllocaAddrSpace());
120
121 if (isPromotableInteger(IT: IntTy) && isDarwinPCS())
122 return ArgInfo::getExtend(T: IntTy);
123 }
124
125 // Everything not handled above is returned directly.
126 return ArgInfo::getDirect();
127 }
128
129 uint64_t Size = RetTy->getFixedSizeInBitsOrZero();
130 if (!RetTy->isSVESizelessType() && (RetTy->isEmptyRecord() || Size == 0))
131 return ArgInfo::getIgnore();
132
133 const Type *Base = nullptr;
134 uint64_t Members = 0;
135 if (isHomogeneousAggregate(Ty: RetTy, Base, Members) &&
136 !(Opts.IsILP32 && IsVariadicFn)) {
137 // Homogeneous Floating-point Aggregates (HFAs) are returned directly.
138 return ArgInfo::getDirect();
139 }
140
141 // In AAPCS return values of a Pure Scalable type are treated as a single
142 // named argument and passed expanded in registers, or indirectly if there are
143 // not enough registers.
144 if (Opts.Kind == AArch64ABIKind::AAPCS) {
145 unsigned NSRN = 0, NPRN = 0;
146 unsigned NVec = 0, NPred = 0;
147 SmallVector<const Type *> UnpaddedCoerceToSeq;
148 if (passAsPureScalableType(Ty: RetTy, NV&: NVec, NP&: NPred, CoerceToSeq&: UnpaddedCoerceToSeq) &&
149 (NVec + NPred) > 0)
150 return coerceAndExpandPureScalableAggregate(
151 Ty: RetTy, /*IsNamedArg=*/true, NVec, NPred, UnpaddedCoerceToSeq, NSRN,
152 NPRN);
153 }
154
155 // Aggregates of at most 16 bytes are returned directly in registers or on
156 // the stack.
157 if (Size <= 128) {
158 if (Size <= 64 && !Opts.IsBigEndian) {
159 // Composite types are returned in lower bits of a 64-bit register for LE,
160 // and in higher bits for BE. However, integer types are always returned
161 // in lower bits for both LE and BE, and they are not rounded up to
162 // 64-bits. We can skip rounding up of composite types for LE, but not for
163 // BE, otherwise composite types will be indistinguishable from integer
164 // types.
165 return ArgInfo::getDirect(
166 T: TB.getIntegerType(BitWidth: Size, Align: llvm::Align(8), /*Signed=*/false));
167 }
168
169 uint64_t AlignBits = RetTy->getAlignment().value() * 8;
170 Size = llvm::alignTo(Value: Size, Align: 64); // round up to multiple of 8 bytes
171
172 // A 16-byte value whose ABI alignment is below 16 bytes is a pair of
173 // i64. A 16-byte-aligned value is an i128.
174 if (AlignBits < 128 && Size == 128) {
175 const Type *I64 = TB.getIntegerType(BitWidth: 64, Align: llvm::Align(8), /*Signed=*/false);
176 return ArgInfo::getDirect(T: TB.getArrayType(ElementType: I64, NumElements: Size / 64, SizeInBits: Size));
177 }
178 return ArgInfo::getDirect(
179 T: TB.getIntegerType(BitWidth: Size, Align: llvm::Align(8), /*Signed=*/false));
180 }
181
182 return getNaturalAlignIndirect(Ty: RetTy, AddrSpace: getAllocaAddrSpace());
183}
184
185ArgInfo AArch64TargetInfo::classifyArgumentType(
186 const Type *Ty, bool IsVariadicFn, bool IsNamedArg,
187 unsigned CallingConvention, unsigned &NSRN, unsigned &NPRN) const {
188 Ty = useFirstFieldIfTransparentUnion(Ty);
189
190 // Arm64EC variadic functions classify their arguments with the x86-64
191 // rules rather than the AArch64 ones.
192 if (IsVariadicFn && Opts.IsWindowsArm64EC) {
193 reportNYI(Feature: "Arm64EC variadic argument handling");
194 return ArgInfo::getIgnore();
195 }
196
197 // Handle illegal vector types here.
198 if (isIllegalVectorType(Ty))
199 return coerceIllegalVector(VT: cast<VectorType>(Val: Ty), NSRN, NPRN);
200
201 if (!passAsAggregateType(Ty)) {
202 if (const auto *IntTy = dyn_cast<IntegerType>(Val: Ty)) {
203 if (IntTy->isBitInt())
204 if (Ty->getSizeInBits().getFixedValue() > 128)
205 return getNaturalAlignIndirect(Ty, AddrSpace: getAllocaAddrSpace(),
206 /*ByVal=*/false);
207
208 if (isPromotableInteger(IT: IntTy) && isDarwinPCS())
209 return ArgInfo::getExtend(T: IntTy);
210 }
211
212 // Predicates and svcount_t are passed in a predicate register. Legal
213 // vectors, SVE data vectors, and floating-point types are passed in a
214 // SIMD and floating-point register. A tuple occupies one register of the
215 // appropriate kind per vector it contains.
216 if (const auto *VT = dyn_cast<VectorType>(Val: Ty)) {
217 if (VT->isSVEPredicate() || VT->isSVECount())
218 NPRN = std::min(a: NPRN + 1, b: 4u);
219 else
220 NSRN = std::min(a: NSRN + 1, b: 8u);
221 } else if (const auto *TT = dyn_cast<TupleType>(Val: Ty)) {
222 if (TT->getVectorType()->isSVEPredicate())
223 NPRN = std::min(a: NPRN + TT->getNumVectors(), b: 4u);
224 else
225 NSRN = std::min(a: NSRN + TT->getNumVectors(), b: 8u);
226 } else if (Ty->isFloat()) {
227 NSRN = std::min(a: NSRN + 1, b: 8u);
228 }
229
230 // Everything not handled above is returned directly.
231 return ArgInfo::getDirect();
232 }
233
234 // Structures with either a non-trivial destructor or a non-trivial
235 // copy constructor are always indirect.
236 if (auto RecordRAA = getRecordArgABI(Ty)) {
237 return getNaturalAlignIndirect(Ty, AddrSpace: getAllocaAddrSpace(),
238 /*ByVal=*/RecordRAA ==
239 RecordArgABI::RAA_DirectInMemory);
240 }
241
242 // AAPCS64 does not say that empty C records are ignored as arguments,
243 // but other compilers do so in certain situations, and we copy that behavior.
244 uint64_t Size = Ty->getFixedSizeInBitsOrZero();
245 if (!Ty->isSVESizelessType() && (Ty->isEmptyRecord() || Size == 0)) {
246 // Darwin overrides the psABI here to ignore all empty records in all modes.
247 // The ABI explicitly says that an empty class shall be treated as if its
248 // type were an aggregate with a single member of type unsigned byte.
249 if (!Opts.IsCXX || isDarwinPCS())
250 return ArgInfo::getIgnore();
251
252 // In C++ mode, arguments which have sizeof() == 0 (which are non-standard
253 // C++) are ignored. This isn't defined by any standard, so we copy GCC's
254 // behaviour here.
255 if (Size == 0)
256 return ArgInfo::getIgnore();
257 }
258
259 // Homogeneous Floating-point Aggregates (HFAs) need to be expanded.
260 const Type *Base = nullptr;
261 uint64_t Members = 0;
262 bool IsWin64 = Opts.Kind == AArch64ABIKind::Win64 ||
263 CallingConvention == llvm::CallingConv::Win64;
264 bool IsWinVariadic = IsWin64 && IsVariadicFn;
265 // In variadic functions on Windows, all composite types are treated alike,
266 // no special handling of HFAs/HVAs.
267 if (!IsWinVariadic && isHomogeneousAggregate(Ty, Base, Members)) {
268 NSRN = std::min(a: NSRN + Members, b: uint64_t(8));
269 uint64_t BaseAllocSizeInBits = Base->getTypeAllocSize().getFixedValue() * 8;
270 const Type *CoerceTy =
271 TB.getArrayType(ElementType: Base, NumElements: Members, SizeInBits: Members * BaseAllocSizeInBits);
272 if (Opts.Kind != AArch64ABIKind::AAPCS)
273 return ArgInfo::getDirect(T: CoerceTy);
274
275 // For HFAs/HVAs, cap the argument alignment to 16, otherwise
276 // set it to 8 according to the AAPCS64 document.
277 unsigned TyAlign = Ty->getUnadjustedAlignment().value();
278 TyAlign = (TyAlign >= 16) ? 16 : 8;
279 return ArgInfo::getDirect(T: CoerceTy, /*Offset=*/0, Align: llvm::Align(TyAlign));
280 }
281
282 // In AAPCS, named arguments of a Pure Scalable Type are passed expanded
283 // in registers, or indirectly if there are not enough registers.
284 if (Opts.Kind == AArch64ABIKind::AAPCS) {
285 unsigned NVec = 0, NPred = 0;
286 SmallVector<const Type *> UnpaddedCoerceToSeq;
287 if (passAsPureScalableType(Ty, NV&: NVec, NP&: NPred, CoerceToSeq&: UnpaddedCoerceToSeq) &&
288 (NVec + NPred) > 0)
289 return coerceAndExpandPureScalableAggregate(
290 Ty, IsNamedArg, NVec, NPred, UnpaddedCoerceToSeq, NSRN, NPRN);
291 }
292
293 // Aggregates of at most 16 bytes are passed directly in registers or on
294 // the stack.
295 if (Size <= 128) {
296 if (Size < 64 && !Opts.IsBigEndian &&
297 Opts.Kind != AArch64ABIKind::DarwinPCS)
298 return ArgInfo::getDirect(
299 T: TB.getIntegerType(BitWidth: Size, Align: llvm::Align(8), /*Signed=*/false));
300
301 uint64_t AlignBits;
302 if (Opts.Kind == AArch64ABIKind::AAPCS) {
303 // An 8-byte slot when the unadjusted alignment is below 16 bytes, and
304 // a 16-byte slot otherwise.
305 AlignBits = Ty->getUnadjustedAlignment().value() * 8;
306 AlignBits = AlignBits < 128 ? 64 : 128;
307 } else {
308 // The larger of the ABI alignment and the pointer width.
309 uint64_t PointerWidth = Opts.IsILP32 ? 32 : 64;
310 AlignBits = std::max(a: Ty->getAlignment().value() * 8, b: PointerWidth);
311 }
312 Size = llvm::alignTo(Value: Size, Align: AlignBits);
313
314 const Type *BaseTy;
315 if ((Size == 64 || Size == 128) && AlignBits == 64 &&
316 containsOnlyPointers(Ty)) {
317 // A record of 64-bit pointers in an 8-byte slot is coerced to a pointer
318 // or an array of pointers.
319 BaseTy = TB.getPointerType(Size: 64, Align: llvm::Align(8));
320 } else {
321 // Every other aggregate is coerced to an integer of the slot width, or
322 // an array of those integers.
323 BaseTy = TB.getIntegerType(BitWidth: AlignBits, Align: llvm::Align(AlignBits / 8),
324 /*Signed=*/false);
325 }
326
327 if (Size == AlignBits)
328 return ArgInfo::getDirect(T: BaseTy);
329 return ArgInfo::getDirect(T: TB.getArrayType(ElementType: BaseTy, NumElements: Size / AlignBits, SizeInBits: Size));
330 }
331
332 return getNaturalAlignIndirect(Ty, AddrSpace: getAllocaAddrSpace(), /*ByVal=*/false);
333}
334
335// True for a record whose bases and fields are plain pointers, or records of
336// such pointers. A plain pointer is a 64-bit pointer with no address-space
337// qualifier. An array field is inspected through its base element. False for an
338// empty record and for a type that is not a record.
339bool AArch64TargetInfo::containsOnlyPointers(const Type *Ty) const {
340 if (Ty->isEmptyRecord())
341 return false;
342
343 const auto *RT = dyn_cast<RecordType>(Val: Ty);
344 if (!RT)
345 return false;
346
347 for (const FieldInfo &Base : RT->getBaseClasses())
348 if (!containsOnlyPointers(Ty: Base.FieldType))
349 return false;
350
351 for (const FieldInfo &Field : RT->getFields()) {
352 const Type *FT = Field.FieldType;
353 while (const auto *AT = dyn_cast<ArrayType>(Val: FT)) {
354 if (AT->isMatrixType())
355 break;
356 FT = AT->getElementType();
357 }
358
359 bool IsPlainPointer = false;
360 if (const auto *PT = dyn_cast<PointerType>(Val: FT))
361 IsPlainPointer = PT->getSizeInBits().getFixedValue() == 64 &&
362 PT->getAddrSpace() == 0 &&
363 !PT->hasAddressSpaceQualifier();
364 if (!IsPlainPointer && !containsOnlyPointers(Ty: FT))
365 return false;
366 }
367 return true;
368}
369
370bool AArch64TargetInfo::passAsAggregateType(const Type *Ty) const {
371 if (Opts.Kind == AArch64ABIKind::AAPCS && Ty->isSVESizelessType()) {
372 // svcount_t and the single-vector types occupy a register of their own,
373 // so only the data and predicate tuples are passed as aggregates.
374 const auto *TupleTy = dyn_cast<TupleType>(Val: Ty);
375 assert((!TupleTy || TupleTy->getNumVectors() > 1) &&
376 "unexpected single vector tuple");
377 return TupleTy && !TupleTy->getVectorType()->isSVECount();
378 }
379 return isAggregateTypeForABI(Ty);
380}
381
382/// Returns the scalable vector type that \p VT, a fixed-length SVE vector,
383/// is passed as. A scalable SVE vector holds 128 bits per granule, so the
384/// scalable element count is 128 divided by the element size, regardless of
385/// how many elements the fixed-length type has.
386const VectorType *AArch64TargetInfo::convertFixedToScalableVectorType(
387 const VectorType *VT) const {
388 // TODO: Verify that this correctly handles MFloat8 when we decide on a
389 // mapping for that type.
390
391 if (VT->isFixedLengthSVEPredicate())
392 return TB.getScalablePredicateOrCountVectorType(ABIAlign: Align(2),
393 Kind: VectorKind::SVEPredicate);
394
395 assert(VT->isFixedLengthSVEData() && "expected a fixed-length SVE vector!");
396
397 const Type *EltTy = VT->getElementType();
398 uint64_t EltBits = EltTy->getSizeInBits().getFixedValue();
399 assert(EltBits >= 8 && EltBits <= 64 && isPowerOf2_64(EltBits) &&
400 "unexpected element type for SVE data vector!");
401
402 return TB.getVectorType(ElementType: EltTy, NumElements: ElementCount::getScalable(MinVal: 128 / EltBits),
403 Align: llvm::Align(16), VecKind: VectorKind::SVEData);
404}
405
406ArgInfo AArch64TargetInfo::coerceIllegalVector(const VectorType *VT,
407 unsigned &NSRN,
408 unsigned &NPRN) const {
409 if (VT->isFixedLengthSVEPredicate()) {
410 // Fixed-length predicates are described with 8-bit elements, but they are
411 // passed in a predicate register as a scalable vector of 16 one-bit
412 // elements.
413 assert(isa<IntegerType>(VT->getElementType()) &&
414 VT->getElementType()->getSizeInBits().getFixedValue() == 8 &&
415 "unexpected element type for SVE predicate!");
416 NPRN = std::min(a: NPRN + 1, b: 4u);
417 return ArgInfo::getDirect(T: TB.getScalablePredicateOrCountVectorType(
418 ABIAlign: Align(2), Kind: VectorKind::SVEPredicate));
419 }
420
421 if (VT->isFixedLengthSVEData()) {
422 NSRN = std::min(a: NSRN + 1, b: 8u);
423 return ArgInfo::getDirect(T: convertFixedToScalableVectorType(VT));
424 }
425
426 uint64_t Size = VT->getABISizeInBits();
427 // Android promotes <2 x i8> to i16, not i32
428 if (Opts.IsAndroidOrOHOS && (Size <= 16)) {
429 auto *ResType = TB.getIntegerType(BitWidth: 16, Align: llvm::Align(2), /*Signed=*/false);
430 return ArgInfo::getDirect(T: ResType);
431 }
432 const Type *I32 = TB.getIntegerType(BitWidth: 32, Align: llvm::Align(4), /*Signed=*/false);
433 if (Size <= 32)
434 return ArgInfo::getDirect(T: I32);
435 if (Size == 64) {
436 NSRN = std::min(a: NSRN + 1, b: 8u);
437 return ArgInfo::getDirect(
438 T: TB.getVectorType(ElementType: I32, NumElements: ElementCount::getFixed(MinVal: 2), Align: llvm::Align(8)));
439 }
440 if (Size == 128) {
441 NSRN = std::min(a: NSRN + 1, b: 8u);
442 return ArgInfo::getDirect(
443 T: TB.getVectorType(ElementType: I32, NumElements: ElementCount::getFixed(MinVal: 4), Align: llvm::Align(16)));
444 }
445
446 return getNaturalAlignIndirect(Ty: VT, AddrSpace: getAllocaAddrSpace(), /*ByVal=*/false);
447}
448
449bool AArch64TargetInfo::isIllegalVectorType(const Type *Ty) const {
450 if (const auto *VT = dyn_cast<VectorType>(Val: Ty)) {
451 // Check whether VT is a fixed-length SVE vector. These types are
452 // represented as scalable vectors in function args/return and must be
453 // coerced from fixed vectors.
454 if (VT->isFixedLengthSVEData() || VT->isFixedLengthSVEPredicate())
455 return true;
456
457 // Scalable SVE types are legal.
458 if (VT->isScalable())
459 return false;
460
461 // Check whether VT is legal.
462 unsigned NumElements = VT->getNumElements().getFixedValue();
463 uint64_t Size = VT->getABISizeInBits();
464 // NumElements should be power of 2.
465 if (!isPowerOf2_32(Value: NumElements))
466 return true;
467
468 // arm64_32 has to be compatible with the ARM logic here, which allows huge
469 // vectors for some reason.
470 if (Opts.IsILP32 && Opts.IsMachO)
471 return Size <= 32;
472
473 return Size != 64 && (Size != 128 || NumElements == 1);
474 }
475 return false;
476}
477
478// Expand a memory type into a sequence with an element for each non-record,
479// non-array member of the type, with the exception of the padding types, which
480// are retained.
481void AArch64TargetInfo::flattenType(
482 const Type *Ty, SmallVectorImpl<const Type *> &Flattened) const {
483 if (ArgInfo::isPaddingForCoerceAndExpand(Ty)) {
484 Flattened.push_back(Elt: Ty);
485 return;
486 }
487
488 if (const auto *AT = dyn_cast<ArrayType>(Val: Ty)) {
489 uint64_t NElt = AT->getNumElements();
490 if (NElt == 0)
491 return;
492
493 SmallVector<const Type *, 4> EltFlattened;
494 flattenType(Ty: AT->getElementType(), Flattened&: EltFlattened);
495
496 for (uint64_t I = 0; I < NElt; ++I)
497 llvm::append_range(C&: Flattened, R&: EltFlattened);
498 return;
499 }
500
501 if (const auto *RT = dyn_cast<RecordType>(Val: Ty)) {
502 for (const FieldInfo &Field : RT->getFields())
503 flattenType(Ty: Field.FieldType, Flattened);
504 return;
505 }
506
507 Flattened.push_back(Elt: Ty);
508}
509
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 {
514 // An unnamed argument, or one that does not fit in the remaining Z or P
515 // registers, is passed indirectly and does not consume those registers.
516 if (!IsNamedArg || NSRN + NVec > 8 || NPRN + NPred > 4)
517 return getNaturalAlignIndirect(Ty, AddrSpace: getAllocaAddrSpace(), /*ByVal=*/false);
518
519 NSRN += NVec;
520 NPRN += NPred;
521
522 // A sizeless SVE tuple is already one register per member.
523 if (Ty->isSVESizelessType())
524 return ArgInfo::getDirect();
525
526 assert(!UnpaddedCoerceToSeq.empty() && "pure scalable type has no members");
527 const Type *UnpaddedCoerceToType =
528 UnpaddedCoerceToSeq.size() == 1
529 ? UnpaddedCoerceToSeq[0]
530 : getStructOfTypes(Elems: UnpaddedCoerceToSeq, /*Packed=*/true);
531
532 SmallVector<const Type *, 8> CoerceToSeq;
533 flattenType(Ty: convertTypeForMem(Ty), Flattened&: CoerceToSeq);
534 return ArgInfo::getCoerceAndExpand(
535 CoerceToType: getStructOfTypes(Elems: CoerceToSeq, /*Packed=*/false), UnpaddedCoerceToType);
536}
537
538// A Pure Scalable Type (AAPCS64) is passed in Z and P registers. On success
539// NVec and NPred are how many of each it needs, and CoerceToSeq has one
540// scalable vector per register. A sequence longer than 12 is rejected so the
541// caller treats the type as a large composite.
542bool AArch64TargetInfo::passAsPureScalableType(
543 const Type *Ty, unsigned &NVec, unsigned &NPred,
544 SmallVectorImpl<const Type *> &CoerceToSeq) const {
545 if (const auto *AT = dyn_cast<ArrayType>(Val: Ty)) {
546 if (AT->isMatrixType())
547 return false;
548
549 uint64_t NElt = AT->getNumElements();
550 if (NElt == 0)
551 return false;
552
553 unsigned NV = 0, NP = 0;
554 SmallVector<const Type *, 4> EltCoerceToSeq;
555 if (!passAsPureScalableType(Ty: AT->getElementType(), NVec&: NV, NPred&: NP, CoerceToSeq&: EltCoerceToSeq))
556 return false;
557
558 if (CoerceToSeq.size() + NElt * EltCoerceToSeq.size() > 12)
559 return false;
560
561 for (uint64_t I = 0; I < NElt; ++I)
562 llvm::append_range(C&: CoerceToSeq, R&: EltCoerceToSeq);
563
564 NVec += NElt * NV;
565 NPred += NElt * NP;
566 return true;
567 }
568
569 if (const auto *RT = dyn_cast<RecordType>(Val: Ty)) {
570 if (getRecordArgABI(RT) != RAA_Default)
571 return false;
572 // Pure scalable types are never unions and never contain unions.
573 if (RT->isUnion())
574 return false;
575
576 // A flexible array member is lowered as a zero-length array, which the
577 // field walk below skips. The member disqualifies a pure scalable type.
578 if (RT->hasFlexibleArrayMember())
579 return false;
580
581 // Direct virtual bases are not in getBaseClasses(). A record that has
582 // one cannot be passed in registers, and getRecordArgABI rejected it
583 // above.
584 for (const FieldInfo &Base : RT->getBaseClasses()) {
585 if (Base.FieldType->isEmptyRecord())
586 continue;
587 if (!passAsPureScalableType(Ty: Base.FieldType, NVec, NPred, CoerceToSeq))
588 return false;
589 }
590 for (const FieldInfo &Field : RT->getFields()) {
591 if (Field.isEmpty())
592 continue;
593 if (!passAsPureScalableType(Ty: Field.FieldType, NVec, NPred, CoerceToSeq))
594 return false;
595 }
596 return true;
597 }
598
599 if (const auto *TT = dyn_cast<TupleType>(Val: Ty)) {
600 const VectorType *VT = TT->getVectorType();
601 if (!VT->isScalable() || VT->isSVECount())
602 return false;
603
604 unsigned N = TT->getNumVectors();
605 if (CoerceToSeq.size() + N > 12)
606 return false;
607
608 bool IsPred = VT->isSVEPredicate();
609 if (!IsPred && !VT->isSVEData())
610 return false;
611 if (IsPred)
612 NPred += N;
613 else
614 NVec += N;
615
616 for (unsigned I = 0; I < N; ++I)
617 CoerceToSeq.push_back(Elt: VT);
618 return true;
619 }
620
621 if (const auto *VT = dyn_cast<VectorType>(Val: Ty)) {
622 const Type *Coerced = nullptr;
623 bool IsPred = false;
624 if (VT->isFixedLengthSVEPredicate()) {
625 IsPred = true;
626 Coerced = convertFixedToScalableVectorType(VT);
627 } else if (VT->isFixedLengthSVEData()) {
628 Coerced = convertFixedToScalableVectorType(VT);
629 } else if (VT->isScalable() && VT->isSVEPredicate()) {
630 IsPred = true;
631 Coerced = VT;
632 } else if (VT->isScalable() && VT->isSVEData()) {
633 Coerced = VT;
634 } else {
635 return false;
636 }
637
638 if (CoerceToSeq.size() + 1 > 12)
639 return false;
640
641 if (IsPred)
642 ++NPred;
643 else
644 ++NVec;
645 CoerceToSeq.push_back(Elt: Coerced);
646 return true;
647 }
648
649 return false;
650}
651
652bool AArch64TargetInfo::isHomogeneousAggregateBaseType(const Type *Ty) const {
653 // Soft-float ABI: no types are homogeneous aggregates.
654 if (isSoftFloat())
655 return false;
656
657 // Homogeneous aggregates for AAPCS64 must have base types of a floating
658 // point type or a short-vector type.
659 if (Ty->isFloat())
660 return true;
661
662 if (const auto *VT = dyn_cast<VectorType>(Val: Ty)) {
663 if (VT->isScalable() || VT->isSVEData() || VT->isSVEPredicate())
664 return false;
665
666 uint64_t VecSize = VT->getABISizeInBits();
667 if (VecSize == 64 || VecSize == 128)
668 return true;
669 }
670 return false;
671}
672
673bool AArch64TargetInfo::isHomogeneousAggregateSmallEnough(
674 const Type * /*Base*/, uint64_t Members) const {
675 return Members <= 4;
676}
677
678bool AArch64TargetInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate()
679 const {
680 // AAPCS64 applies homogeneity to the output of the data layout decision, so
681 // zero-length bitfields do not affect homogeneity.
682 return true;
683}
684
685bool AArch64TargetInfo::isPermittedToBeHomogeneousAggregate(
686 const RecordType *RT) const {
687 if (Opts.IsMicrosoftCXXABI && RT->isCXXRecord()) {
688 // This won't always return false, but we don't have enough information to
689 // perform the full check correctly yet.
690 reportNYI(Feature: "MicrosoftCXXABI homogeneous record classification");
691 return false;
692 }
693
694 return true;
695}
696
697} // namespace abi
698} // namespace llvm
699