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

source code of clang/lib/CodeGen/ABIInfoImpl.cpp