/src/llvm-project/clang/lib/CodeGen/Targets/AArch64.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- AArch64.cpp --------------------------------------------------------===// |
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 "ABIInfoImpl.h" |
10 | | #include "TargetInfo.h" |
11 | | |
12 | | using namespace clang; |
13 | | using namespace clang::CodeGen; |
14 | | |
15 | | //===----------------------------------------------------------------------===// |
16 | | // AArch64 ABI Implementation |
17 | | //===----------------------------------------------------------------------===// |
18 | | |
19 | | namespace { |
20 | | |
21 | | class AArch64ABIInfo : public ABIInfo { |
22 | | AArch64ABIKind Kind; |
23 | | |
24 | | public: |
25 | | AArch64ABIInfo(CodeGenTypes &CGT, AArch64ABIKind Kind) |
26 | 0 | : ABIInfo(CGT), Kind(Kind) {} |
27 | | |
28 | | private: |
29 | 0 | AArch64ABIKind getABIKind() const { return Kind; } |
30 | 0 | bool isDarwinPCS() const { return Kind == AArch64ABIKind::DarwinPCS; } |
31 | | |
32 | | ABIArgInfo classifyReturnType(QualType RetTy, bool IsVariadic) const; |
33 | | ABIArgInfo classifyArgumentType(QualType RetTy, bool IsVariadic, |
34 | | unsigned CallingConvention) const; |
35 | | ABIArgInfo coerceIllegalVector(QualType Ty) const; |
36 | | bool isHomogeneousAggregateBaseType(QualType Ty) const override; |
37 | | bool isHomogeneousAggregateSmallEnough(const Type *Ty, |
38 | | uint64_t Members) const override; |
39 | | bool isZeroLengthBitfieldPermittedInHomogeneousAggregate() const override; |
40 | | |
41 | | bool isIllegalVectorType(QualType Ty) const; |
42 | | |
43 | 0 | void computeInfo(CGFunctionInfo &FI) const override { |
44 | 0 | if (!::classifyReturnType(getCXXABI(), FI, *this)) |
45 | 0 | FI.getReturnInfo() = |
46 | 0 | classifyReturnType(FI.getReturnType(), FI.isVariadic()); |
47 | |
|
48 | 0 | for (auto &it : FI.arguments()) |
49 | 0 | it.info = classifyArgumentType(it.type, FI.isVariadic(), |
50 | 0 | FI.getCallingConvention()); |
51 | 0 | } |
52 | | |
53 | | Address EmitDarwinVAArg(Address VAListAddr, QualType Ty, |
54 | | CodeGenFunction &CGF) const; |
55 | | |
56 | | Address EmitAAPCSVAArg(Address VAListAddr, QualType Ty, |
57 | | CodeGenFunction &CGF) const; |
58 | | |
59 | | Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, |
60 | 0 | QualType Ty) const override { |
61 | 0 | llvm::Type *BaseTy = CGF.ConvertType(Ty); |
62 | 0 | if (isa<llvm::ScalableVectorType>(BaseTy)) |
63 | 0 | llvm::report_fatal_error("Passing SVE types to variadic functions is " |
64 | 0 | "currently not supported"); |
65 | |
|
66 | 0 | return Kind == AArch64ABIKind::Win64 ? EmitMSVAArg(CGF, VAListAddr, Ty) |
67 | 0 | : isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF) |
68 | 0 | : EmitAAPCSVAArg(VAListAddr, Ty, CGF); |
69 | 0 | } |
70 | | |
71 | | Address EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, |
72 | | QualType Ty) const override; |
73 | | |
74 | 0 | bool allowBFloatArgsAndRet() const override { |
75 | 0 | return getTarget().hasBFloat16Type(); |
76 | 0 | } |
77 | | }; |
78 | | |
79 | | class AArch64SwiftABIInfo : public SwiftABIInfo { |
80 | | public: |
81 | | explicit AArch64SwiftABIInfo(CodeGenTypes &CGT) |
82 | 0 | : SwiftABIInfo(CGT, /*SwiftErrorInRegister=*/true) {} |
83 | | |
84 | | bool isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy, |
85 | | unsigned NumElts) const override; |
86 | | }; |
87 | | |
88 | | class AArch64TargetCodeGenInfo : public TargetCodeGenInfo { |
89 | | public: |
90 | | AArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIKind Kind) |
91 | 0 | : TargetCodeGenInfo(std::make_unique<AArch64ABIInfo>(CGT, Kind)) { |
92 | 0 | SwiftInfo = std::make_unique<AArch64SwiftABIInfo>(CGT); |
93 | 0 | } |
94 | | |
95 | 0 | StringRef getARCRetainAutoreleasedReturnValueMarker() const override { |
96 | 0 | return "mov\tfp, fp\t\t// marker for objc_retainAutoreleaseReturnValue"; |
97 | 0 | } |
98 | | |
99 | 0 | int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { |
100 | 0 | return 31; |
101 | 0 | } |
102 | | |
103 | 0 | bool doesReturnSlotInterfereWithArgs() const override { return false; } |
104 | | |
105 | | void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, |
106 | 0 | CodeGen::CodeGenModule &CGM) const override { |
107 | 0 | const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); |
108 | 0 | if (!FD) |
109 | 0 | return; |
110 | | |
111 | 0 | const auto *TA = FD->getAttr<TargetAttr>(); |
112 | 0 | if (TA == nullptr) |
113 | 0 | return; |
114 | | |
115 | 0 | ParsedTargetAttr Attr = |
116 | 0 | CGM.getTarget().parseTargetAttr(TA->getFeaturesStr()); |
117 | 0 | if (Attr.BranchProtection.empty()) |
118 | 0 | return; |
119 | | |
120 | 0 | TargetInfo::BranchProtectionInfo BPI; |
121 | 0 | StringRef Error; |
122 | 0 | (void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection, |
123 | 0 | Attr.CPU, BPI, Error); |
124 | 0 | assert(Error.empty()); |
125 | | |
126 | 0 | auto *Fn = cast<llvm::Function>(GV); |
127 | 0 | static const char *SignReturnAddrStr[] = {"none", "non-leaf", "all"}; |
128 | 0 | Fn->addFnAttr("sign-return-address", SignReturnAddrStr[static_cast<int>(BPI.SignReturnAddr)]); |
129 | |
|
130 | 0 | if (BPI.SignReturnAddr != LangOptions::SignReturnAddressScopeKind::None) { |
131 | 0 | Fn->addFnAttr("sign-return-address-key", |
132 | 0 | BPI.SignKey == LangOptions::SignReturnAddressKeyKind::AKey |
133 | 0 | ? "a_key" |
134 | 0 | : "b_key"); |
135 | 0 | } |
136 | |
|
137 | 0 | Fn->addFnAttr("branch-target-enforcement", |
138 | 0 | BPI.BranchTargetEnforcement ? "true" : "false"); |
139 | 0 | Fn->addFnAttr("branch-protection-pauth-lr", |
140 | 0 | BPI.BranchProtectionPAuthLR ? "true" : "false"); |
141 | 0 | Fn->addFnAttr("guarded-control-stack", |
142 | 0 | BPI.GuardedControlStack ? "true" : "false"); |
143 | 0 | } |
144 | | |
145 | | bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF, |
146 | 0 | llvm::Type *Ty) const override { |
147 | 0 | if (CGF.getTarget().hasFeature("ls64")) { |
148 | 0 | auto *ST = dyn_cast<llvm::StructType>(Ty); |
149 | 0 | if (ST && ST->getNumElements() == 1) { |
150 | 0 | auto *AT = dyn_cast<llvm::ArrayType>(ST->getElementType(0)); |
151 | 0 | if (AT && AT->getNumElements() == 8 && |
152 | 0 | AT->getElementType()->isIntegerTy(64)) |
153 | 0 | return true; |
154 | 0 | } |
155 | 0 | } |
156 | 0 | return TargetCodeGenInfo::isScalarizableAsmOperand(CGF, Ty); |
157 | 0 | } |
158 | | }; |
159 | | |
160 | | class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo { |
161 | | public: |
162 | | WindowsAArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIKind K) |
163 | 0 | : AArch64TargetCodeGenInfo(CGT, K) {} |
164 | | |
165 | | void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, |
166 | | CodeGen::CodeGenModule &CGM) const override; |
167 | | |
168 | | void getDependentLibraryOption(llvm::StringRef Lib, |
169 | 0 | llvm::SmallString<24> &Opt) const override { |
170 | 0 | Opt = "/DEFAULTLIB:" + qualifyWindowsLibrary(Lib); |
171 | 0 | } |
172 | | |
173 | | void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef Value, |
174 | 0 | llvm::SmallString<32> &Opt) const override { |
175 | 0 | Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\""; |
176 | 0 | } |
177 | | }; |
178 | | |
179 | | void WindowsAArch64TargetCodeGenInfo::setTargetAttributes( |
180 | 0 | const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { |
181 | 0 | AArch64TargetCodeGenInfo::setTargetAttributes(D, GV, CGM); |
182 | 0 | if (GV->isDeclaration()) |
183 | 0 | return; |
184 | 0 | addStackProbeTargetAttributes(D, GV, CGM); |
185 | 0 | } |
186 | | } |
187 | | |
188 | 0 | ABIArgInfo AArch64ABIInfo::coerceIllegalVector(QualType Ty) const { |
189 | 0 | assert(Ty->isVectorType() && "expected vector type!"); |
190 | | |
191 | 0 | const auto *VT = Ty->castAs<VectorType>(); |
192 | 0 | if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate) { |
193 | 0 | assert(VT->getElementType()->isBuiltinType() && "expected builtin type!"); |
194 | 0 | assert(VT->getElementType()->castAs<BuiltinType>()->getKind() == |
195 | 0 | BuiltinType::UChar && |
196 | 0 | "unexpected builtin type for SVE predicate!"); |
197 | 0 | return ABIArgInfo::getDirect(llvm::ScalableVectorType::get( |
198 | 0 | llvm::Type::getInt1Ty(getVMContext()), 16)); |
199 | 0 | } |
200 | | |
201 | 0 | if (VT->getVectorKind() == VectorKind::SveFixedLengthData) { |
202 | 0 | assert(VT->getElementType()->isBuiltinType() && "expected builtin type!"); |
203 | | |
204 | 0 | const auto *BT = VT->getElementType()->castAs<BuiltinType>(); |
205 | 0 | llvm::ScalableVectorType *ResType = nullptr; |
206 | 0 | switch (BT->getKind()) { |
207 | 0 | default: |
208 | 0 | llvm_unreachable("unexpected builtin type for SVE vector!"); |
209 | 0 | case BuiltinType::SChar: |
210 | 0 | case BuiltinType::UChar: |
211 | 0 | ResType = llvm::ScalableVectorType::get( |
212 | 0 | llvm::Type::getInt8Ty(getVMContext()), 16); |
213 | 0 | break; |
214 | 0 | case BuiltinType::Short: |
215 | 0 | case BuiltinType::UShort: |
216 | 0 | ResType = llvm::ScalableVectorType::get( |
217 | 0 | llvm::Type::getInt16Ty(getVMContext()), 8); |
218 | 0 | break; |
219 | 0 | case BuiltinType::Int: |
220 | 0 | case BuiltinType::UInt: |
221 | 0 | ResType = llvm::ScalableVectorType::get( |
222 | 0 | llvm::Type::getInt32Ty(getVMContext()), 4); |
223 | 0 | break; |
224 | 0 | case BuiltinType::Long: |
225 | 0 | case BuiltinType::ULong: |
226 | 0 | ResType = llvm::ScalableVectorType::get( |
227 | 0 | llvm::Type::getInt64Ty(getVMContext()), 2); |
228 | 0 | break; |
229 | 0 | case BuiltinType::Half: |
230 | 0 | ResType = llvm::ScalableVectorType::get( |
231 | 0 | llvm::Type::getHalfTy(getVMContext()), 8); |
232 | 0 | break; |
233 | 0 | case BuiltinType::Float: |
234 | 0 | ResType = llvm::ScalableVectorType::get( |
235 | 0 | llvm::Type::getFloatTy(getVMContext()), 4); |
236 | 0 | break; |
237 | 0 | case BuiltinType::Double: |
238 | 0 | ResType = llvm::ScalableVectorType::get( |
239 | 0 | llvm::Type::getDoubleTy(getVMContext()), 2); |
240 | 0 | break; |
241 | 0 | case BuiltinType::BFloat16: |
242 | 0 | ResType = llvm::ScalableVectorType::get( |
243 | 0 | llvm::Type::getBFloatTy(getVMContext()), 8); |
244 | 0 | break; |
245 | 0 | } |
246 | 0 | return ABIArgInfo::getDirect(ResType); |
247 | 0 | } |
248 | | |
249 | 0 | uint64_t Size = getContext().getTypeSize(Ty); |
250 | | // Android promotes <2 x i8> to i16, not i32 |
251 | 0 | if ((isAndroid() || isOHOSFamily()) && (Size <= 16)) { |
252 | 0 | llvm::Type *ResType = llvm::Type::getInt16Ty(getVMContext()); |
253 | 0 | return ABIArgInfo::getDirect(ResType); |
254 | 0 | } |
255 | 0 | if (Size <= 32) { |
256 | 0 | llvm::Type *ResType = llvm::Type::getInt32Ty(getVMContext()); |
257 | 0 | return ABIArgInfo::getDirect(ResType); |
258 | 0 | } |
259 | 0 | if (Size == 64) { |
260 | 0 | auto *ResType = |
261 | 0 | llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 2); |
262 | 0 | return ABIArgInfo::getDirect(ResType); |
263 | 0 | } |
264 | 0 | if (Size == 128) { |
265 | 0 | auto *ResType = |
266 | 0 | llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 4); |
267 | 0 | return ABIArgInfo::getDirect(ResType); |
268 | 0 | } |
269 | 0 | return getNaturalAlignIndirect(Ty, /*ByVal=*/false); |
270 | 0 | } |
271 | | |
272 | | ABIArgInfo |
273 | | AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadic, |
274 | 0 | unsigned CallingConvention) const { |
275 | 0 | Ty = useFirstFieldIfTransparentUnion(Ty); |
276 | | |
277 | | // Handle illegal vector types here. |
278 | 0 | if (isIllegalVectorType(Ty)) |
279 | 0 | return coerceIllegalVector(Ty); |
280 | | |
281 | 0 | if (!isAggregateTypeForABI(Ty)) { |
282 | | // Treat an enum type as its underlying type. |
283 | 0 | if (const EnumType *EnumTy = Ty->getAs<EnumType>()) |
284 | 0 | Ty = EnumTy->getDecl()->getIntegerType(); |
285 | |
|
286 | 0 | if (const auto *EIT = Ty->getAs<BitIntType>()) |
287 | 0 | if (EIT->getNumBits() > 128) |
288 | 0 | return getNaturalAlignIndirect(Ty); |
289 | | |
290 | 0 | return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS() |
291 | 0 | ? ABIArgInfo::getExtend(Ty) |
292 | 0 | : ABIArgInfo::getDirect()); |
293 | 0 | } |
294 | | |
295 | | // Structures with either a non-trivial destructor or a non-trivial |
296 | | // copy constructor are always indirect. |
297 | 0 | if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { |
298 | 0 | return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA == |
299 | 0 | CGCXXABI::RAA_DirectInMemory); |
300 | 0 | } |
301 | | |
302 | | // Empty records are always ignored on Darwin, but actually passed in C++ mode |
303 | | // elsewhere for GNU compatibility. |
304 | 0 | uint64_t Size = getContext().getTypeSize(Ty); |
305 | 0 | bool IsEmpty = isEmptyRecord(getContext(), Ty, true); |
306 | 0 | if (IsEmpty || Size == 0) { |
307 | 0 | if (!getContext().getLangOpts().CPlusPlus || isDarwinPCS()) |
308 | 0 | return ABIArgInfo::getIgnore(); |
309 | | |
310 | | // GNU C mode. The only argument that gets ignored is an empty one with size |
311 | | // 0. |
312 | 0 | if (IsEmpty && Size == 0) |
313 | 0 | return ABIArgInfo::getIgnore(); |
314 | 0 | return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); |
315 | 0 | } |
316 | | |
317 | | // Homogeneous Floating-point Aggregates (HFAs) need to be expanded. |
318 | 0 | const Type *Base = nullptr; |
319 | 0 | uint64_t Members = 0; |
320 | 0 | bool IsWin64 = Kind == AArch64ABIKind::Win64 || |
321 | 0 | CallingConvention == llvm::CallingConv::Win64; |
322 | 0 | bool IsWinVariadic = IsWin64 && IsVariadic; |
323 | | // In variadic functions on Windows, all composite types are treated alike, |
324 | | // no special handling of HFAs/HVAs. |
325 | 0 | if (!IsWinVariadic && isHomogeneousAggregate(Ty, Base, Members)) { |
326 | 0 | if (Kind != AArch64ABIKind::AAPCS) |
327 | 0 | return ABIArgInfo::getDirect( |
328 | 0 | llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members)); |
329 | | |
330 | | // For HFAs/HVAs, cap the argument alignment to 16, otherwise |
331 | | // set it to 8 according to the AAPCS64 document. |
332 | 0 | unsigned Align = |
333 | 0 | getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity(); |
334 | 0 | Align = (Align >= 16) ? 16 : 8; |
335 | 0 | return ABIArgInfo::getDirect( |
336 | 0 | llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members), 0, |
337 | 0 | nullptr, true, Align); |
338 | 0 | } |
339 | | |
340 | | // Aggregates <= 16 bytes are passed directly in registers or on the stack. |
341 | 0 | if (Size <= 128) { |
342 | | // On RenderScript, coerce Aggregates <= 16 bytes to an integer array of |
343 | | // same size and alignment. |
344 | 0 | if (getTarget().isRenderScriptTarget()) { |
345 | 0 | return coerceToIntArray(Ty, getContext(), getVMContext()); |
346 | 0 | } |
347 | 0 | unsigned Alignment; |
348 | 0 | if (Kind == AArch64ABIKind::AAPCS) { |
349 | 0 | Alignment = getContext().getTypeUnadjustedAlign(Ty); |
350 | 0 | Alignment = Alignment < 128 ? 64 : 128; |
351 | 0 | } else { |
352 | 0 | Alignment = |
353 | 0 | std::max(getContext().getTypeAlign(Ty), |
354 | 0 | (unsigned)getTarget().getPointerWidth(LangAS::Default)); |
355 | 0 | } |
356 | 0 | Size = llvm::alignTo(Size, Alignment); |
357 | | |
358 | | // We use a pair of i64 for 16-byte aggregate with 8-byte alignment. |
359 | | // For aggregates with 16-byte alignment, we use i128. |
360 | 0 | llvm::Type *BaseTy = llvm::Type::getIntNTy(getVMContext(), Alignment); |
361 | 0 | return ABIArgInfo::getDirect( |
362 | 0 | Size == Alignment ? BaseTy |
363 | 0 | : llvm::ArrayType::get(BaseTy, Size / Alignment)); |
364 | 0 | } |
365 | | |
366 | 0 | return getNaturalAlignIndirect(Ty, /*ByVal=*/false); |
367 | 0 | } |
368 | | |
369 | | ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy, |
370 | 0 | bool IsVariadic) const { |
371 | 0 | if (RetTy->isVoidType()) |
372 | 0 | return ABIArgInfo::getIgnore(); |
373 | | |
374 | 0 | if (const auto *VT = RetTy->getAs<VectorType>()) { |
375 | 0 | if (VT->getVectorKind() == VectorKind::SveFixedLengthData || |
376 | 0 | VT->getVectorKind() == VectorKind::SveFixedLengthPredicate) |
377 | 0 | return coerceIllegalVector(RetTy); |
378 | 0 | } |
379 | | |
380 | | // Large vector types should be returned via memory. |
381 | 0 | if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 128) |
382 | 0 | return getNaturalAlignIndirect(RetTy); |
383 | | |
384 | 0 | if (!isAggregateTypeForABI(RetTy)) { |
385 | | // Treat an enum type as its underlying type. |
386 | 0 | if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) |
387 | 0 | RetTy = EnumTy->getDecl()->getIntegerType(); |
388 | |
|
389 | 0 | if (const auto *EIT = RetTy->getAs<BitIntType>()) |
390 | 0 | if (EIT->getNumBits() > 128) |
391 | 0 | return getNaturalAlignIndirect(RetTy); |
392 | | |
393 | 0 | return (isPromotableIntegerTypeForABI(RetTy) && isDarwinPCS() |
394 | 0 | ? ABIArgInfo::getExtend(RetTy) |
395 | 0 | : ABIArgInfo::getDirect()); |
396 | 0 | } |
397 | | |
398 | 0 | uint64_t Size = getContext().getTypeSize(RetTy); |
399 | 0 | if (isEmptyRecord(getContext(), RetTy, true) || Size == 0) |
400 | 0 | return ABIArgInfo::getIgnore(); |
401 | | |
402 | 0 | const Type *Base = nullptr; |
403 | 0 | uint64_t Members = 0; |
404 | 0 | if (isHomogeneousAggregate(RetTy, Base, Members) && |
405 | 0 | !(getTarget().getTriple().getArch() == llvm::Triple::aarch64_32 && |
406 | 0 | IsVariadic)) |
407 | | // Homogeneous Floating-point Aggregates (HFAs) are returned directly. |
408 | 0 | return ABIArgInfo::getDirect(); |
409 | | |
410 | | // Aggregates <= 16 bytes are returned directly in registers or on the stack. |
411 | 0 | if (Size <= 128) { |
412 | | // On RenderScript, coerce Aggregates <= 16 bytes to an integer array of |
413 | | // same size and alignment. |
414 | 0 | if (getTarget().isRenderScriptTarget()) { |
415 | 0 | return coerceToIntArray(RetTy, getContext(), getVMContext()); |
416 | 0 | } |
417 | | |
418 | 0 | if (Size <= 64 && getDataLayout().isLittleEndian()) { |
419 | | // Composite types are returned in lower bits of a 64-bit register for LE, |
420 | | // and in higher bits for BE. However, integer types are always returned |
421 | | // in lower bits for both LE and BE, and they are not rounded up to |
422 | | // 64-bits. We can skip rounding up of composite types for LE, but not for |
423 | | // BE, otherwise composite types will be indistinguishable from integer |
424 | | // types. |
425 | 0 | return ABIArgInfo::getDirect( |
426 | 0 | llvm::IntegerType::get(getVMContext(), Size)); |
427 | 0 | } |
428 | | |
429 | 0 | unsigned Alignment = getContext().getTypeAlign(RetTy); |
430 | 0 | Size = llvm::alignTo(Size, 64); // round up to multiple of 8 bytes |
431 | | |
432 | | // We use a pair of i64 for 16-byte aggregate with 8-byte alignment. |
433 | | // For aggregates with 16-byte alignment, we use i128. |
434 | 0 | if (Alignment < 128 && Size == 128) { |
435 | 0 | llvm::Type *BaseTy = llvm::Type::getInt64Ty(getVMContext()); |
436 | 0 | return ABIArgInfo::getDirect(llvm::ArrayType::get(BaseTy, Size / 64)); |
437 | 0 | } |
438 | 0 | return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size)); |
439 | 0 | } |
440 | | |
441 | 0 | return getNaturalAlignIndirect(RetTy); |
442 | 0 | } |
443 | | |
444 | | /// isIllegalVectorType - check whether the vector type is legal for AArch64. |
445 | 0 | bool AArch64ABIInfo::isIllegalVectorType(QualType Ty) const { |
446 | 0 | if (const VectorType *VT = Ty->getAs<VectorType>()) { |
447 | | // Check whether VT is a fixed-length SVE vector. These types are |
448 | | // represented as scalable vectors in function args/return and must be |
449 | | // coerced from fixed vectors. |
450 | 0 | if (VT->getVectorKind() == VectorKind::SveFixedLengthData || |
451 | 0 | VT->getVectorKind() == VectorKind::SveFixedLengthPredicate) |
452 | 0 | return true; |
453 | | |
454 | | // Check whether VT is legal. |
455 | 0 | unsigned NumElements = VT->getNumElements(); |
456 | 0 | uint64_t Size = getContext().getTypeSize(VT); |
457 | | // NumElements should be power of 2. |
458 | 0 | if (!llvm::isPowerOf2_32(NumElements)) |
459 | 0 | return true; |
460 | | |
461 | | // arm64_32 has to be compatible with the ARM logic here, which allows huge |
462 | | // vectors for some reason. |
463 | 0 | llvm::Triple Triple = getTarget().getTriple(); |
464 | 0 | if (Triple.getArch() == llvm::Triple::aarch64_32 && |
465 | 0 | Triple.isOSBinFormatMachO()) |
466 | 0 | return Size <= 32; |
467 | | |
468 | 0 | return Size != 64 && (Size != 128 || NumElements == 1); |
469 | 0 | } |
470 | 0 | return false; |
471 | 0 | } |
472 | | |
473 | | bool AArch64SwiftABIInfo::isLegalVectorType(CharUnits VectorSize, |
474 | | llvm::Type *EltTy, |
475 | 0 | unsigned NumElts) const { |
476 | 0 | if (!llvm::isPowerOf2_32(NumElts)) |
477 | 0 | return false; |
478 | 0 | if (VectorSize.getQuantity() != 8 && |
479 | 0 | (VectorSize.getQuantity() != 16 || NumElts == 1)) |
480 | 0 | return false; |
481 | 0 | return true; |
482 | 0 | } |
483 | | |
484 | 0 | bool AArch64ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { |
485 | | // Homogeneous aggregates for AAPCS64 must have base types of a floating |
486 | | // point type or a short-vector type. This is the same as the 32-bit ABI, |
487 | | // but with the difference that any floating-point type is allowed, |
488 | | // including __fp16. |
489 | 0 | if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { |
490 | 0 | if (BT->isFloatingPoint()) |
491 | 0 | return true; |
492 | 0 | } else if (const VectorType *VT = Ty->getAs<VectorType>()) { |
493 | 0 | unsigned VecSize = getContext().getTypeSize(VT); |
494 | 0 | if (VecSize == 64 || VecSize == 128) |
495 | 0 | return true; |
496 | 0 | } |
497 | 0 | return false; |
498 | 0 | } |
499 | | |
500 | | bool AArch64ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base, |
501 | 0 | uint64_t Members) const { |
502 | 0 | return Members <= 4; |
503 | 0 | } |
504 | | |
505 | | bool AArch64ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() |
506 | 0 | const { |
507 | | // AAPCS64 says that the rule for whether something is a homogeneous |
508 | | // aggregate is applied to the output of the data layout decision. So |
509 | | // anything that doesn't affect the data layout also does not affect |
510 | | // homogeneity. In particular, zero-length bitfields don't stop a struct |
511 | | // being homogeneous. |
512 | 0 | return true; |
513 | 0 | } |
514 | | |
515 | | Address AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty, |
516 | 0 | CodeGenFunction &CGF) const { |
517 | 0 | ABIArgInfo AI = classifyArgumentType(Ty, /*IsVariadic=*/true, |
518 | 0 | CGF.CurFnInfo->getCallingConvention()); |
519 | | // Empty records are ignored for parameter passing purposes. |
520 | 0 | if (AI.isIgnore()) { |
521 | 0 | uint64_t PointerSize = getTarget().getPointerWidth(LangAS::Default) / 8; |
522 | 0 | CharUnits SlotSize = CharUnits::fromQuantity(PointerSize); |
523 | 0 | VAListAddr = VAListAddr.withElementType(CGF.Int8PtrTy); |
524 | 0 | auto *Load = CGF.Builder.CreateLoad(VAListAddr); |
525 | 0 | return Address(Load, CGF.ConvertTypeForMem(Ty), SlotSize); |
526 | 0 | } |
527 | | |
528 | 0 | bool IsIndirect = AI.isIndirect(); |
529 | |
|
530 | 0 | llvm::Type *BaseTy = CGF.ConvertType(Ty); |
531 | 0 | if (IsIndirect) |
532 | 0 | BaseTy = llvm::PointerType::getUnqual(BaseTy); |
533 | 0 | else if (AI.getCoerceToType()) |
534 | 0 | BaseTy = AI.getCoerceToType(); |
535 | |
|
536 | 0 | unsigned NumRegs = 1; |
537 | 0 | if (llvm::ArrayType *ArrTy = dyn_cast<llvm::ArrayType>(BaseTy)) { |
538 | 0 | BaseTy = ArrTy->getElementType(); |
539 | 0 | NumRegs = ArrTy->getNumElements(); |
540 | 0 | } |
541 | 0 | bool IsFPR = BaseTy->isFloatingPointTy() || BaseTy->isVectorTy(); |
542 | | |
543 | | // The AArch64 va_list type and handling is specified in the Procedure Call |
544 | | // Standard, section B.4: |
545 | | // |
546 | | // struct { |
547 | | // void *__stack; |
548 | | // void *__gr_top; |
549 | | // void *__vr_top; |
550 | | // int __gr_offs; |
551 | | // int __vr_offs; |
552 | | // }; |
553 | |
|
554 | 0 | llvm::BasicBlock *MaybeRegBlock = CGF.createBasicBlock("vaarg.maybe_reg"); |
555 | 0 | llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg"); |
556 | 0 | llvm::BasicBlock *OnStackBlock = CGF.createBasicBlock("vaarg.on_stack"); |
557 | 0 | llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end"); |
558 | |
|
559 | 0 | CharUnits TySize = getContext().getTypeSizeInChars(Ty); |
560 | 0 | CharUnits TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty); |
561 | |
|
562 | 0 | Address reg_offs_p = Address::invalid(); |
563 | 0 | llvm::Value *reg_offs = nullptr; |
564 | 0 | int reg_top_index; |
565 | 0 | int RegSize = IsIndirect ? 8 : TySize.getQuantity(); |
566 | 0 | if (!IsFPR) { |
567 | | // 3 is the field number of __gr_offs |
568 | 0 | reg_offs_p = CGF.Builder.CreateStructGEP(VAListAddr, 3, "gr_offs_p"); |
569 | 0 | reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "gr_offs"); |
570 | 0 | reg_top_index = 1; // field number for __gr_top |
571 | 0 | RegSize = llvm::alignTo(RegSize, 8); |
572 | 0 | } else { |
573 | | // 4 is the field number of __vr_offs. |
574 | 0 | reg_offs_p = CGF.Builder.CreateStructGEP(VAListAddr, 4, "vr_offs_p"); |
575 | 0 | reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "vr_offs"); |
576 | 0 | reg_top_index = 2; // field number for __vr_top |
577 | 0 | RegSize = 16 * NumRegs; |
578 | 0 | } |
579 | | |
580 | | //======================================= |
581 | | // Find out where argument was passed |
582 | | //======================================= |
583 | | |
584 | | // If reg_offs >= 0 we're already using the stack for this type of |
585 | | // argument. We don't want to keep updating reg_offs (in case it overflows, |
586 | | // though anyone passing 2GB of arguments, each at most 16 bytes, deserves |
587 | | // whatever they get). |
588 | 0 | llvm::Value *UsingStack = nullptr; |
589 | 0 | UsingStack = CGF.Builder.CreateICmpSGE( |
590 | 0 | reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, 0)); |
591 | |
|
592 | 0 | CGF.Builder.CreateCondBr(UsingStack, OnStackBlock, MaybeRegBlock); |
593 | | |
594 | | // Otherwise, at least some kind of argument could go in these registers, the |
595 | | // question is whether this particular type is too big. |
596 | 0 | CGF.EmitBlock(MaybeRegBlock); |
597 | | |
598 | | // Integer arguments may need to correct register alignment (for example a |
599 | | // "struct { __int128 a; };" gets passed in x_2N, x_{2N+1}). In this case we |
600 | | // align __gr_offs to calculate the potential address. |
601 | 0 | if (!IsFPR && !IsIndirect && TyAlign.getQuantity() > 8) { |
602 | 0 | int Align = TyAlign.getQuantity(); |
603 | |
|
604 | 0 | reg_offs = CGF.Builder.CreateAdd( |
605 | 0 | reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, Align - 1), |
606 | 0 | "align_regoffs"); |
607 | 0 | reg_offs = CGF.Builder.CreateAnd( |
608 | 0 | reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, -Align), |
609 | 0 | "aligned_regoffs"); |
610 | 0 | } |
611 | | |
612 | | // Update the gr_offs/vr_offs pointer for next call to va_arg on this va_list. |
613 | | // The fact that this is done unconditionally reflects the fact that |
614 | | // allocating an argument to the stack also uses up all the remaining |
615 | | // registers of the appropriate kind. |
616 | 0 | llvm::Value *NewOffset = nullptr; |
617 | 0 | NewOffset = CGF.Builder.CreateAdd( |
618 | 0 | reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, RegSize), "new_reg_offs"); |
619 | 0 | CGF.Builder.CreateStore(NewOffset, reg_offs_p); |
620 | | |
621 | | // Now we're in a position to decide whether this argument really was in |
622 | | // registers or not. |
623 | 0 | llvm::Value *InRegs = nullptr; |
624 | 0 | InRegs = CGF.Builder.CreateICmpSLE( |
625 | 0 | NewOffset, llvm::ConstantInt::get(CGF.Int32Ty, 0), "inreg"); |
626 | |
|
627 | 0 | CGF.Builder.CreateCondBr(InRegs, InRegBlock, OnStackBlock); |
628 | | |
629 | | //======================================= |
630 | | // Argument was in registers |
631 | | //======================================= |
632 | | |
633 | | // Now we emit the code for if the argument was originally passed in |
634 | | // registers. First start the appropriate block: |
635 | 0 | CGF.EmitBlock(InRegBlock); |
636 | |
|
637 | 0 | llvm::Value *reg_top = nullptr; |
638 | 0 | Address reg_top_p = |
639 | 0 | CGF.Builder.CreateStructGEP(VAListAddr, reg_top_index, "reg_top_p"); |
640 | 0 | reg_top = CGF.Builder.CreateLoad(reg_top_p, "reg_top"); |
641 | 0 | Address BaseAddr(CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, reg_top, reg_offs), |
642 | 0 | CGF.Int8Ty, CharUnits::fromQuantity(IsFPR ? 16 : 8)); |
643 | 0 | Address RegAddr = Address::invalid(); |
644 | 0 | llvm::Type *MemTy = CGF.ConvertTypeForMem(Ty), *ElementTy = MemTy; |
645 | |
|
646 | 0 | if (IsIndirect) { |
647 | | // If it's been passed indirectly (actually a struct), whatever we find from |
648 | | // stored registers or on the stack will actually be a struct **. |
649 | 0 | MemTy = llvm::PointerType::getUnqual(MemTy); |
650 | 0 | } |
651 | |
|
652 | 0 | const Type *Base = nullptr; |
653 | 0 | uint64_t NumMembers = 0; |
654 | 0 | bool IsHFA = isHomogeneousAggregate(Ty, Base, NumMembers); |
655 | 0 | if (IsHFA && NumMembers > 1) { |
656 | | // Homogeneous aggregates passed in registers will have their elements split |
657 | | // and stored 16-bytes apart regardless of size (they're notionally in qN, |
658 | | // qN+1, ...). We reload and store into a temporary local variable |
659 | | // contiguously. |
660 | 0 | assert(!IsIndirect && "Homogeneous aggregates should be passed directly"); |
661 | 0 | auto BaseTyInfo = getContext().getTypeInfoInChars(QualType(Base, 0)); |
662 | 0 | llvm::Type *BaseTy = CGF.ConvertType(QualType(Base, 0)); |
663 | 0 | llvm::Type *HFATy = llvm::ArrayType::get(BaseTy, NumMembers); |
664 | 0 | Address Tmp = CGF.CreateTempAlloca(HFATy, |
665 | 0 | std::max(TyAlign, BaseTyInfo.Align)); |
666 | | |
667 | | // On big-endian platforms, the value will be right-aligned in its slot. |
668 | 0 | int Offset = 0; |
669 | 0 | if (CGF.CGM.getDataLayout().isBigEndian() && |
670 | 0 | BaseTyInfo.Width.getQuantity() < 16) |
671 | 0 | Offset = 16 - BaseTyInfo.Width.getQuantity(); |
672 | |
|
673 | 0 | for (unsigned i = 0; i < NumMembers; ++i) { |
674 | 0 | CharUnits BaseOffset = CharUnits::fromQuantity(16 * i + Offset); |
675 | 0 | Address LoadAddr = |
676 | 0 | CGF.Builder.CreateConstInBoundsByteGEP(BaseAddr, BaseOffset); |
677 | 0 | LoadAddr = LoadAddr.withElementType(BaseTy); |
678 | |
|
679 | 0 | Address StoreAddr = CGF.Builder.CreateConstArrayGEP(Tmp, i); |
680 | |
|
681 | 0 | llvm::Value *Elem = CGF.Builder.CreateLoad(LoadAddr); |
682 | 0 | CGF.Builder.CreateStore(Elem, StoreAddr); |
683 | 0 | } |
684 | |
|
685 | 0 | RegAddr = Tmp.withElementType(MemTy); |
686 | 0 | } else { |
687 | | // Otherwise the object is contiguous in memory. |
688 | | |
689 | | // It might be right-aligned in its slot. |
690 | 0 | CharUnits SlotSize = BaseAddr.getAlignment(); |
691 | 0 | if (CGF.CGM.getDataLayout().isBigEndian() && !IsIndirect && |
692 | 0 | (IsHFA || !isAggregateTypeForABI(Ty)) && |
693 | 0 | TySize < SlotSize) { |
694 | 0 | CharUnits Offset = SlotSize - TySize; |
695 | 0 | BaseAddr = CGF.Builder.CreateConstInBoundsByteGEP(BaseAddr, Offset); |
696 | 0 | } |
697 | |
|
698 | 0 | RegAddr = BaseAddr.withElementType(MemTy); |
699 | 0 | } |
700 | | |
701 | 0 | CGF.EmitBranch(ContBlock); |
702 | | |
703 | | //======================================= |
704 | | // Argument was on the stack |
705 | | //======================================= |
706 | 0 | CGF.EmitBlock(OnStackBlock); |
707 | |
|
708 | 0 | Address stack_p = CGF.Builder.CreateStructGEP(VAListAddr, 0, "stack_p"); |
709 | 0 | llvm::Value *OnStackPtr = CGF.Builder.CreateLoad(stack_p, "stack"); |
710 | | |
711 | | // Again, stack arguments may need realignment. In this case both integer and |
712 | | // floating-point ones might be affected. |
713 | 0 | if (!IsIndirect && TyAlign.getQuantity() > 8) { |
714 | 0 | int Align = TyAlign.getQuantity(); |
715 | |
|
716 | 0 | OnStackPtr = CGF.Builder.CreatePtrToInt(OnStackPtr, CGF.Int64Ty); |
717 | |
|
718 | 0 | OnStackPtr = CGF.Builder.CreateAdd( |
719 | 0 | OnStackPtr, llvm::ConstantInt::get(CGF.Int64Ty, Align - 1), |
720 | 0 | "align_stack"); |
721 | 0 | OnStackPtr = CGF.Builder.CreateAnd( |
722 | 0 | OnStackPtr, llvm::ConstantInt::get(CGF.Int64Ty, -Align), |
723 | 0 | "align_stack"); |
724 | |
|
725 | 0 | OnStackPtr = CGF.Builder.CreateIntToPtr(OnStackPtr, CGF.Int8PtrTy); |
726 | 0 | } |
727 | 0 | Address OnStackAddr = Address(OnStackPtr, CGF.Int8Ty, |
728 | 0 | std::max(CharUnits::fromQuantity(8), TyAlign)); |
729 | | |
730 | | // All stack slots are multiples of 8 bytes. |
731 | 0 | CharUnits StackSlotSize = CharUnits::fromQuantity(8); |
732 | 0 | CharUnits StackSize; |
733 | 0 | if (IsIndirect) |
734 | 0 | StackSize = StackSlotSize; |
735 | 0 | else |
736 | 0 | StackSize = TySize.alignTo(StackSlotSize); |
737 | |
|
738 | 0 | llvm::Value *StackSizeC = CGF.Builder.getSize(StackSize); |
739 | 0 | llvm::Value *NewStack = CGF.Builder.CreateInBoundsGEP( |
740 | 0 | CGF.Int8Ty, OnStackPtr, StackSizeC, "new_stack"); |
741 | | |
742 | | // Write the new value of __stack for the next call to va_arg |
743 | 0 | CGF.Builder.CreateStore(NewStack, stack_p); |
744 | |
|
745 | 0 | if (CGF.CGM.getDataLayout().isBigEndian() && !isAggregateTypeForABI(Ty) && |
746 | 0 | TySize < StackSlotSize) { |
747 | 0 | CharUnits Offset = StackSlotSize - TySize; |
748 | 0 | OnStackAddr = CGF.Builder.CreateConstInBoundsByteGEP(OnStackAddr, Offset); |
749 | 0 | } |
750 | |
|
751 | 0 | OnStackAddr = OnStackAddr.withElementType(MemTy); |
752 | |
|
753 | 0 | CGF.EmitBranch(ContBlock); |
754 | | |
755 | | //======================================= |
756 | | // Tidy up |
757 | | //======================================= |
758 | 0 | CGF.EmitBlock(ContBlock); |
759 | |
|
760 | 0 | Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock, OnStackAddr, |
761 | 0 | OnStackBlock, "vaargs.addr"); |
762 | |
|
763 | 0 | if (IsIndirect) |
764 | 0 | return Address(CGF.Builder.CreateLoad(ResAddr, "vaarg.addr"), ElementTy, |
765 | 0 | TyAlign); |
766 | | |
767 | 0 | return ResAddr; |
768 | 0 | } |
769 | | |
770 | | Address AArch64ABIInfo::EmitDarwinVAArg(Address VAListAddr, QualType Ty, |
771 | 0 | CodeGenFunction &CGF) const { |
772 | | // The backend's lowering doesn't support va_arg for aggregates or |
773 | | // illegal vector types. Lower VAArg here for these cases and use |
774 | | // the LLVM va_arg instruction for everything else. |
775 | 0 | if (!isAggregateTypeForABI(Ty) && !isIllegalVectorType(Ty)) |
776 | 0 | return EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect()); |
777 | | |
778 | 0 | uint64_t PointerSize = getTarget().getPointerWidth(LangAS::Default) / 8; |
779 | 0 | CharUnits SlotSize = CharUnits::fromQuantity(PointerSize); |
780 | | |
781 | | // Empty records are ignored for parameter passing purposes. |
782 | 0 | if (isEmptyRecord(getContext(), Ty, true)) |
783 | 0 | return Address(CGF.Builder.CreateLoad(VAListAddr, "ap.cur"), |
784 | 0 | CGF.ConvertTypeForMem(Ty), SlotSize); |
785 | | |
786 | | // The size of the actual thing passed, which might end up just |
787 | | // being a pointer for indirect types. |
788 | 0 | auto TyInfo = getContext().getTypeInfoInChars(Ty); |
789 | | |
790 | | // Arguments bigger than 16 bytes which aren't homogeneous |
791 | | // aggregates should be passed indirectly. |
792 | 0 | bool IsIndirect = false; |
793 | 0 | if (TyInfo.Width.getQuantity() > 16) { |
794 | 0 | const Type *Base = nullptr; |
795 | 0 | uint64_t Members = 0; |
796 | 0 | IsIndirect = !isHomogeneousAggregate(Ty, Base, Members); |
797 | 0 | } |
798 | |
|
799 | 0 | return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, |
800 | 0 | TyInfo, SlotSize, /*AllowHigherAlign*/ true); |
801 | 0 | } |
802 | | |
803 | | Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, |
804 | 0 | QualType Ty) const { |
805 | 0 | bool IsIndirect = false; |
806 | | |
807 | | // Composites larger than 16 bytes are passed by reference. |
808 | 0 | if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) > 128) |
809 | 0 | IsIndirect = true; |
810 | |
|
811 | 0 | return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, |
812 | 0 | CGF.getContext().getTypeInfoInChars(Ty), |
813 | 0 | CharUnits::fromQuantity(8), |
814 | 0 | /*allowHigherAlign*/ false); |
815 | 0 | } |
816 | | |
817 | | std::unique_ptr<TargetCodeGenInfo> |
818 | | CodeGen::createAArch64TargetCodeGenInfo(CodeGenModule &CGM, |
819 | 0 | AArch64ABIKind Kind) { |
820 | 0 | return std::make_unique<AArch64TargetCodeGenInfo>(CGM.getTypes(), Kind); |
821 | 0 | } |
822 | | |
823 | | std::unique_ptr<TargetCodeGenInfo> |
824 | | CodeGen::createWindowsAArch64TargetCodeGenInfo(CodeGenModule &CGM, |
825 | 0 | AArch64ABIKind K) { |
826 | 0 | return std::make_unique<WindowsAArch64TargetCodeGenInfo>(CGM.getTypes(), K); |
827 | 0 | } |