Clang Project

clang_source_code/lib/CodeGen/CGCXXABI.cpp
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
17using namespace clang;
18using namespace CodeGen;
19
20CGCXXABI::~CGCXXABI() { }
21
22void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGFStringRef 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
31bool CGCXXABI::canCopyArgument(const CXXRecordDecl *RDconst {
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
37llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) {
38  return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T));
39}
40
41llvm::Type *
42CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
43  return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
44}
45
46CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer(
47    CodeGenFunction &CGFconst Expr *EAddress This,
48    llvm::Value *&ThisPtrForCall,
49    llvm::Value *MemPtrconst 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(RDFPT/*FD=*/nullptr));
59  llvm::Constant *FnPtr = llvm::Constant::getNullValue(FTy->getPointerTo());
60  return CGCallee::forDirect(FnPtrFPT);
61}
62
63llvm::Value *
64CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGFconst Expr *E,
65                                       Address Basellvm::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
73llvm::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
80llvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E,
81                                                      llvm::Constant *Src) {
82  return GetBogusMemberPointer(E->getType());
83}
84
85llvm::Value *
86CGCXXABI::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
95llvm::Value *
96CGCXXABI::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
103llvm::Constant *
104CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
105  return GetBogusMemberPointer(QualType(MPT0));
106}
107
108llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
109  return GetBogusMemberPointer(CGM.getContext().getMemberPointerType(
110      MD->getType(), MD->getParent()->getTypeForDecl()));
111}
112
113llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
114                                                CharUnits offset) {
115  return GetBogusMemberPointer(QualType(MPT0));
116}
117
118llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MPQualType MPT) {
119  return GetBogusMemberPointer(MPT);
120}
121
122bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
123  // Fake answer.
124  return true;
125}
126
127void CGCXXABI::buildThisParam(CodeGenFunction &CGFFunctionArgList &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(), nullptrMD->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
151llvm::Value *CGCXXABI::loadIncomingCXXThis(CodeGenFunction &CGF) {
152  return CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
153                                "this");
154}
155
156void CGCXXABI::setCXXABIThisValue(CodeGenFunction &CGFllvm::Value *ThisPtr) {
157  /// Initialize the 'this' slot.
158   (0) . __assert_fail ("getThisDecl(CGF) && \"no 'this' variable for function\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCXXABI.cpp", 158, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(getThisDecl(CGF) && "no 'this' variable for function");
159  CGF.CXXABIThisValue = ThisPtr;
160}
161
162void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
163                                   RValue RVQualType ResultType) {
164  CGF.EmitReturnOfRValue(RVResultType);
165}
166
167CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
168  if (!requiresArrayCookie(expr))
169    return CharUnits::Zero();
170  return getArrayCookieSizeImpl(expr->getAllocatedType());
171}
172
173CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) {
174  // BOGUS
175  return CharUnits::Zero();
176}
177
178Address 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
188bool 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
198bool 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
207void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGFAddress ptr,
208                               const CXXDeleteExpr *exprQualType eltTy,
209                               llvm::Value *&numElements,
210                               llvm::Value *&allocPtrCharUnits &cookieSize) {
211  // Derive a char* in the same address space as the pointer.
212  ptr = CGF.Builder.CreateElementBitCast(ptrCGF.Int8Ty);
213
214  // If we don't need an array cookie, bail out early.
215  if (!requiresArrayCookie(expreltTy)) {
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(CGFallocAddrcookieSize);
227}
228
229llvm::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.
239llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) {
240  getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCXXABI.cpp", 241, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
241getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCXXABI.cpp", 241, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">         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
257CharUnits 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 = 0N = Path.size(); I != N; ++I) {
266    const CXXRecordDecl *Base = RD;
267    const CXXRecordDecl *Derived = Path[I];
268    if (DerivedMember)
269      std::swap(BaseDerived);
270    ThisAdjustment +=
271      getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base);
272    RD = Path[I];
273  }
274  if (DerivedMember)
275    ThisAdjustment = -ThisAdjustment;
276  return ThisAdjustment;
277}
278
279llvm::BasicBlock *
280CGCXXABI::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
289void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
290                                          const CXXDestructorDecl *Dtor,
291                                          CXXDtorType DTconst {
292  // Assume the base C++ ABI has no special rules for destructor variants.
293  CGM.setDLLImportDLLExport(GVDtor);
294}
295
296llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage(
297    GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const {
298  // Delegate back to CGM by default.
299  return CGM.getLLVMLinkageForDeclarator(DtorLinkage,
300                                         /*isConstantVariable=*/false);
301}
302
303bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
304  return false;
305}
306
307llvm::CallInst *
308CGCXXABI::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
314CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() {
315  return CatchTypeInfo{nullptr0};
316}
317
318std::vector<CharUnitsCGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) {
319  return std::vector<CharUnits>();
320}
321
clang::CodeGen::CGCXXABI::ErrorUnsupportedABI
clang::CodeGen::CGCXXABI::canCopyArgument
clang::CodeGen::CGCXXABI::GetBogusMemberPointer
clang::CodeGen::CGCXXABI::ConvertMemberPointerType
clang::CodeGen::CGCXXABI::EmitLoadOfMemberFunctionPointer
clang::CodeGen::CGCXXABI::EmitMemberDataPointerAddress
clang::CodeGen::CGCXXABI::EmitMemberPointerConversion
clang::CodeGen::CGCXXABI::EmitMemberPointerConversion
clang::CodeGen::CGCXXABI::EmitMemberPointerComparison
clang::CodeGen::CGCXXABI::EmitMemberPointerIsNotNull
clang::CodeGen::CGCXXABI::EmitNullMemberPointer
clang::CodeGen::CGCXXABI::EmitMemberFunctionPointer
clang::CodeGen::CGCXXABI::EmitMemberDataPointer
clang::CodeGen::CGCXXABI::EmitMemberPointer
clang::CodeGen::CGCXXABI::isZeroInitializable
clang::CodeGen::CGCXXABI::buildThisParam
clang::CodeGen::CGCXXABI::loadIncomingCXXThis
clang::CodeGen::CGCXXABI::setCXXABIThisValue
clang::CodeGen::CGCXXABI::EmitReturnFromThunk
clang::CodeGen::CGCXXABI::GetArrayCookieSize
clang::CodeGen::CGCXXABI::getArrayCookieSizeImpl
clang::CodeGen::CGCXXABI::InitializeArrayCookie
clang::CodeGen::CGCXXABI::requiresArrayCookie
clang::CodeGen::CGCXXABI::requiresArrayCookie
clang::CodeGen::CGCXXABI::ReadArrayCookie
clang::CodeGen::CGCXXABI::readArrayCookieImpl
clang::CodeGen::CGCXXABI::getMemberPointerAdjustment
clang::CodeGen::CGCXXABI::getMemberPointerPathAdjustment
clang::CodeGen::CGCXXABI::EmitCtorCompleteObjectHandler
clang::CodeGen::CGCXXABI::setCXXDestructorDLLStorage
clang::CodeGen::CGCXXABI::getCXXDestructorLinkage
clang::CodeGen::CGCXXABI::NeedsVTTParameter
clang::CodeGen::CGCXXABI::emitTerminateForUnexpectedException
clang::CodeGen::CGCXXABI::getCatchAllTypeInfo
clang::CodeGen::CGCXXABI::getVBPtrOffsets