CGCXXABI.cpp revision c7971a9efdf9880448a69aabb5182c3c27eecf6d
1//===----- CGCXXABI.cpp - Interface to C++ ABIs -----------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This provides an abstract class for C++ code generation. Concrete subclasses
11// of this implement code generation for specific C++ ABIs.
12//
13//===----------------------------------------------------------------------===//
14
15#include "CGCXXABI.h"
16
17using namespace clang;
18using namespace CodeGen;
19
20CGCXXABI::~CGCXXABI() { }
21
22void 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
31llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) {
32  return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T));
33}
34
35llvm::Type *
36CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
37  return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
38}
39
40llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
41                                                       llvm::Value *&This,
42                                                       llvm::Value *MemPtr,
43                                                 const MemberPointerType *MPT) {
44  ErrorUnsupportedABI(CGF, "calls through member pointers");
45
46  const FunctionProtoType *FPT =
47    MPT->getPointeeType()->getAs<FunctionProtoType>();
48  const CXXRecordDecl *RD =
49    cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
50  llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
51                              CGM.getTypes().arrangeCXXMethodType(RD, FPT));
52  return llvm::Constant::getNullValue(FTy->getPointerTo());
53}
54
55llvm::Value *CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
56                                                    llvm::Value *Base,
57                                                    llvm::Value *MemPtr,
58                                              const MemberPointerType *MPT) {
59  ErrorUnsupportedABI(CGF, "loads of member pointers");
60  llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType())->getPointerTo();
61  return llvm::Constant::getNullValue(Ty);
62}
63
64llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
65                                                   const CastExpr *E,
66                                                   llvm::Value *Src) {
67  ErrorUnsupportedABI(CGF, "member function pointer conversions");
68  return GetBogusMemberPointer(E->getType());
69}
70
71llvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E,
72                                                      llvm::Constant *Src) {
73  return GetBogusMemberPointer(E->getType());
74}
75
76llvm::Value *
77CGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
78                                      llvm::Value *L,
79                                      llvm::Value *R,
80                                      const MemberPointerType *MPT,
81                                      bool Inequality) {
82  ErrorUnsupportedABI(CGF, "member function pointer comparison");
83  return CGF.Builder.getFalse();
84}
85
86llvm::Value *
87CGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
88                                     llvm::Value *MemPtr,
89                                     const MemberPointerType *MPT) {
90  ErrorUnsupportedABI(CGF, "member function pointer null testing");
91  return CGF.Builder.getFalse();
92}
93
94llvm::Constant *
95CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
96  return GetBogusMemberPointer(QualType(MPT, 0));
97}
98
99llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
100  return GetBogusMemberPointer(
101                         CGM.getContext().getMemberPointerType(MD->getType(),
102                                         MD->getParent()->getTypeForDecl()));
103}
104
105llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
106                                                CharUnits offset) {
107  return GetBogusMemberPointer(QualType(MPT, 0));
108}
109
110llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) {
111  return GetBogusMemberPointer(MPT);
112}
113
114bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
115  // Fake answer.
116  return true;
117}
118
119void CGCXXABI::BuildThisParam(CodeGenFunction &CGF, FunctionArgList &params) {
120  const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
121
122  // FIXME: I'm not entirely sure I like using a fake decl just for code
123  // generation. Maybe we can come up with a better way?
124  ImplicitParamDecl *ThisDecl
125    = ImplicitParamDecl::Create(CGM.getContext(), 0, MD->getLocation(),
126                                &CGM.getContext().Idents.get("this"),
127                                MD->getThisType(CGM.getContext()));
128  params.push_back(ThisDecl);
129  getThisDecl(CGF) = ThisDecl;
130}
131
132void CGCXXABI::EmitThisParam(CodeGenFunction &CGF) {
133  /// Initialize the 'this' slot.
134  assert(getThisDecl(CGF) && "no 'this' variable for function");
135  getThisValue(CGF)
136    = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
137                             "this");
138}
139
140void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
141                                   RValue RV, QualType ResultType) {
142  CGF.EmitReturnOfRValue(RV, ResultType);
143}
144
145CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
146  if (!requiresArrayCookie(expr))
147    return CharUnits::Zero();
148  return getArrayCookieSizeImpl(expr->getAllocatedType());
149}
150
151CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) {
152  // BOGUS
153  return CharUnits::Zero();
154}
155
156llvm::Value *CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
157                                             llvm::Value *NewPtr,
158                                             llvm::Value *NumElements,
159                                             const CXXNewExpr *expr,
160                                             QualType ElementType) {
161  // Should never be called.
162  ErrorUnsupportedABI(CGF, "array cookie initialization");
163  return 0;
164}
165
166bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
167                                   QualType elementType) {
168  // If the class's usual deallocation function takes two arguments,
169  // it needs a cookie.
170  if (expr->doesUsualArrayDeleteWantSize())
171    return true;
172
173  return elementType.isDestructedType();
174}
175
176bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
177  // If the class's usual deallocation function takes two arguments,
178  // it needs a cookie.
179  if (expr->doesUsualArrayDeleteWantSize())
180    return true;
181
182  return expr->getAllocatedType().isDestructedType();
183}
184
185void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *ptr,
186                               const CXXDeleteExpr *expr, QualType eltTy,
187                               llvm::Value *&numElements,
188                               llvm::Value *&allocPtr, CharUnits &cookieSize) {
189  // Derive a char* in the same address space as the pointer.
190  unsigned AS = ptr->getType()->getPointerAddressSpace();
191  llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS);
192  ptr = CGF.Builder.CreateBitCast(ptr, charPtrTy);
193
194  // If we don't need an array cookie, bail out early.
195  if (!requiresArrayCookie(expr, eltTy)) {
196    allocPtr = ptr;
197    numElements = 0;
198    cookieSize = CharUnits::Zero();
199    return;
200  }
201
202  cookieSize = getArrayCookieSizeImpl(eltTy);
203  allocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(ptr,
204                                                    -cookieSize.getQuantity());
205  numElements = readArrayCookieImpl(CGF, allocPtr, cookieSize);
206}
207
208llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
209                                           llvm::Value *ptr,
210                                           CharUnits cookieSize) {
211  ErrorUnsupportedABI(CGF, "reading a new[] cookie");
212  return llvm::ConstantInt::get(CGF.SizeTy, 0);
213}
214
215void CGCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
216                               const VarDecl &D,
217                               llvm::GlobalVariable *GV,
218                               bool PerformInit) {
219  ErrorUnsupportedABI(CGF, "static local variable initialization");
220}
221
222void CGCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
223                                  const VarDecl &D,
224                                  llvm::Constant *dtor,
225                                  llvm::Constant *addr) {
226  if (D.getTLSKind())
227    CGM.ErrorUnsupported(&D, "non-trivial TLS destruction");
228
229  // The default behavior is to use atexit.
230  CGF.registerGlobalDtorWithAtExit(D, dtor, addr);
231}
232
233/// Returns the adjustment, in bytes, required for the given
234/// member-pointer operation.  Returns null if no adjustment is
235/// required.
236llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) {
237  assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
238         E->getCastKind() == CK_BaseToDerivedMemberPointer);
239
240  QualType derivedType;
241  if (E->getCastKind() == CK_DerivedToBaseMemberPointer)
242    derivedType = E->getSubExpr()->getType();
243  else
244    derivedType = E->getType();
245
246  const CXXRecordDecl *derivedClass =
247    derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl();
248
249  return CGM.GetNonVirtualBaseClassOffset(derivedClass,
250                                          E->path_begin(),
251                                          E->path_end());
252}
253
254CharUnits CGCXXABI::getMemberPointerPathAdjustment(const APValue &MP) {
255  // TODO: Store base specifiers in APValue member pointer paths so we can
256  // easily reuse CGM.GetNonVirtualBaseClassOffset().
257  const ValueDecl *MPD = MP.getMemberPointerDecl();
258  CharUnits ThisAdjustment = CharUnits::Zero();
259  ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath();
260  bool DerivedMember = MP.isMemberPointerToDerivedMember();
261  const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext());
262  for (unsigned I = 0, N = Path.size(); I != N; ++I) {
263    const CXXRecordDecl *Base = RD;
264    const CXXRecordDecl *Derived = Path[I];
265    if (DerivedMember)
266      std::swap(Base, Derived);
267    ThisAdjustment +=
268      getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base);
269    RD = Path[I];
270  }
271  if (DerivedMember)
272    ThisAdjustment = -ThisAdjustment;
273  return ThisAdjustment;
274}
275
276llvm::BasicBlock *
277CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
278                                        const CXXRecordDecl *RD) {
279  if (CGM.getTarget().getCXXABI().hasConstructorVariants())
280    llvm_unreachable("shouldn't be called in this ABI");
281
282  ErrorUnsupportedABI(CGF, "complete object detection in ctor");
283  return 0;
284}
285
286void CGCXXABI::EmitThreadLocalInitFuncs(
287    llvm::ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls,
288    llvm::Function *InitFunc) {
289}
290
291LValue CGCXXABI::EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF,
292                                          const DeclRefExpr *DRE) {
293  ErrorUnsupportedABI(CGF, "odr-use of thread_local global");
294  return LValue();
295}
296
297bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
298  return false;
299}
300