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