1//===- ABIInfoImpl.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
11using namespace clang;
12using namespace clang::CodeGen;
13
14// Pin the vtable to this file.
15DefaultABIInfo::~DefaultABIInfo() = default;
16
17ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
18 Ty = useFirstFieldIfTransparentUnion(Ty);
19
20 if (isAggregateTypeForABI(T: Ty)) {
21 // Records with non-trivial destructors/copy-constructors should not be
22 // passed by value.
23 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(T: Ty, CXXABI&: getCXXABI()))
24 return getNaturalAlignIndirect(Ty, AddrSpace: getDataLayout().getAllocaAddrSpace(),
25 ByVal: RAA == CGCXXABI::RAA_DirectInMemory);
26
27 return getNaturalAlignIndirect(Ty, AddrSpace: getDataLayout().getAllocaAddrSpace());
28 }
29
30 // Treat an enum type as its underlying type.
31 if (const auto *ED = Ty->getAsEnumDecl())
32 Ty = ED->getIntegerType();
33
34 ASTContext &Context = getContext();
35 if (const auto *EIT = Ty->getAs<BitIntType>())
36 if (EIT->getNumBits() >
37 Context.getTypeSize(T: Context.getTargetInfo().hasInt128Type()
38 ? Context.Int128Ty
39 : Context.LongLongTy))
40 return getNaturalAlignIndirect(Ty, AddrSpace: getDataLayout().getAllocaAddrSpace());
41
42 return (isPromotableIntegerTypeForABI(Ty)
43 ? ABIArgInfo::getExtend(Ty, T: CGT.ConvertType(T: Ty))
44 : ABIArgInfo::getDirect());
45}
46
47ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {
48 if (RetTy->isVoidType())
49 return ABIArgInfo::getIgnore();
50
51 if (isAggregateTypeForABI(T: RetTy))
52 return getNaturalAlignIndirect(Ty: RetTy, AddrSpace: getDataLayout().getAllocaAddrSpace());
53
54 // Treat an enum type as its underlying type.
55 if (const auto *ED = RetTy->getAsEnumDecl())
56 RetTy = ED->getIntegerType();
57
58 if (const auto *EIT = RetTy->getAs<BitIntType>())
59 if (EIT->getNumBits() >
60 getContext().getTypeSize(T: getContext().getTargetInfo().hasInt128Type()
61 ? getContext().Int128Ty
62 : getContext().LongLongTy))
63 return getNaturalAlignIndirect(Ty: RetTy,
64 AddrSpace: getDataLayout().getAllocaAddrSpace());
65
66 return (isPromotableIntegerTypeForABI(Ty: RetTy) ? ABIArgInfo::getExtend(Ty: RetTy)
67 : ABIArgInfo::getDirect());
68}
69
70void DefaultABIInfo::computeInfo(CGFunctionInfo &FI) const {
71 if (!getCXXABI().classifyReturnType(FI))
72 FI.getReturnInfo() = classifyReturnType(RetTy: FI.getReturnType());
73 for (auto &I : FI.arguments())
74 I.info = classifyArgumentType(Ty: I.type);
75}
76
77RValue DefaultABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
78 QualType Ty, AggValueSlot Slot) const {
79 return CGF.EmitLoadOfAnyValue(
80 V: CGF.MakeAddrLValue(
81 Addr: EmitVAArgInstr(CGF, VAListAddr, Ty, AI: classifyArgumentType(Ty)), T: Ty),
82 Slot);
83}
84
85void CodeGen::AssignToArrayRange(CodeGen::CGBuilderTy &Builder,
86 llvm::Value *Array, llvm::Value *Value,
87 unsigned FirstIndex, unsigned LastIndex) {
88 // Alternatively, we could emit this as a loop in the source.
89 for (unsigned I = FirstIndex; I <= LastIndex; ++I) {
90 llvm::Value *Cell =
91 Builder.CreateConstInBoundsGEP1_32(Ty: Builder.getInt8Ty(), Ptr: Array, Idx0: I);
92 Builder.CreateAlignedStore(Val: Value, Addr: Cell, Align: CharUnits::One());
93 }
94}
95
96bool CodeGen::isAggregateTypeForABI(QualType T) {
97 return !CodeGenFunction::hasScalarEvaluationKind(T) ||
98 T->isMemberFunctionPointerType();
99}
100
101llvm::Type *CodeGen::getVAListElementType(CodeGenFunction &CGF) {
102 return CGF.ConvertTypeForMem(
103 T: CGF.getContext().getBuiltinVaListType()->getPointeeType());
104}
105
106CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(const RecordType *RT,
107 CGCXXABI &CXXABI) {
108 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
109 if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(Val: RD))
110 return CXXABI.getRecordArgABI(RD: CXXRD);
111 if (!RD->canPassInRegisters())
112 return CGCXXABI::RAA_Indirect;
113 return CGCXXABI::RAA_Default;
114}
115
116CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(QualType T, CGCXXABI &CXXABI) {
117 const RecordType *RT = T->getAsCanonical<RecordType>();
118 if (!RT)
119 return CGCXXABI::RAA_Default;
120 return getRecordArgABI(RT, CXXABI);
121}
122
123bool CodeGen::classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI,
124 const ABIInfo &Info) {
125 QualType Ty = FI.getReturnType();
126
127 if (const auto *RD = Ty->getAsRecordDecl();
128 RD && !isa<CXXRecordDecl>(Val: RD) && !RD->canPassInRegisters()) {
129 FI.getReturnInfo() = Info.getNaturalAlignIndirect(
130 Ty, AddrSpace: Info.getDataLayout().getAllocaAddrSpace());
131 return true;
132 }
133
134 return CXXABI.classifyReturnType(FI);
135}
136
137QualType CodeGen::useFirstFieldIfTransparentUnion(QualType Ty) {
138 if (const RecordType *UT = Ty->getAsUnionType()) {
139 const RecordDecl *UD = UT->getDecl()->getDefinitionOrSelf();
140 if (UD->hasAttr<TransparentUnionAttr>()) {
141 assert(!UD->field_empty() && "sema created an empty transparent union");
142 return UD->field_begin()->getType();
143 }
144 }
145 return Ty;
146}
147
148llvm::Value *CodeGen::emitRoundPointerUpToAlignment(CodeGenFunction &CGF,
149 llvm::Value *Ptr,
150 CharUnits Align) {
151 // OverflowArgArea = (OverflowArgArea + Align - 1) & -Align;
152 llvm::Value *RoundUp = CGF.Builder.CreateConstInBoundsGEP1_32(
153 Ty: CGF.Builder.getInt8Ty(), Ptr, Idx0: Align.getQuantity() - 1);
154 return CGF.Builder.CreateIntrinsic(
155 ID: llvm::Intrinsic::ptrmask, Types: {Ptr->getType(), CGF.IntPtrTy},
156 Args: {RoundUp,
157 llvm::ConstantInt::getSigned(Ty: CGF.IntPtrTy, V: -Align.getQuantity())},
158 FMFSource: nullptr, Name: Ptr->getName() + ".aligned");
159}
160
161Address
162CodeGen::emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr,
163 llvm::Type *DirectTy, CharUnits DirectSize,
164 CharUnits DirectAlign, CharUnits SlotSize,
165 bool AllowHigherAlign, bool ForceRightAdjust) {
166 // Cast the element type to i8* if necessary. Some platforms define
167 // va_list as a struct containing an i8* instead of just an i8*.
168 if (VAListAddr.getElementType() != CGF.Int8PtrTy)
169 VAListAddr = VAListAddr.withElementType(ElemTy: CGF.Int8PtrTy);
170
171 llvm::Value *Ptr = CGF.Builder.CreateLoad(Addr: VAListAddr, Name: "argp.cur");
172
173 // If the CC aligns values higher than the slot size, do so if needed.
174 Address Addr = Address::invalid();
175 if (AllowHigherAlign && DirectAlign > SlotSize) {
176 Addr = Address(emitRoundPointerUpToAlignment(CGF, Ptr, Align: DirectAlign),
177 CGF.Int8Ty, DirectAlign);
178 } else {
179 Addr = Address(Ptr, CGF.Int8Ty, SlotSize);
180 }
181
182 // Advance the pointer past the argument, then store that back.
183 CharUnits FullDirectSize = DirectSize.alignTo(Align: SlotSize);
184 Address NextPtr =
185 CGF.Builder.CreateConstInBoundsByteGEP(Addr, Offset: FullDirectSize, Name: "argp.next");
186 CGF.Builder.CreateStore(Val: NextPtr.emitRawPointer(CGF), Addr: VAListAddr);
187
188 // If the argument is smaller than a slot, and this is a big-endian
189 // target, the argument will be right-adjusted in its slot.
190 if (DirectSize < SlotSize && CGF.CGM.getDataLayout().isBigEndian() &&
191 (!DirectTy->isStructTy() || ForceRightAdjust)) {
192 Addr = CGF.Builder.CreateConstInBoundsByteGEP(Addr, Offset: SlotSize - DirectSize);
193 }
194
195 return Addr.withElementType(ElemTy: DirectTy);
196}
197
198RValue CodeGen::emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,
199 QualType ValueTy, bool IsIndirect,
200 TypeInfoChars ValueInfo,
201 CharUnits SlotSizeAndAlign,
202 bool AllowHigherAlign, AggValueSlot Slot,
203 bool ForceRightAdjust) {
204 // The size and alignment of the value that was passed directly.
205 CharUnits DirectSize, DirectAlign;
206 if (IsIndirect) {
207 DirectSize = CGF.getPointerSize();
208 DirectAlign = CGF.getPointerAlign();
209 } else {
210 DirectSize = ValueInfo.Width;
211 DirectAlign = ValueInfo.Align;
212 }
213
214 // Cast the address we've calculated to the right type.
215 llvm::Type *DirectTy = CGF.ConvertTypeForMem(T: ValueTy), *ElementTy = DirectTy;
216 if (IsIndirect) {
217 unsigned AllocaAS = CGF.CGM.getDataLayout().getAllocaAddrSpace();
218 DirectTy = llvm::PointerType::get(C&: CGF.getLLVMContext(), AddressSpace: AllocaAS);
219 }
220
221 Address Addr = emitVoidPtrDirectVAArg(CGF, VAListAddr, DirectTy, DirectSize,
222 DirectAlign, SlotSize: SlotSizeAndAlign,
223 AllowHigherAlign, ForceRightAdjust);
224
225 if (IsIndirect) {
226 Addr = Address(CGF.Builder.CreateLoad(Addr), ElementTy, ValueInfo.Align);
227 }
228
229 return CGF.EmitLoadOfAnyValue(V: CGF.MakeAddrLValue(Addr, T: ValueTy), Slot);
230}
231
232Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1,
233 llvm::BasicBlock *Block1, Address Addr2,
234 llvm::BasicBlock *Block2,
235 const llvm::Twine &Name) {
236 assert(Addr1.getType() == Addr2.getType());
237 llvm::PHINode *PHI = CGF.Builder.CreatePHI(Ty: Addr1.getType(), NumReservedValues: 2, Name);
238 PHI->addIncoming(V: Addr1.emitRawPointer(CGF), BB: Block1);
239 PHI->addIncoming(V: Addr2.emitRawPointer(CGF), BB: Block2);
240 CharUnits Align = std::min(a: Addr1.getAlignment(), b: Addr2.getAlignment());
241 return Address(PHI, Addr1.getElementType(), Align);
242}
243
244bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD,
245 bool AllowArrays, bool AsIfNoUniqueAddr) {
246 if (FD->isUnnamedBitField())
247 return true;
248
249 QualType FT = FD->getType();
250
251 // Constant arrays of empty records count as empty, strip them off.
252 // Constant arrays of zero length always count as empty.
253 bool WasArray = false;
254 if (AllowArrays)
255 while (const ConstantArrayType *AT = Context.getAsConstantArrayType(T: FT)) {
256 if (AT->isZeroSize())
257 return true;
258 FT = AT->getElementType();
259 // The [[no_unique_address]] special case below does not apply to
260 // arrays of C++ empty records, so we need to remember this fact.
261 WasArray = true;
262 }
263
264 const RecordType *RT = FT->getAsCanonical<RecordType>();
265 if (!RT)
266 return false;
267
268 // C++ record fields are never empty, at least in the Itanium ABI.
269 //
270 // FIXME: We should use a predicate for whether this behavior is true in the
271 // current ABI.
272 //
273 // The exception to the above rule are fields marked with the
274 // [[no_unique_address]] attribute (since C++20). Those do count as empty
275 // according to the Itanium ABI. The exception applies only to records,
276 // not arrays of records, so we must also check whether we stripped off an
277 // array type above.
278 if (isa<CXXRecordDecl>(Val: RT->getDecl()) &&
279 (WasArray || (!AsIfNoUniqueAddr && !FD->hasAttr<NoUniqueAddressAttr>())))
280 return false;
281
282 return isEmptyRecord(Context, T: FT, AllowArrays, AsIfNoUniqueAddr);
283}
284
285bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays,
286 bool AsIfNoUniqueAddr) {
287 const auto *RD = T->getAsRecordDecl();
288 if (!RD)
289 return false;
290 if (RD->hasFlexibleArrayMember())
291 return false;
292
293 // If this is a C++ record, check the bases first.
294 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(Val: RD))
295 for (const auto &I : CXXRD->bases())
296 if (!isEmptyRecord(Context, T: I.getType(), AllowArrays: true, AsIfNoUniqueAddr))
297 return false;
298
299 for (const auto *I : RD->fields())
300 if (!isEmptyField(Context, FD: I, AllowArrays, AsIfNoUniqueAddr))
301 return false;
302 return true;
303}
304
305bool CodeGen::isEmptyFieldForLayout(const ASTContext &Context,
306 const FieldDecl *FD) {
307 if (FD->isZeroLengthBitField())
308 return true;
309
310 if (FD->isUnnamedBitField())
311 return false;
312
313 return isEmptyRecordForLayout(Context, T: FD->getType());
314}
315
316bool CodeGen::isEmptyRecordForLayout(const ASTContext &Context, QualType T) {
317 const auto *RD = T->getAsRecordDecl();
318 if (!RD)
319 return false;
320
321 // If this is a C++ record, check the bases first.
322 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(Val: RD)) {
323 if (CXXRD->isDynamicClass())
324 return false;
325
326 for (const auto &I : CXXRD->bases())
327 if (!isEmptyRecordForLayout(Context, T: I.getType()))
328 return false;
329 }
330
331 for (const auto *I : RD->fields())
332 if (!isEmptyFieldForLayout(Context, FD: I))
333 return false;
334
335 return true;
336}
337
338const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) {
339 const auto *RD = T->getAsRecordDecl();
340 if (!RD)
341 return nullptr;
342
343 if (RD->hasFlexibleArrayMember())
344 return nullptr;
345
346 const Type *Found = nullptr;
347
348 // If this is a C++ record, check the bases first.
349 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(Val: RD)) {
350 for (const auto &I : CXXRD->bases()) {
351 // Ignore empty records.
352 if (isEmptyRecord(Context, T: I.getType(), AllowArrays: true))
353 continue;
354
355 // If we already found an element then this isn't a single-element struct.
356 if (Found)
357 return nullptr;
358
359 // If this is non-empty and not a single element struct, the composite
360 // cannot be a single element struct.
361 Found = isSingleElementStruct(T: I.getType(), Context);
362 if (!Found)
363 return nullptr;
364 }
365 }
366
367 // Check for single element.
368 for (const auto *FD : RD->fields()) {
369 QualType FT = FD->getType();
370
371 // Ignore empty fields.
372 if (isEmptyField(Context, FD, AllowArrays: true))
373 continue;
374
375 // If we already found an element then this isn't a single-element
376 // struct.
377 if (Found)
378 return nullptr;
379
380 // Treat single element arrays as the element.
381 while (const ConstantArrayType *AT = Context.getAsConstantArrayType(T: FT)) {
382 if (AT->getZExtSize() != 1)
383 break;
384 FT = AT->getElementType();
385 }
386
387 if (!isAggregateTypeForABI(T: FT)) {
388 Found = FT.getTypePtr();
389 } else {
390 Found = isSingleElementStruct(T: FT, Context);
391 if (!Found)
392 return nullptr;
393 }
394 }
395
396 // We don't consider a struct a single-element struct if it has
397 // padding beyond the element type.
398 if (Found && Context.getTypeSize(T: Found) != Context.getTypeSize(T))
399 return nullptr;
400
401 return Found;
402}
403
404Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr,
405 QualType Ty, const ABIArgInfo &AI) {
406 // This default implementation defers to the llvm backend's va_arg
407 // instruction. It can handle only passing arguments directly
408 // (typically only handled in the backend for primitive types), or
409 // aggregates passed indirectly by pointer (NOTE: if the "byval"
410 // flag has ABI impact in the callee, this implementation cannot
411 // work.)
412
413 // Only a few cases are covered here at the moment -- those needed
414 // by the default abi.
415 llvm::Value *Val;
416
417 if (AI.isIndirect()) {
418 assert(!AI.getPaddingType() &&
419 "Unexpected PaddingType seen in arginfo in generic VAArg emitter!");
420 assert(
421 !AI.getIndirectRealign() &&
422 "Unexpected IndirectRealign seen in arginfo in generic VAArg emitter!");
423
424 auto TyInfo = CGF.getContext().getTypeInfoInChars(T: Ty);
425 CharUnits TyAlignForABI = TyInfo.Align;
426
427 llvm::Type *ElementTy = CGF.ConvertTypeForMem(T: Ty);
428 llvm::Type *BaseTy = llvm::PointerType::getUnqual(C&: CGF.getLLVMContext());
429 llvm::Value *Addr =
430 CGF.Builder.CreateVAArg(List: VAListAddr.emitRawPointer(CGF), Ty: BaseTy);
431 return Address(Addr, ElementTy, TyAlignForABI);
432 } else {
433 assert((AI.isDirect() || AI.isExtend()) &&
434 "Unexpected ArgInfo Kind in generic VAArg emitter!");
435
436 assert(!AI.getInReg() &&
437 "Unexpected InReg seen in arginfo in generic VAArg emitter!");
438 assert(!AI.getPaddingType() &&
439 "Unexpected PaddingType seen in arginfo in generic VAArg emitter!");
440 assert(!AI.getDirectOffset() &&
441 "Unexpected DirectOffset seen in arginfo in generic VAArg emitter!");
442 assert(!AI.getCoerceToType() &&
443 "Unexpected CoerceToType seen in arginfo in generic VAArg emitter!");
444
445 Address Temp = CGF.CreateMemTemp(T: Ty, Name: "varet");
446 Val = CGF.Builder.CreateVAArg(List: VAListAddr.emitRawPointer(CGF),
447 Ty: CGF.ConvertTypeForMem(T: Ty));
448 CGF.Builder.CreateStore(Val, Addr: Temp);
449 return Temp;
450 }
451}
452
453bool CodeGen::isSIMDVectorType(ASTContext &Context, QualType Ty) {
454 return Ty->getAs<VectorType>() && Context.getTypeSize(T: Ty) == 128;
455}
456
457bool CodeGen::isRecordWithSIMDVectorType(ASTContext &Context, QualType Ty) {
458 const auto *RD = Ty->getAsRecordDecl();
459 if (!RD)
460 return false;
461
462 // If this is a C++ record, check the bases first.
463 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(Val: RD))
464 for (const auto &I : CXXRD->bases())
465 if (!isRecordWithSIMDVectorType(Context, Ty: I.getType()))
466 return false;
467
468 for (const auto *i : RD->fields()) {
469 QualType FT = i->getType();
470
471 if (isSIMDVectorType(Context, Ty: FT))
472 return true;
473
474 if (isRecordWithSIMDVectorType(Context, Ty: FT))
475 return true;
476 }
477
478 return false;
479}
480