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