LLVM 24.0.0git
AArch64.cpp
Go to the documentation of this file.
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
10#include "llvm/ABI/TargetInfo.h"
11#include "llvm/ABI/Types.h"
12#include "llvm/ADT/STLExtras.h"
19#include <algorithm>
20#include <cstdint>
21
22namespace llvm {
23namespace abi {
24
26public:
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 {
36 FI.getReturnInfo() =
37 classifyReturnType(FI.getReturnType(), 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(I.ABIType, FI.isVariadic(), IsNamedArg,
46 FI.getCallingConvention(), NSRN, NPRN);
47 }
48 }
49
50private:
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;
85 bool isPermittedToBeHomogeneousAggregate(const RecordType *RT) const override;
86};
87
88std::unique_ptr<TargetInfo>
90 return std::make_unique<AArch64TargetInfo>(TB, Opts);
91}
92
93static void reportNYI(StringRef Feature) {
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>(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)
113 }
114
115 if (!passAsAggregateType(RetTy)) {
116 if (const auto *IntTy = dyn_cast<IntegerType>(RetTy)) {
117 if (IntTy->isBitInt())
118 if (RetTy->getSizeInBits().getFixedValue() > 128)
120
121 if (isPromotableInteger(IntTy) && isDarwinPCS())
122 return ArgInfo::getExtend(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(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(RetTy, NVec, NPred, UnpaddedCoerceToSeq) &&
149 (NVec + NPred) > 0)
150 return coerceAndExpandPureScalableAggregate(
151 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 TB.getIntegerType(Size, llvm::Align(8), /*Signed=*/false));
167 }
168
169 uint64_t AlignBits = RetTy->getAlignment().value() * 8;
170 Size = llvm::alignTo(Size, 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(64, llvm::Align(8), /*Signed=*/false);
176 return ArgInfo::getDirect(TB.getArrayType(I64, Size / 64, Size));
177 }
178 return ArgInfo::getDirect(
179 TB.getIntegerType(Size, llvm::Align(8), /*Signed=*/false));
180 }
181
183}
184
185ArgInfo AArch64TargetInfo::classifyArgumentType(
186 const Type *Ty, bool IsVariadicFn, bool IsNamedArg,
187 unsigned CallingConvention, unsigned &NSRN, unsigned &NPRN) const {
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("Arm64EC variadic argument handling");
194 return ArgInfo::getIgnore();
195 }
196
197 // Handle illegal vector types here.
198 if (isIllegalVectorType(Ty))
199 return coerceIllegalVector(cast<VectorType>(Ty), NSRN, NPRN);
200
201 if (!passAsAggregateType(Ty)) {
202 if (const auto *IntTy = dyn_cast<IntegerType>(Ty)) {
203 if (IntTy->isBitInt())
204 if (Ty->getSizeInBits().getFixedValue() > 128)
206 /*ByVal=*/false);
207
208 if (isPromotableInteger(IntTy) && isDarwinPCS())
209 return ArgInfo::getExtend(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>(Ty)) {
217 if (VT->isSVEPredicate() || VT->isSVECount())
218 NPRN = std::min(NPRN + 1, 4u);
219 else
220 NSRN = std::min(NSRN + 1, 8u);
221 } else if (const auto *TT = dyn_cast<TupleType>(Ty)) {
222 if (TT->getVectorType()->isSVEPredicate())
223 NPRN = std::min(NPRN + TT->getNumVectors(), 4u);
224 else
225 NSRN = std::min(NSRN + TT->getNumVectors(), 8u);
226 } else if (Ty->isFloat()) {
227 NSRN = std::min(NSRN + 1, 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)) {
238 /*ByVal=*/RecordRAA ==
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 ||
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(NSRN + Members, uint64_t(8));
269 uint64_t BaseAllocSizeInBits = Base->getTypeAllocSize().getFixedValue() * 8;
270 const Type *CoerceTy =
271 TB.getArrayType(Base, Members, Members * BaseAllocSizeInBits);
272 if (Opts.Kind != AArch64ABIKind::AAPCS)
273 return ArgInfo::getDirect(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(CoerceTy, /*Offset=*/0, 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, NVec, NPred, 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 TB.getIntegerType(Size, 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(Ty->getAlignment().value() * 8, PointerWidth);
311 }
312 Size = llvm::alignTo(Size, 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(64, 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(AlignBits, llvm::Align(AlignBits / 8),
324 /*Signed=*/false);
325 }
326
327 if (Size == AlignBits)
328 return ArgInfo::getDirect(BaseTy);
329 return ArgInfo::getDirect(TB.getArrayType(BaseTy, Size / AlignBits, Size));
330 }
331
332 return getNaturalAlignIndirect(Ty, 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>(Ty);
344 if (!RT)
345 return false;
346
347 for (const FieldInfo &Base : RT->getBaseClasses())
348 if (!containsOnlyPointers(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>(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>(FT))
361 IsPlainPointer = PT->getSizeInBits().getFixedValue() == 64 &&
362 PT->getAddrSpace() == 0 &&
363 !PT->hasAddressSpaceQualifier();
364 if (!IsPlainPointer && !containsOnlyPointers(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>(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(Align(2),
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(EltTy, ElementCount::getScalable(128 / EltBits),
403 llvm::Align(16), 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(NPRN + 1, 4u);
417 return ArgInfo::getDirect(TB.getScalablePredicateOrCountVectorType(
419 }
420
421 if (VT->isFixedLengthSVEData()) {
422 NSRN = std::min(NSRN + 1, 8u);
423 return ArgInfo::getDirect(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(16, llvm::Align(2), /*Signed=*/false);
430 return ArgInfo::getDirect(ResType);
431 }
432 const Type *I32 = TB.getIntegerType(32, llvm::Align(4), /*Signed=*/false);
433 if (Size <= 32)
434 return ArgInfo::getDirect(I32);
435 if (Size == 64) {
436 NSRN = std::min(NSRN + 1, 8u);
437 return ArgInfo::getDirect(
438 TB.getVectorType(I32, ElementCount::getFixed(2), llvm::Align(8)));
439 }
440 if (Size == 128) {
441 NSRN = std::min(NSRN + 1, 8u);
442 return ArgInfo::getDirect(
443 TB.getVectorType(I32, ElementCount::getFixed(4), llvm::Align(16)));
444 }
445
446 return getNaturalAlignIndirect(VT, getAllocaAddrSpace(), /*ByVal=*/false);
447}
448
449bool AArch64TargetInfo::isIllegalVectorType(const Type *Ty) const {
450 if (const auto *VT = dyn_cast<VectorType>(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(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 {
484 Flattened.push_back(Ty);
485 return;
486 }
487
488 if (const auto *AT = dyn_cast<ArrayType>(Ty)) {
489 uint64_t NElt = AT->getNumElements();
490 if (NElt == 0)
491 return;
492
493 SmallVector<const Type *, 4> EltFlattened;
494 flattenType(AT->getElementType(), EltFlattened);
495
496 for (uint64_t I = 0; I < NElt; ++I)
497 llvm::append_range(Flattened, EltFlattened);
498 return;
499 }
500
501 if (const auto *RT = dyn_cast<RecordType>(Ty)) {
502 for (const FieldInfo &Field : RT->getFields())
503 flattenType(Field.FieldType, Flattened);
504 return;
505 }
506
507 Flattened.push_back(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, 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(UnpaddedCoerceToSeq, /*Packed=*/true);
531
533 flattenType(convertTypeForMem(Ty), CoerceToSeq);
535 getStructOfTypes(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>(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(AT->getElementType(), NV, NP, 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(CoerceToSeq, EltCoerceToSeq);
563
564 NVec += NElt * NV;
565 NPred += NElt * NP;
566 return true;
567 }
568
569 if (const auto *RT = dyn_cast<RecordType>(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(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(Field.FieldType, NVec, NPred, CoerceToSeq))
594 return false;
595 }
596 return true;
597 }
598
599 if (const auto *TT = dyn_cast<TupleType>(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(VT);
618 return true;
619 }
620
621 if (const auto *VT = dyn_cast<VectorType>(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(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>(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
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("MicrosoftCXXABI homogeneous record classification");
691 return false;
692 }
693
694 return true;
695}
696
697} // namespace abi
698} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
#define I(x, y, z)
Definition MD5.cpp:57
OptimizedStructLayoutField Field
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
FunctionLoweringInfo::StatepointRelocationRecord RecordType
Target-specific ABI information and factory functions.
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:309
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:306
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
Definition WithColor.cpp:86
AArch64TargetInfo(TypeBuilder &TB, const AArch64ABIOptions &Opts)
Definition AArch64.cpp:27
void computeInfo(FunctionInfo &FI) const override
Populate FI with the target's ABI-lowering decisions for each argument and return value.
Definition AArch64.cpp:34
const ABICompatInfo & getABICompatInfo() const override
Return this target's ABI compatibility flags.
Definition AArch64.cpp:30
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
const Type * getReturnType() const
virtual unsigned getAllocaAddrSpace() const
Address space in which indirect arguments are allocated (the target's alloca/stack space).
Definition TargetInfo.h:85
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...
Definition TargetInfo.h:157
TargetInfo(TypeBuilder &Builder)
Definition TargetInfo.h:70
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
TypeBuilder & TB
Definition TargetInfo.h:67
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.
Definition Types.h:471
Represents the ABI-specific view of a type in LLVM.
Definition Types.h:47
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)
Definition AArch64.cpp:93
@ SVEPredicate
An AArch64 SVE predicate vector, such as svbool_t.
Definition Types.h:292
@ SVEData
An AArch64 SVE data vector, such as svint32_t.
Definition Types.h:285
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
Definition TargetInfo.h:34
@ RAA_Default
Pass it using the normal C aggregate rules for the ABI, potentially introducing extra copies and pass...
Definition TargetInfo.h:29
LLVM_ABI std::unique_ptr< TargetInfo > createAArch64TargetInfo(TypeBuilder &TB, const AArch64ABIOptions &Opts)
Definition AArch64.cpp:89
CallingConvention
Definition Dwarf.h:851
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.
Definition Casting.h:643
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
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...
Definition Casting.h:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
#define N
Helper struct shared between Function Specialization and SCCP Solver.
Definition SCCPSolver.h:42
Target / language flags that affect AArch64 ABI classification.
Definition TargetInfo.h:201
Flags controlling ABI compatibility behaviour that applies to every target.
Definition TargetInfo.h:43