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 | |
11 | using namespace clang; |
12 | using namespace clang::CodeGen; |
13 | |
14 | // Pin the vtable to this file. |
15 | DefaultABIInfo::~DefaultABIInfo() = default; |
16 | |
17 | ABIArgInfo 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 | |
47 | ABIArgInfo 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 | |
70 | void 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 | |
77 | RValue 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 | |
85 | void 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 | |
96 | bool CodeGen::isAggregateTypeForABI(QualType T) { |
97 | return !CodeGenFunction::hasScalarEvaluationKind(T) || |
98 | T->isMemberFunctionPointerType(); |
99 | } |
100 | |
101 | llvm::Type *CodeGen::getVAListElementType(CodeGenFunction &CGF) { |
102 | return CGF.ConvertTypeForMem( |
103 | T: CGF.getContext().getBuiltinVaListType()->getPointeeType()); |
104 | } |
105 | |
106 | CGCXXABI::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 | |
117 | CGCXXABI::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 | |
124 | bool 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 | |
139 | QualType 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 | |
150 | llvm::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 | |
162 | Address |
163 | CodeGen::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 | |
199 | RValue 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 | |
233 | Address 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 | |
245 | bool 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 | |
286 | bool 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 | |
307 | bool 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 | |
318 | bool 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 | |
342 | const 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 | |
409 | Address 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 | |
458 | bool CodeGen::isSIMDVectorType(ASTContext &Context, QualType Ty) { |
459 | return Ty->getAs<VectorType>() && Context.getTypeSize(T: Ty) == 128; |
460 | } |
461 | |
462 | bool 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 | |