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 
17 using namespace clang;
18 using namespace CodeGen;
19 
20 CGCXXABI::~CGCXXABI() { }
21 
22 void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) {
23   DiagnosticsEngine &Diags = CGF.CGM.getDiags();
24   unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
25                                           "cannot yet compile %0 in this ABI");
26   Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()),
27                DiagID)
28     << S;
29 }
30 
31 bool CGCXXABI::canCopyArgument(const CXXRecordDecl *RD) const {
32   // We can only copy the argument if there exists at least one trivial,
33   // non-deleted copy or move constructor.
34   return RD->canPassInRegisters();
35 }
36 
37 llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) {
38   return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T));
39 }
40 
41 llvm::Type *
42 CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
43   return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
44 }
45 
46 CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer(
47     CodeGenFunction &CGF, const Expr *E, Address This,
48     llvm::Value *&ThisPtrForCall,
49     llvm::Value *MemPtr, const MemberPointerType *MPT) {
50   ErrorUnsupportedABI(CGF, "calls through member pointers");
51 
52   ThisPtrForCall = This.getPointer();
53   const FunctionProtoType *FPT =
54     MPT->getPointeeType()->getAs<FunctionProtoType>();
55   const CXXRecordDecl *RD =
56     cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
57   llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
58       CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr));
59   llvm::Constant *FnPtr = llvm::Constant::getNullValue(FTy->getPointerTo());
60   return CGCallee::forDirect(FnPtr, FPT);
61 }
62 
63 llvm::Value *
64 CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
65                                        Address Base, llvm::Value *MemPtr,
66                                        const MemberPointerType *MPT) {
67   ErrorUnsupportedABI(CGF, "loads of member pointers");
68   llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType())
69                          ->getPointerTo(Base.getAddressSpace());
70   return llvm::Constant::getNullValue(Ty);
71 }
72 
73 llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
74                                                    const CastExpr *E,
75                                                    llvm::Value *Src) {
76   ErrorUnsupportedABI(CGF, "member function pointer conversions");
77   return GetBogusMemberPointer(E->getType());
78 }
79 
80 llvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E,
81                                                       llvm::Constant *Src) {
82   return GetBogusMemberPointer(E->getType());
83 }
84 
85 llvm::Value *
86 CGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
87                                       llvm::Value *L,
88                                       llvm::Value *R,
89                                       const MemberPointerType *MPT,
90                                       bool Inequality) {
91   ErrorUnsupportedABI(CGF, "member function pointer comparison");
92   return CGF.Builder.getFalse();
93 }
94 
95 llvm::Value *
96 CGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
97                                      llvm::Value *MemPtr,
98                                      const MemberPointerType *MPT) {
99   ErrorUnsupportedABI(CGF, "member function pointer null testing");
100   return CGF.Builder.getFalse();
101 }
102 
103 llvm::Constant *
104 CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
105   return GetBogusMemberPointer(QualType(MPT, 0));
106 }
107 
108 llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
109   return GetBogusMemberPointer(CGM.getContext().getMemberPointerType(
110       MD->getType(), MD->getParent()->getTypeForDecl()));
111 }
112 
113 llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
114                                                 CharUnits offset) {
115   return GetBogusMemberPointer(QualType(MPT, 0));
116 }
117 
118 llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) {
119   return GetBogusMemberPointer(MPT);
120 }
121 
122 bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
123   // Fake answer.
124   return true;
125 }
126 
127 void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList &params) {
128   const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
129 
130   // FIXME: I'm not entirely sure I like using a fake decl just for code
131   // generation. Maybe we can come up with a better way?
132   auto *ThisDecl = ImplicitParamDecl::Create(
133       CGM.getContext(), nullptr, MD->getLocation(),
134       &CGM.getContext().Idents.get("this"), MD->getThisType(),
135       ImplicitParamDecl::CXXThis);
136   params.push_back(ThisDecl);
137   CGF.CXXABIThisDecl = ThisDecl;
138 
139   // Compute the presumed alignment of 'this', which basically comes
140   // down to whether we know it's a complete object or not.
141   auto &Layout = CGF.getContext().getASTRecordLayout(MD->getParent());
142   if (MD->getParent()->getNumVBases() == 0 || // avoid vcall in common case
143       MD->getParent()->hasAttr<FinalAttr>() ||
144       !isThisCompleteObject(CGF.CurGD)) {
145     CGF.CXXABIThisAlignment = Layout.getAlignment();
146   } else {
147     CGF.CXXABIThisAlignment = Layout.getNonVirtualAlignment();
148   }
149 }
150 
151 llvm::Value *CGCXXABI::loadIncomingCXXThis(CodeGenFunction &CGF) {
152   return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
153                                 "this");
154 }
155 
156 void CGCXXABI::setCXXABIThisValue(CodeGenFunction &CGF, llvm::Value *ThisPtr) {
157   /// Initialize the 'this' slot.
158   assert(getThisDecl(CGF) && "no 'this' variable for function");
159   CGF.CXXABIThisValue = ThisPtr;
160 }
161 
162 void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
163                                    RValue RV, QualType ResultType) {
164   CGF.EmitReturnOfRValue(RV, ResultType);
165 }
166 
167 CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
168   if (!requiresArrayCookie(expr))
169     return CharUnits::Zero();
170   return getArrayCookieSizeImpl(expr->getAllocatedType());
171 }
172 
173 CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) {
174   // BOGUS
175   return CharUnits::Zero();
176 }
177 
178 Address CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
179                                         Address NewPtr,
180                                         llvm::Value *NumElements,
181                                         const CXXNewExpr *expr,
182                                         QualType ElementType) {
183   // Should never be called.
184   ErrorUnsupportedABI(CGF, "array cookie initialization");
185   return Address::invalid();
186 }
187 
188 bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
189                                    QualType elementType) {
190   // If the class's usual deallocation function takes two arguments,
191   // it needs a cookie.
192   if (expr->doesUsualArrayDeleteWantSize())
193     return true;
194 
195   return elementType.isDestructedType();
196 }
197 
198 bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
199   // If the class's usual deallocation function takes two arguments,
200   // it needs a cookie.
201   if (expr->doesUsualArrayDeleteWantSize())
202     return true;
203 
204   return expr->getAllocatedType().isDestructedType();
205 }
206 
207 void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr,
208                                const CXXDeleteExpr *expr, QualType eltTy,
209                                llvm::Value *&numElements,
210                                llvm::Value *&allocPtr, CharUnits &cookieSize) {
211   // Derive a char* in the same address space as the pointer.
212   ptr = CGF.Builder.CreateElementBitCast(ptr, CGF.Int8Ty);
213 
214   // If we don't need an array cookie, bail out early.
215   if (!requiresArrayCookie(expr, eltTy)) {
216     allocPtr = ptr.getPointer();
217     numElements = nullptr;
218     cookieSize = CharUnits::Zero();
219     return;
220   }
221 
222   cookieSize = getArrayCookieSizeImpl(eltTy);
223   Address allocAddr =
224     CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize);
225   allocPtr = allocAddr.getPointer();
226   numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize);
227 }
228 
229 llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
230                                            Address ptr,
231                                            CharUnits cookieSize) {
232   ErrorUnsupportedABI(CGF, "reading a new[] cookie");
233   return llvm::ConstantInt::get(CGF.SizeTy, 0);
234 }
235 
236 /// Returns the adjustment, in bytes, required for the given
237 /// member-pointer operation.  Returns null if no adjustment is
238 /// required.
239 llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) {
240   assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
241          E->getCastKind() == CK_BaseToDerivedMemberPointer);
242 
243   QualType derivedType;
244   if (E->getCastKind() == CK_DerivedToBaseMemberPointer)
245     derivedType = E->getSubExpr()->getType();
246   else
247     derivedType = E->getType();
248 
249   const CXXRecordDecl *derivedClass =
250     derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl();
251 
252   return CGM.GetNonVirtualBaseClassOffset(derivedClass,
253                                           E->path_begin(),
254                                           E->path_end());
255 }
256 
257 CharUnits CGCXXABI::getMemberPointerPathAdjustment(const APValue &MP) {
258   // TODO: Store base specifiers in APValue member pointer paths so we can
259   // easily reuse CGM.GetNonVirtualBaseClassOffset().
260   const ValueDecl *MPD = MP.getMemberPointerDecl();
261   CharUnits ThisAdjustment = CharUnits::Zero();
262   ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath();
263   bool DerivedMember = MP.isMemberPointerToDerivedMember();
264   const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext());
265   for (unsigned I = 0, N = Path.size(); I != N; ++I) {
266     const CXXRecordDecl *Base = RD;
267     const CXXRecordDecl *Derived = Path[I];
268     if (DerivedMember)
269       std::swap(Base, Derived);
270     ThisAdjustment +=
271       getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base);
272     RD = Path[I];
273   }
274   if (DerivedMember)
275     ThisAdjustment = -ThisAdjustment;
276   return ThisAdjustment;
277 }
278 
279 llvm::BasicBlock *
280 CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
281                                         const CXXRecordDecl *RD) {
282   if (CGM.getTarget().getCXXABI().hasConstructorVariants())
283     llvm_unreachable("shouldn't be called in this ABI");
284 
285   ErrorUnsupportedABI(CGF, "complete object detection in ctor");
286   return nullptr;
287 }
288 
289 void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
290                                           const CXXDestructorDecl *Dtor,
291                                           CXXDtorType DT) const {
292   // Assume the base C++ ABI has no special rules for destructor variants.
293   CGM.setDLLImportDLLExport(GV, Dtor);
294 }
295 
296 llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage(
297     GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const {
298   // Delegate back to CGM by default.
299   return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage,
300                                          /*isConstantVariable=*/false);
301 }
302 
303 bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
304   return false;
305 }
306 
307 llvm::CallInst *
308 CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
309                                               llvm::Value *Exn) {
310   // Just call std::terminate and ignore the violating exception.
311   return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn());
312 }
313 
314 CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() {
315   return CatchTypeInfo{nullptr, 0};
316 }
317 
318 std::vector<CharUnits> CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) {
319   return std::vector<CharUnits>();
320 }
321