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