1263508Sdim//===----- CGCXXABI.cpp - Interface to C++ ABIs ---------------------------===//
2218887Sdim//
3218887Sdim//                     The LLVM Compiler Infrastructure
4218887Sdim//
5218887Sdim// This file is distributed under the University of Illinois Open Source
6218887Sdim// License. See LICENSE.TXT for details.
7218887Sdim//
8218887Sdim//===----------------------------------------------------------------------===//
9218887Sdim//
10218887Sdim// This provides an abstract class for C++ code generation. Concrete subclasses
11218887Sdim// of this implement code generation for specific C++ ABIs.
12218887Sdim//
13218887Sdim//===----------------------------------------------------------------------===//
14218887Sdim
15218887Sdim#include "CGCXXABI.h"
16218887Sdim
17218887Sdimusing namespace clang;
18218887Sdimusing namespace CodeGen;
19218887Sdim
20218887SdimCGCXXABI::~CGCXXABI() { }
21218887Sdim
22249423Sdimvoid CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) {
23226633Sdim  DiagnosticsEngine &Diags = CGF.CGM.getDiags();
24226633Sdim  unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
25239462Sdim                                          "cannot yet compile %0 in this ABI");
26218887Sdim  Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()),
27218887Sdim               DiagID)
28218887Sdim    << S;
29218887Sdim}
30218887Sdim
31249423Sdimllvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) {
32218887Sdim  return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T));
33218887Sdim}
34218887Sdim
35224145Sdimllvm::Type *
36218887SdimCGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
37218887Sdim  return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
38218887Sdim}
39218887Sdim
40218887Sdimllvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
41218887Sdim                                                       llvm::Value *&This,
42218887Sdim                                                       llvm::Value *MemPtr,
43218887Sdim                                                 const MemberPointerType *MPT) {
44218887Sdim  ErrorUnsupportedABI(CGF, "calls through member pointers");
45218887Sdim
46218887Sdim  const FunctionProtoType *FPT =
47218887Sdim    MPT->getPointeeType()->getAs<FunctionProtoType>();
48218887Sdim  const CXXRecordDecl *RD =
49218887Sdim    cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
50234353Sdim  llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
51234353Sdim                              CGM.getTypes().arrangeCXXMethodType(RD, FPT));
52218887Sdim  return llvm::Constant::getNullValue(FTy->getPointerTo());
53218887Sdim}
54218887Sdim
55218887Sdimllvm::Value *CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
56218887Sdim                                                    llvm::Value *Base,
57218887Sdim                                                    llvm::Value *MemPtr,
58218887Sdim                                              const MemberPointerType *MPT) {
59218887Sdim  ErrorUnsupportedABI(CGF, "loads of member pointers");
60226633Sdim  llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType())->getPointerTo();
61218887Sdim  return llvm::Constant::getNullValue(Ty);
62218887Sdim}
63218887Sdim
64218887Sdimllvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
65218887Sdim                                                   const CastExpr *E,
66218887Sdim                                                   llvm::Value *Src) {
67218887Sdim  ErrorUnsupportedABI(CGF, "member function pointer conversions");
68249423Sdim  return GetBogusMemberPointer(E->getType());
69218887Sdim}
70218887Sdim
71234353Sdimllvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E,
72234353Sdim                                                      llvm::Constant *Src) {
73249423Sdim  return GetBogusMemberPointer(E->getType());
74234353Sdim}
75234353Sdim
76218887Sdimllvm::Value *
77218887SdimCGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
78218887Sdim                                      llvm::Value *L,
79218887Sdim                                      llvm::Value *R,
80218887Sdim                                      const MemberPointerType *MPT,
81218887Sdim                                      bool Inequality) {
82218887Sdim  ErrorUnsupportedABI(CGF, "member function pointer comparison");
83218887Sdim  return CGF.Builder.getFalse();
84218887Sdim}
85218887Sdim
86218887Sdimllvm::Value *
87218887SdimCGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
88218887Sdim                                     llvm::Value *MemPtr,
89218887Sdim                                     const MemberPointerType *MPT) {
90218887Sdim  ErrorUnsupportedABI(CGF, "member function pointer null testing");
91218887Sdim  return CGF.Builder.getFalse();
92218887Sdim}
93218887Sdim
94218887Sdimllvm::Constant *
95218887SdimCGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
96249423Sdim  return GetBogusMemberPointer(QualType(MPT, 0));
97218887Sdim}
98218887Sdim
99218887Sdimllvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
100249423Sdim  return GetBogusMemberPointer(
101218887Sdim                         CGM.getContext().getMemberPointerType(MD->getType(),
102218887Sdim                                         MD->getParent()->getTypeForDecl()));
103218887Sdim}
104218887Sdim
105218887Sdimllvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
106218887Sdim                                                CharUnits offset) {
107249423Sdim  return GetBogusMemberPointer(QualType(MPT, 0));
108218887Sdim}
109218887Sdim
110234353Sdimllvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) {
111249423Sdim  return GetBogusMemberPointer(MPT);
112234353Sdim}
113234353Sdim
114218887Sdimbool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
115218887Sdim  // Fake answer.
116218887Sdim  return true;
117218887Sdim}
118218887Sdim
119221345Sdimvoid CGCXXABI::BuildThisParam(CodeGenFunction &CGF, FunctionArgList &params) {
120218887Sdim  const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
121218887Sdim
122218887Sdim  // FIXME: I'm not entirely sure I like using a fake decl just for code
123218887Sdim  // generation. Maybe we can come up with a better way?
124218887Sdim  ImplicitParamDecl *ThisDecl
125218887Sdim    = ImplicitParamDecl::Create(CGM.getContext(), 0, MD->getLocation(),
126218887Sdim                                &CGM.getContext().Idents.get("this"),
127218887Sdim                                MD->getThisType(CGM.getContext()));
128221345Sdim  params.push_back(ThisDecl);
129218887Sdim  getThisDecl(CGF) = ThisDecl;
130218887Sdim}
131218887Sdim
132218887Sdimvoid CGCXXABI::EmitThisParam(CodeGenFunction &CGF) {
133218887Sdim  /// Initialize the 'this' slot.
134218887Sdim  assert(getThisDecl(CGF) && "no 'this' variable for function");
135218887Sdim  getThisValue(CGF)
136218887Sdim    = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
137218887Sdim                             "this");
138218887Sdim}
139218887Sdim
140218887Sdimvoid CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
141218887Sdim                                   RValue RV, QualType ResultType) {
142218887Sdim  CGF.EmitReturnOfRValue(RV, ResultType);
143218887Sdim}
144218887Sdim
145218887SdimCharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
146239462Sdim  if (!requiresArrayCookie(expr))
147239462Sdim    return CharUnits::Zero();
148239462Sdim  return getArrayCookieSizeImpl(expr->getAllocatedType());
149239462Sdim}
150239462Sdim
151239462SdimCharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) {
152239462Sdim  // BOGUS
153218887Sdim  return CharUnits::Zero();
154218887Sdim}
155218887Sdim
156218887Sdimllvm::Value *CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
157218887Sdim                                             llvm::Value *NewPtr,
158218887Sdim                                             llvm::Value *NumElements,
159218887Sdim                                             const CXXNewExpr *expr,
160218887Sdim                                             QualType ElementType) {
161218887Sdim  // Should never be called.
162218887Sdim  ErrorUnsupportedABI(CGF, "array cookie initialization");
163218887Sdim  return 0;
164218887Sdim}
165218887Sdim
166239462Sdimbool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
167239462Sdim                                   QualType elementType) {
168239462Sdim  // If the class's usual deallocation function takes two arguments,
169239462Sdim  // it needs a cookie.
170239462Sdim  if (expr->doesUsualArrayDeleteWantSize())
171239462Sdim    return true;
172218887Sdim
173239462Sdim  return elementType.isDestructedType();
174218887Sdim}
175218887Sdim
176239462Sdimbool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
177239462Sdim  // If the class's usual deallocation function takes two arguments,
178239462Sdim  // it needs a cookie.
179239462Sdim  if (expr->doesUsualArrayDeleteWantSize())
180239462Sdim    return true;
181239462Sdim
182239462Sdim  return expr->getAllocatedType().isDestructedType();
183239462Sdim}
184239462Sdim
185239462Sdimvoid CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *ptr,
186239462Sdim                               const CXXDeleteExpr *expr, QualType eltTy,
187239462Sdim                               llvm::Value *&numElements,
188239462Sdim                               llvm::Value *&allocPtr, CharUnits &cookieSize) {
189239462Sdim  // Derive a char* in the same address space as the pointer.
190243830Sdim  unsigned AS = ptr->getType()->getPointerAddressSpace();
191239462Sdim  llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS);
192239462Sdim  ptr = CGF.Builder.CreateBitCast(ptr, charPtrTy);
193239462Sdim
194239462Sdim  // If we don't need an array cookie, bail out early.
195239462Sdim  if (!requiresArrayCookie(expr, eltTy)) {
196239462Sdim    allocPtr = ptr;
197239462Sdim    numElements = 0;
198239462Sdim    cookieSize = CharUnits::Zero();
199239462Sdim    return;
200239462Sdim  }
201239462Sdim
202239462Sdim  cookieSize = getArrayCookieSizeImpl(eltTy);
203239462Sdim  allocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(ptr,
204239462Sdim                                                    -cookieSize.getQuantity());
205239462Sdim  numElements = readArrayCookieImpl(CGF, allocPtr, cookieSize);
206239462Sdim}
207239462Sdim
208239462Sdimllvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
209239462Sdim                                           llvm::Value *ptr,
210239462Sdim                                           CharUnits cookieSize) {
211239462Sdim  ErrorUnsupportedABI(CGF, "reading a new[] cookie");
212239462Sdim  return llvm::ConstantInt::get(CGF.SizeTy, 0);
213239462Sdim}
214239462Sdim
215239462Sdimvoid CGCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
216251662Sdim                                  const VarDecl &D,
217239462Sdim                                  llvm::Constant *dtor,
218239462Sdim                                  llvm::Constant *addr) {
219251662Sdim  if (D.getTLSKind())
220251662Sdim    CGM.ErrorUnsupported(&D, "non-trivial TLS destruction");
221251662Sdim
222239462Sdim  // The default behavior is to use atexit.
223263508Sdim  CGF.registerGlobalDtorWithAtExit(D, dtor, addr);
224239462Sdim}
225239462Sdim
226234353Sdim/// Returns the adjustment, in bytes, required for the given
227234353Sdim/// member-pointer operation.  Returns null if no adjustment is
228234353Sdim/// required.
229234353Sdimllvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) {
230234353Sdim  assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
231234353Sdim         E->getCastKind() == CK_BaseToDerivedMemberPointer);
232234353Sdim
233234353Sdim  QualType derivedType;
234234353Sdim  if (E->getCastKind() == CK_DerivedToBaseMemberPointer)
235234353Sdim    derivedType = E->getSubExpr()->getType();
236234353Sdim  else
237234353Sdim    derivedType = E->getType();
238234353Sdim
239234353Sdim  const CXXRecordDecl *derivedClass =
240234353Sdim    derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl();
241234353Sdim
242234353Sdim  return CGM.GetNonVirtualBaseClassOffset(derivedClass,
243234353Sdim                                          E->path_begin(),
244234353Sdim                                          E->path_end());
245234353Sdim}
246249423Sdim
247263508SdimCharUnits CGCXXABI::getMemberPointerPathAdjustment(const APValue &MP) {
248263508Sdim  // TODO: Store base specifiers in APValue member pointer paths so we can
249263508Sdim  // easily reuse CGM.GetNonVirtualBaseClassOffset().
250263508Sdim  const ValueDecl *MPD = MP.getMemberPointerDecl();
251263508Sdim  CharUnits ThisAdjustment = CharUnits::Zero();
252263508Sdim  ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath();
253263508Sdim  bool DerivedMember = MP.isMemberPointerToDerivedMember();
254263508Sdim  const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext());
255263508Sdim  for (unsigned I = 0, N = Path.size(); I != N; ++I) {
256263508Sdim    const CXXRecordDecl *Base = RD;
257263508Sdim    const CXXRecordDecl *Derived = Path[I];
258263508Sdim    if (DerivedMember)
259263508Sdim      std::swap(Base, Derived);
260263508Sdim    ThisAdjustment +=
261263508Sdim      getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base);
262263508Sdim    RD = Path[I];
263263508Sdim  }
264263508Sdim  if (DerivedMember)
265263508Sdim    ThisAdjustment = -ThisAdjustment;
266263508Sdim  return ThisAdjustment;
267263508Sdim}
268263508Sdim
269263508Sdimllvm::BasicBlock *
270263508SdimCGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
271263508Sdim                                        const CXXRecordDecl *RD) {
272249423Sdim  if (CGM.getTarget().getCXXABI().hasConstructorVariants())
273249423Sdim    llvm_unreachable("shouldn't be called in this ABI");
274249423Sdim
275249423Sdim  ErrorUnsupportedABI(CGF, "complete object detection in ctor");
276249423Sdim  return 0;
277249423Sdim}
278251662Sdim
279251662Sdimvoid CGCXXABI::EmitThreadLocalInitFuncs(
280251662Sdim    llvm::ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls,
281251662Sdim    llvm::Function *InitFunc) {
282251662Sdim}
283251662Sdim
284251662SdimLValue CGCXXABI::EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF,
285251662Sdim                                          const DeclRefExpr *DRE) {
286251662Sdim  ErrorUnsupportedABI(CGF, "odr-use of thread_local global");
287251662Sdim  return LValue();
288251662Sdim}
289263508Sdim
290263508Sdimbool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
291263508Sdim  return false;
292263508Sdim}
293