Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/CodeGen/CGCXXABI.cpp
35233 views
1
//===----- CGCXXABI.cpp - Interface to C++ ABIs ---------------------------===//
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
// This provides an abstract class for C++ code generation. Concrete subclasses
10
// of this implement code generation for specific C++ ABIs.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "CGCXXABI.h"
15
#include "CGCleanup.h"
16
#include "clang/AST/Attr.h"
17
18
using namespace clang;
19
using namespace CodeGen;
20
21
CGCXXABI::~CGCXXABI() { }
22
23
Address CGCXXABI::getThisAddress(CodeGenFunction &CGF) {
24
return CGF.makeNaturalAddressForPointer(
25
CGF.CXXABIThisValue, CGF.CXXABIThisDecl->getType()->getPointeeType(),
26
CGF.CXXABIThisAlignment);
27
}
28
29
void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) {
30
DiagnosticsEngine &Diags = CGF.CGM.getDiags();
31
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
32
"cannot yet compile %0 in this ABI");
33
Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()),
34
DiagID)
35
<< S;
36
}
37
38
llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) {
39
return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T));
40
}
41
42
llvm::Type *
43
CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
44
return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
45
}
46
47
CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer(
48
CodeGenFunction &CGF, const Expr *E, Address This,
49
llvm::Value *&ThisPtrForCall,
50
llvm::Value *MemPtr, const MemberPointerType *MPT) {
51
ErrorUnsupportedABI(CGF, "calls through member pointers");
52
53
const auto *RD =
54
cast<CXXRecordDecl>(MPT->getClass()->castAs<RecordType>()->getDecl());
55
ThisPtrForCall =
56
CGF.getAsNaturalPointerTo(This, CGF.getContext().getRecordType(RD));
57
const FunctionProtoType *FPT =
58
MPT->getPointeeType()->getAs<FunctionProtoType>();
59
llvm::Constant *FnPtr = llvm::Constant::getNullValue(
60
llvm::PointerType::getUnqual(CGM.getLLVMContext()));
61
return CGCallee::forDirect(FnPtr, FPT);
62
}
63
64
llvm::Value *
65
CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
66
Address Base, llvm::Value *MemPtr,
67
const MemberPointerType *MPT) {
68
ErrorUnsupportedABI(CGF, "loads of member pointers");
69
llvm::Type *Ty =
70
llvm::PointerType::get(CGF.getLLVMContext(), Base.getAddressSpace());
71
return llvm::Constant::getNullValue(Ty);
72
}
73
74
llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
75
const CastExpr *E,
76
llvm::Value *Src) {
77
ErrorUnsupportedABI(CGF, "member function pointer conversions");
78
return GetBogusMemberPointer(E->getType());
79
}
80
81
llvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E,
82
llvm::Constant *Src) {
83
return GetBogusMemberPointer(E->getType());
84
}
85
86
llvm::Value *
87
CGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
88
llvm::Value *L,
89
llvm::Value *R,
90
const MemberPointerType *MPT,
91
bool Inequality) {
92
ErrorUnsupportedABI(CGF, "member function pointer comparison");
93
return CGF.Builder.getFalse();
94
}
95
96
llvm::Value *
97
CGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
98
llvm::Value *MemPtr,
99
const MemberPointerType *MPT) {
100
ErrorUnsupportedABI(CGF, "member function pointer null testing");
101
return CGF.Builder.getFalse();
102
}
103
104
llvm::Constant *
105
CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
106
return GetBogusMemberPointer(QualType(MPT, 0));
107
}
108
109
llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
110
return GetBogusMemberPointer(CGM.getContext().getMemberPointerType(
111
MD->getType(), MD->getParent()->getTypeForDecl()));
112
}
113
114
llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
115
CharUnits offset) {
116
return GetBogusMemberPointer(QualType(MPT, 0));
117
}
118
119
llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) {
120
return GetBogusMemberPointer(MPT);
121
}
122
123
bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
124
// Fake answer.
125
return true;
126
}
127
128
void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList &params) {
129
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
130
131
// FIXME: I'm not entirely sure I like using a fake decl just for code
132
// generation. Maybe we can come up with a better way?
133
auto *ThisDecl =
134
ImplicitParamDecl::Create(CGM.getContext(), nullptr, MD->getLocation(),
135
&CGM.getContext().Idents.get("this"),
136
MD->getThisType(), ImplicitParamKind::CXXThis);
137
params.push_back(ThisDecl);
138
CGF.CXXABIThisDecl = ThisDecl;
139
140
// Compute the presumed alignment of 'this', which basically comes
141
// down to whether we know it's a complete object or not.
142
auto &Layout = CGF.getContext().getASTRecordLayout(MD->getParent());
143
if (MD->getParent()->getNumVBases() == 0 || // avoid vcall in common case
144
MD->getParent()->isEffectivelyFinal() ||
145
isThisCompleteObject(CGF.CurGD)) {
146
CGF.CXXABIThisAlignment = Layout.getAlignment();
147
} else {
148
CGF.CXXABIThisAlignment = Layout.getNonVirtualAlignment();
149
}
150
}
151
152
llvm::Value *CGCXXABI::loadIncomingCXXThis(CodeGenFunction &CGF) {
153
return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
154
"this");
155
}
156
157
void CGCXXABI::setCXXABIThisValue(CodeGenFunction &CGF, llvm::Value *ThisPtr) {
158
/// Initialize the 'this' slot.
159
assert(getThisDecl(CGF) && "no 'this' variable for function");
160
CGF.CXXABIThisValue = ThisPtr;
161
}
162
163
bool CGCXXABI::mayNeedDestruction(const VarDecl *VD) const {
164
if (VD->needsDestruction(getContext()))
165
return true;
166
167
// If the variable has an incomplete class type (or array thereof), it
168
// might need destruction.
169
const Type *T = VD->getType()->getBaseElementTypeUnsafe();
170
if (T->getAs<RecordType>() && T->isIncompleteType())
171
return true;
172
173
return false;
174
}
175
176
bool CGCXXABI::isEmittedWithConstantInitializer(
177
const VarDecl *VD, bool InspectInitForWeakDef) const {
178
VD = VD->getMostRecentDecl();
179
if (VD->hasAttr<ConstInitAttr>())
180
return true;
181
182
// All later checks examine the initializer specified on the variable. If
183
// the variable is weak, such examination would not be correct.
184
if (!InspectInitForWeakDef && (VD->isWeak() || VD->hasAttr<SelectAnyAttr>()))
185
return false;
186
187
const VarDecl *InitDecl = VD->getInitializingDeclaration();
188
if (!InitDecl)
189
return false;
190
191
// If there's no initializer to run, this is constant initialization.
192
if (!InitDecl->hasInit())
193
return true;
194
195
// If we have the only definition, we don't need a thread wrapper if we
196
// will emit the value as a constant.
197
if (isUniqueGVALinkage(getContext().GetGVALinkageForVariable(VD)))
198
return !mayNeedDestruction(VD) && InitDecl->evaluateValue();
199
200
// Otherwise, we need a thread wrapper unless we know that every
201
// translation unit will emit the value as a constant. We rely on the
202
// variable being constant-initialized in every translation unit if it's
203
// constant-initialized in any translation unit, which isn't actually
204
// guaranteed by the standard but is necessary for sanity.
205
return InitDecl->hasConstantInitialization();
206
}
207
208
void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
209
RValue RV, QualType ResultType) {
210
assert(!CGF.hasAggregateEvaluationKind(ResultType) &&
211
"cannot handle aggregates");
212
CGF.EmitReturnOfRValue(RV, ResultType);
213
}
214
215
CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
216
if (!requiresArrayCookie(expr))
217
return CharUnits::Zero();
218
return getArrayCookieSizeImpl(expr->getAllocatedType());
219
}
220
221
CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) {
222
// BOGUS
223
return CharUnits::Zero();
224
}
225
226
Address CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
227
Address NewPtr,
228
llvm::Value *NumElements,
229
const CXXNewExpr *expr,
230
QualType ElementType) {
231
// Should never be called.
232
ErrorUnsupportedABI(CGF, "array cookie initialization");
233
return Address::invalid();
234
}
235
236
bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
237
QualType elementType) {
238
// If the class's usual deallocation function takes two arguments,
239
// it needs a cookie.
240
if (expr->doesUsualArrayDeleteWantSize())
241
return true;
242
243
return elementType.isDestructedType();
244
}
245
246
bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
247
// If the class's usual deallocation function takes two arguments,
248
// it needs a cookie.
249
if (expr->doesUsualArrayDeleteWantSize())
250
return true;
251
252
return expr->getAllocatedType().isDestructedType();
253
}
254
255
void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr,
256
const CXXDeleteExpr *expr, QualType eltTy,
257
llvm::Value *&numElements,
258
llvm::Value *&allocPtr, CharUnits &cookieSize) {
259
// Derive a char* in the same address space as the pointer.
260
ptr = ptr.withElementType(CGF.Int8Ty);
261
262
// If we don't need an array cookie, bail out early.
263
if (!requiresArrayCookie(expr, eltTy)) {
264
allocPtr = ptr.emitRawPointer(CGF);
265
numElements = nullptr;
266
cookieSize = CharUnits::Zero();
267
return;
268
}
269
270
cookieSize = getArrayCookieSizeImpl(eltTy);
271
Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize);
272
allocPtr = allocAddr.emitRawPointer(CGF);
273
numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize);
274
}
275
276
llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
277
Address ptr,
278
CharUnits cookieSize) {
279
ErrorUnsupportedABI(CGF, "reading a new[] cookie");
280
return llvm::ConstantInt::get(CGF.SizeTy, 0);
281
}
282
283
/// Returns the adjustment, in bytes, required for the given
284
/// member-pointer operation. Returns null if no adjustment is
285
/// required.
286
llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) {
287
assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
288
E->getCastKind() == CK_BaseToDerivedMemberPointer);
289
290
QualType derivedType;
291
if (E->getCastKind() == CK_DerivedToBaseMemberPointer)
292
derivedType = E->getSubExpr()->getType();
293
else
294
derivedType = E->getType();
295
296
const CXXRecordDecl *derivedClass =
297
derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl();
298
299
return CGM.GetNonVirtualBaseClassOffset(derivedClass,
300
E->path_begin(),
301
E->path_end());
302
}
303
304
llvm::BasicBlock *
305
CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
306
const CXXRecordDecl *RD) {
307
if (CGM.getTarget().getCXXABI().hasConstructorVariants())
308
llvm_unreachable("shouldn't be called in this ABI");
309
310
ErrorUnsupportedABI(CGF, "complete object detection in ctor");
311
return nullptr;
312
}
313
314
void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
315
const CXXDestructorDecl *Dtor,
316
CXXDtorType DT) const {
317
// Assume the base C++ ABI has no special rules for destructor variants.
318
CGM.setDLLImportDLLExport(GV, Dtor);
319
}
320
321
llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage(
322
GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const {
323
// Delegate back to CGM by default.
324
return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage);
325
}
326
327
bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
328
return false;
329
}
330
331
llvm::CallInst *
332
CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
333
llvm::Value *Exn) {
334
// Just call std::terminate and ignore the violating exception.
335
return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn());
336
}
337
338
CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() {
339
return CatchTypeInfo{nullptr, 0};
340
}
341
342
std::vector<CharUnits> CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) {
343
return std::vector<CharUnits>();
344
}
345
346
CGCXXABI::AddedStructorArgCounts CGCXXABI::addImplicitConstructorArgs(
347
CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,
348
bool ForVirtualBase, bool Delegating, CallArgList &Args) {
349
AddedStructorArgs AddedArgs =
350
getImplicitConstructorArgs(CGF, D, Type, ForVirtualBase, Delegating);
351
for (size_t i = 0; i < AddedArgs.Prefix.size(); ++i) {
352
Args.insert(Args.begin() + 1 + i,
353
CallArg(RValue::get(AddedArgs.Prefix[i].Value),
354
AddedArgs.Prefix[i].Type));
355
}
356
for (const auto &arg : AddedArgs.Suffix) {
357
Args.add(RValue::get(arg.Value), arg.Type);
358
}
359
return AddedStructorArgCounts(AddedArgs.Prefix.size(),
360
AddedArgs.Suffix.size());
361
}
362
363