Coverage Report

Created: 2020-02-25 14:32

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