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