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