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"
16#include <algorithm>
17#include <cstdint>
18
19namespace llvm {
20namespace abi {
21
23public:
25 : TargetInfo(TB), Opts(Opts) {}
26
27 const ABICompatInfo &getABICompatInfo() const override {
28 return Opts.CompatInfo;
29 }
30
31 void computeInfo(FunctionInfo &FI) const override {
33 FI.getReturnInfo() =
34 classifyReturnType(FI.getReturnType(), FI.isVariadic());
35
36 unsigned ArgNo = 0;
37 unsigned NSRN = 0, NPRN = 0;
38 for (auto &I : FI.arguments()) {
39 const bool IsNamedArg =
40 !FI.isVariadic() || ArgNo < FI.getNumRequiredArgs();
41 ++ArgNo;
42 I.Info = classifyArgumentType(I.ABIType, FI.isVariadic(), IsNamedArg,
43 FI.getCallingConvention(), NSRN, NPRN);
44 }
45 }
46
47private:
49
50 ArgInfo classifyReturnType(const Type *RetTy, bool IsVariadicFn) const;
51 ArgInfo classifyArgumentType(const Type *Ty, bool IsVariadicFn,
52 bool IsNamedArg, unsigned CallingConvention,
53 unsigned &NSRN, unsigned &NPRN) const;
54
55 bool isDarwinPCS() const { return Opts.Kind == AArch64ABIKind::DarwinPCS; }
56 bool isSoftFloat() const { return Opts.Kind == AArch64ABIKind::AAPCSSoft; }
57 bool passAsAggregateType(const Type *Ty) const;
58
59 bool isHomogeneousAggregateBaseType(const Type *Ty) const override;
60 bool isHomogeneousAggregateSmallEnough(const Type *Base,
61 uint64_t Members) const override;
63 bool isPermittedToBeHomogeneousAggregate(const RecordType *RT) const override;
64};
65
66std::unique_ptr<TargetInfo>
68 return std::make_unique<AArch64TargetInfo>(TB, Opts);
69}
70
71static void reportNYI(StringRef Feature) {
73 << Feature
74 << " is not yet implemented for AArch64 in the LLVM ABI library.\n";
75}
76
77ArgInfo AArch64TargetInfo::classifyReturnType(const Type *RetTy,
78 bool IsVariadicFn) const {
79 if (RetTy->isVoid())
80 return ArgInfo::getIgnore();
81
82 if (RetTy->isVector()) {
83 reportNYI("Vector return type handling");
84 return ArgInfo::getIgnore();
85 }
86
87 if (!passAsAggregateType(RetTy)) {
88 if (const auto *IntTy = dyn_cast<IntegerType>(RetTy)) {
89 if (IntTy->isBitInt())
90 if (RetTy->getSizeInBits().getFixedValue() > 128)
91 return getNaturalAlignIndirect(RetTy);
92
93 if (isPromotableInteger(IntTy) && isDarwinPCS())
94 return ArgInfo::getExtend(IntTy);
95 }
96
97 // Everything not handled above is returned directly.
98 return ArgInfo::getDirect();
99 }
100
101 // TODO: Handle empty records and zero-size non-SVE types.
102
103 const Type *Base = nullptr;
104 uint64_t Members = 0;
105 if (isHomogeneousAggregate(RetTy, Base, Members) &&
106 !(Opts.IsILP32 && IsVariadicFn)) {
107 // Homogeneous Floating-point Aggregates (HFAs) are returned directly.
108 return ArgInfo::getDirect();
109 }
110
111 reportNYI("Aggregate return type handling");
112 return ArgInfo::getIgnore();
113}
114
115ArgInfo AArch64TargetInfo::classifyArgumentType(
116 const Type *Ty, bool IsVariadicFn, bool IsNamedArg,
117 unsigned CallingConvention, unsigned &NSRN, unsigned &NPRN) const {
119
120 if (Ty->isVector()) {
121 reportNYI("Vector argument type handling");
122 return ArgInfo::getIgnore();
123 }
124
125 if (!passAsAggregateType(Ty)) {
126 if (const auto *IntTy = dyn_cast<IntegerType>(Ty)) {
127 if (IntTy->isBitInt())
128 if (Ty->getSizeInBits().getFixedValue() > 128)
129 return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
130
131 if (isPromotableInteger(IntTy) && isDarwinPCS())
132 return ArgInfo::getExtend(IntTy);
133 }
134
135 // TODO: Legal vector types will update NSRN or NPRN.
136
137 if (Ty->isFloat())
138 NSRN = std::min(NSRN + 1, 8u);
139
140 // Everything not handled above is returned directly.
141 return ArgInfo::getDirect();
142 }
143
144 // Structures with either a non-trivial destructor or a non-trivial
145 // copy constructor are always indirect.
146 if (auto RecordRAA = getRecordArgABI(Ty)) {
147 return getNaturalAlignIndirect(Ty, RecordRAA ==
149 }
150
151 TypeSize TySize = Ty->getSizeInBits();
152 uint64_t Size = TySize.isFixed() ? TySize.getFixedValue() : 0;
153 const auto *RT = dyn_cast<RecordType>(Ty);
154 if (!Ty->isSVESizelessType() && ((RT && RT->isEmpty()) || Size == 0)) {
155 reportNYI("Empty record argument handling");
156 return ArgInfo::getIgnore();
157 }
158
159 // Homogeneous Floating-point Aggregates (HFAs) need to be expanded.
160 const Type *Base = nullptr;
161 uint64_t Members = 0;
162 bool IsWin64 = Opts.Kind == AArch64ABIKind::Win64 ||
164 bool IsWinVariadic = IsWin64 && IsVariadicFn;
165 // In variadic functions on Windows, all composite types are treated alike,
166 // no special handling of HFAs/HVAs.
167 if (!IsWinVariadic && isHomogeneousAggregate(Ty, Base, Members)) {
168 NSRN = std::min(NSRN + Members, uint64_t(8));
169 uint64_t BaseAllocSizeInBits = Base->getTypeAllocSize().getFixedValue() * 8;
170 const Type *CoerceTy =
171 TB.getArrayType(Base, Members, Members * BaseAllocSizeInBits);
172 if (Opts.Kind != AArch64ABIKind::AAPCS)
173 return ArgInfo::getDirect(CoerceTy);
174
175 // For HFAs/HVAs, cap the argument alignment to 16, otherwise
176 // set it to 8 according to the AAPCS64 document.
177 unsigned TyAlign = Ty->getUnadjustedAlignment().value();
178 TyAlign = (TyAlign >= 16) ? 16 : 8;
179 return ArgInfo::getDirect(CoerceTy, /*Offset=*/0, llvm::Align(TyAlign));
180 }
181
182 reportNYI("Aggregate argument type handling");
183 return ArgInfo::getIgnore();
184}
185
186bool AArch64TargetInfo::passAsAggregateType(const Type *Ty) const {
187 // TODO: Handle SVE types. For now, they don't get through the type mapper.
188 return isAggregateTypeForABI(Ty);
189}
190
191bool AArch64TargetInfo::isHomogeneousAggregateBaseType(const Type *Ty) const {
192 // Soft-float ABI: no types are homogeneous aggregates.
193 if (isSoftFloat())
194 return false;
195
196 // Homogeneous aggregates for AAPCS64 must have base types of a floating
197 // point type or a short-vector type.
198 if (Ty->isFloat())
199 return true;
200
201 if (const auto *VT = dyn_cast<VectorType>(Ty)) {
202 if (VT->isScalable() || VT->isSVEData() || VT->isSVEPredicate())
203 return false;
204
205 // Clang's getTypeSize for non-power-of-2 vectors rounds the width up to
206 // the next power-of-2 alignment (e.g. 3 x float is 96 bits of payload but
207 // 128 bits of ABI size), so those vectors are short-vector HVA bases.
209 bit_ceil(std::max<uint64_t>(8, VT->getSizeInBits().getFixedValue()));
210 if (VecSize == 64 || VecSize == 128)
211 return true;
212 }
213 return false;
214}
215
216bool AArch64TargetInfo::isHomogeneousAggregateSmallEnough(
217 const Type * /*Base*/, uint64_t Members) const {
218 return Members <= 4;
219}
220
222 const {
223 // AAPCS64 applies homogeneity to the output of the data layout decision, so
224 // zero-length bitfields do not affect homogeneity.
225 return true;
226}
227
228bool AArch64TargetInfo::isPermittedToBeHomogeneousAggregate(
229 const RecordType *RT) const {
230 if (Opts.IsMicrosoftCXXABI && RT->isCXXRecord()) {
231 // This won't always return false, but we don't have enough information to
232 // perform the full check correctly yet.
233 reportNYI("MicrosoftCXXABI homogeneous record classification");
234 return false;
235 }
236
237 return true;
238}
239
240} // namespace abi
241} // namespace llvm
unsigned uint64_t
#define I(x, y, z)
Definition MD5.cpp:57
FunctionLoweringInfo::StatepointRelocationRecord RecordType
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
Target-specific ABI information and factory functions.
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:24
void computeInfo(FunctionInfo &FI) const override
Populate FI with the target's ABI-lowering decisions for each argument and return value.
Definition AArch64.cpp:31
const ABICompatInfo & getABICompatInfo() const override
Return this target's ABI compatibility flags.
Definition AArch64.cpp:27
Helper class to encapsulate information about how a specific type should be passed to or returned fro...
static ArgInfo getIgnore()
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
LLVM_ABI ArgInfo getNaturalAlignIndirect(const Type *Ty, bool ByVal=true) const
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:112
TargetInfo(TypeBuilder &Builder)
Definition TargetInfo.h:70
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 RecordArgABI getRecordArgABI(const RecordType *RT) const
TypeBuilder manages the lifecycle of ABI types using bump pointer allocation.
Definition Types.h:434
Represents the ABI-specific view of a type in LLVM.
Definition Types.h:46
This file defines the type system for the LLVMABI library, which mirrors ABI-relevant aspects of fron...
@ Win64
The C convention as implemented on Windows/x86-64 and AArch64.
static void reportNYI(StringRef Feature)
Definition AArch64.cpp:71
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
Definition TargetInfo.h:34
LLVM_ABI std::unique_ptr< TargetInfo > createAArch64TargetInfo(TypeBuilder &TB, const AArch64ABIOptions &Opts)
Definition AArch64.cpp:67
CallingConvention
Definition Dwarf.h:843
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
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
Definition bit.h:362
Helper struct shared between Function Specialization and SCCP Solver.
Definition SCCPSolver.h:42
Target / language flags that affect AArch64 ABI classification.
Definition TargetInfo.h:152
Flags controlling ABI compatibility behaviour that applies to every target.
Definition TargetInfo.h:43