CGCXX.cpp revision 202379
1//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===//
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 contains code dealing with C++ code generation.
11//
12//===----------------------------------------------------------------------===//
13
14// We might split this into multiple files if it gets too unwieldy
15
16#include "CodeGenFunction.h"
17#include "CodeGenModule.h"
18#include "Mangle.h"
19#include "clang/AST/ASTContext.h"
20#include "clang/AST/RecordLayout.h"
21#include "clang/AST/Decl.h"
22#include "clang/AST/DeclCXX.h"
23#include "clang/AST/DeclObjC.h"
24#include "clang/AST/StmtCXX.h"
25#include "llvm/ADT/StringExtras.h"
26using namespace clang;
27using namespace CodeGen;
28
29
30
31llvm::Value *CodeGenFunction::LoadCXXThis() {
32  assert(isa<CXXMethodDecl>(CurFuncDecl) &&
33         "Must be in a C++ member function decl to load 'this'");
34  assert(cast<CXXMethodDecl>(CurFuncDecl)->isInstance() &&
35         "Must be in a C++ member function decl to load 'this'");
36
37  // FIXME: What if we're inside a block?
38  // ans: See how CodeGenFunction::LoadObjCSelf() uses
39  // CodeGenFunction::BlockForwardSelf() for how to do this.
40  return Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this");
41}
42
43void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) {
44  EmitGlobal(GlobalDecl(D, Ctor_Complete));
45  EmitGlobal(GlobalDecl(D, Ctor_Base));
46}
47
48void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D,
49                                       CXXCtorType Type) {
50
51  llvm::Function *Fn = GetAddrOfCXXConstructor(D, Type);
52
53  CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
54
55  SetFunctionDefinitionAttributes(D, Fn);
56  SetLLVMFunctionAttributesForDefinition(D, Fn);
57}
58
59llvm::Function *
60CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
61                                       CXXCtorType Type) {
62  const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>();
63  const llvm::FunctionType *FTy =
64    getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type),
65                               FPT->isVariadic());
66
67  const char *Name = getMangledCXXCtorName(D, Type);
68  return cast<llvm::Function>(
69                      GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
70}
71
72const char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D,
73                                                 CXXCtorType Type) {
74  llvm::SmallString<256> Name;
75  getMangleContext().mangleCXXCtor(D, Type, Name);
76
77  Name += '\0';
78  return UniqueMangledName(Name.begin(), Name.end());
79}
80
81void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) {
82  if (D->isVirtual())
83    EmitGlobal(GlobalDecl(D, Dtor_Deleting));
84  EmitGlobal(GlobalDecl(D, Dtor_Complete));
85  EmitGlobal(GlobalDecl(D, Dtor_Base));
86}
87
88void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D,
89                                      CXXDtorType Type) {
90  llvm::Function *Fn = GetAddrOfCXXDestructor(D, Type);
91
92  CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
93
94  SetFunctionDefinitionAttributes(D, Fn);
95  SetLLVMFunctionAttributesForDefinition(D, Fn);
96}
97
98llvm::Function *
99CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
100                                      CXXDtorType Type) {
101  const llvm::FunctionType *FTy =
102    getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), false);
103
104  const char *Name = getMangledCXXDtorName(D, Type);
105  return cast<llvm::Function>(
106                      GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
107}
108
109const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D,
110                                                 CXXDtorType Type) {
111  llvm::SmallString<256> Name;
112  getMangleContext().mangleCXXDtor(D, Type, Name);
113
114  Name += '\0';
115  return UniqueMangledName(Name.begin(), Name.end());
116}
117
118llvm::Constant *
119CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
120                               bool Extern,
121                               const ThunkAdjustment &ThisAdjustment) {
122  return GenerateCovariantThunk(Fn, GD, Extern,
123                                CovariantThunkAdjustment(ThisAdjustment,
124                                                         ThunkAdjustment()));
125}
126
127llvm::Value *
128CodeGenFunction::DynamicTypeAdjust(llvm::Value *V,
129                                   const ThunkAdjustment &Adjustment) {
130  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
131
132  const llvm::Type *OrigTy = V->getType();
133  if (Adjustment.NonVirtual) {
134    // Do the non-virtual adjustment
135    V = Builder.CreateBitCast(V, Int8PtrTy);
136    V = Builder.CreateConstInBoundsGEP1_64(V, Adjustment.NonVirtual);
137    V = Builder.CreateBitCast(V, OrigTy);
138  }
139
140  if (!Adjustment.Virtual)
141    return V;
142
143  assert(Adjustment.Virtual % (LLVMPointerWidth / 8) == 0 &&
144         "vtable entry unaligned");
145
146  // Do the virtual this adjustment
147  const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
148  const llvm::Type *PtrDiffPtrTy = PtrDiffTy->getPointerTo();
149
150  llvm::Value *ThisVal = Builder.CreateBitCast(V, Int8PtrTy);
151  V = Builder.CreateBitCast(V, PtrDiffPtrTy->getPointerTo());
152  V = Builder.CreateLoad(V, "vtable");
153
154  llvm::Value *VTablePtr = V;
155  uint64_t VirtualAdjustment = Adjustment.Virtual / (LLVMPointerWidth / 8);
156  V = Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment);
157  V = Builder.CreateLoad(V);
158  V = Builder.CreateGEP(ThisVal, V);
159
160  return Builder.CreateBitCast(V, OrigTy);
161}
162
163llvm::Constant *
164CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn,
165                                   GlobalDecl GD, bool Extern,
166                                   const CovariantThunkAdjustment &Adjustment) {
167  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
168  QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType();
169
170  FunctionArgList Args;
171  ImplicitParamDecl *ThisDecl =
172    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
173                              MD->getThisType(getContext()));
174  Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType()));
175  for (FunctionDecl::param_const_iterator i = MD->param_begin(),
176         e = MD->param_end();
177       i != e; ++i) {
178    ParmVarDecl *D = *i;
179    Args.push_back(std::make_pair(D, D->getType()));
180  }
181  IdentifierInfo *II
182    = &CGM.getContext().Idents.get("__thunk_named_foo_");
183  FunctionDecl *FD = FunctionDecl::Create(getContext(),
184                                          getContext().getTranslationUnitDecl(),
185                                          SourceLocation(), II, ResultType, 0,
186                                          Extern
187                                            ? FunctionDecl::Extern
188                                            : FunctionDecl::Static,
189                                          false, true);
190  StartFunction(FD, ResultType, Fn, Args, SourceLocation());
191
192  // generate body
193  const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
194  const llvm::Type *Ty =
195    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
196                                   FPT->isVariadic());
197  llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty);
198
199  CallArgList CallArgs;
200
201  bool ShouldAdjustReturnPointer = true;
202  QualType ArgType = MD->getThisType(getContext());
203  llvm::Value *Arg = Builder.CreateLoad(LocalDeclMap[ThisDecl], "this");
204  if (!Adjustment.ThisAdjustment.isEmpty()) {
205    // Do the this adjustment.
206    const llvm::Type *OrigTy = Callee->getType();
207    Arg = DynamicTypeAdjust(Arg, Adjustment.ThisAdjustment);
208
209    if (!Adjustment.ReturnAdjustment.isEmpty()) {
210      const CovariantThunkAdjustment &ReturnAdjustment =
211        CovariantThunkAdjustment(ThunkAdjustment(),
212                                 Adjustment.ReturnAdjustment);
213
214      Callee = CGM.BuildCovariantThunk(GD, Extern, ReturnAdjustment);
215
216      Callee = Builder.CreateBitCast(Callee, OrigTy);
217      ShouldAdjustReturnPointer = false;
218    }
219  }
220
221  CallArgs.push_back(std::make_pair(RValue::get(Arg), ArgType));
222
223  for (FunctionDecl::param_const_iterator i = MD->param_begin(),
224         e = MD->param_end();
225       i != e; ++i) {
226    ParmVarDecl *D = *i;
227    QualType ArgType = D->getType();
228
229    // llvm::Value *Arg = CGF.GetAddrOfLocalVar(Dst);
230    Expr *Arg = new (getContext()) DeclRefExpr(D, ArgType.getNonReferenceType(),
231                                               SourceLocation());
232    CallArgs.push_back(std::make_pair(EmitCallArg(Arg, ArgType), ArgType));
233  }
234
235  RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
236                       Callee, ReturnValueSlot(), CallArgs, MD);
237  if (ShouldAdjustReturnPointer && !Adjustment.ReturnAdjustment.isEmpty()) {
238    bool CanBeZero = !(ResultType->isReferenceType()
239    // FIXME: attr nonnull can't be zero either
240                       /* || ResultType->hasAttr<NonNullAttr>() */ );
241    // Do the return result adjustment.
242    if (CanBeZero) {
243      llvm::BasicBlock *NonZeroBlock = createBasicBlock();
244      llvm::BasicBlock *ZeroBlock = createBasicBlock();
245      llvm::BasicBlock *ContBlock = createBasicBlock();
246
247      const llvm::Type *Ty = RV.getScalarVal()->getType();
248      llvm::Value *Zero = llvm::Constant::getNullValue(Ty);
249      Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero),
250                           NonZeroBlock, ZeroBlock);
251      EmitBlock(NonZeroBlock);
252      llvm::Value *NZ =
253        DynamicTypeAdjust(RV.getScalarVal(), Adjustment.ReturnAdjustment);
254      EmitBranch(ContBlock);
255      EmitBlock(ZeroBlock);
256      llvm::Value *Z = RV.getScalarVal();
257      EmitBlock(ContBlock);
258      llvm::PHINode *RVOrZero = Builder.CreatePHI(Ty);
259      RVOrZero->reserveOperandSpace(2);
260      RVOrZero->addIncoming(NZ, NonZeroBlock);
261      RVOrZero->addIncoming(Z, ZeroBlock);
262      RV = RValue::get(RVOrZero);
263    } else
264      RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(),
265                                         Adjustment.ReturnAdjustment));
266  }
267
268  if (!ResultType->isVoidType())
269    EmitReturnOfRValue(RV, ResultType);
270
271  FinishFunction();
272  return Fn;
273}
274
275llvm::Constant *
276CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
277                              const ThunkAdjustment &ThisAdjustment) {
278  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
279
280  // Compute mangled name
281  llvm::SmallString<256> OutName;
282  if (const CXXDestructorDecl* DD = dyn_cast<CXXDestructorDecl>(MD))
283    getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(), ThisAdjustment,
284                                          OutName);
285  else
286    getMangleContext().mangleThunk(MD, ThisAdjustment, OutName);
287  OutName += '\0';
288  const char* Name = UniqueMangledName(OutName.begin(), OutName.end());
289
290  // Get function for mangled name
291  const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD);
292  return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl());
293}
294
295llvm::Constant *
296CodeGenModule::GetAddrOfCovariantThunk(GlobalDecl GD,
297                                   const CovariantThunkAdjustment &Adjustment) {
298  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
299
300  // Compute mangled name
301  llvm::SmallString<256> OutName;
302  getMangleContext().mangleCovariantThunk(MD, Adjustment, OutName);
303  OutName += '\0';
304  const char* Name = UniqueMangledName(OutName.begin(), OutName.end());
305
306  // Get function for mangled name
307  const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD);
308  return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl());
309}
310
311void CodeGenModule::BuildThunksForVirtual(GlobalDecl GD) {
312  CGVtableInfo::AdjustmentVectorTy *AdjPtr = getVtableInfo().getAdjustments(GD);
313  if (!AdjPtr)
314    return;
315  CGVtableInfo::AdjustmentVectorTy &Adj = *AdjPtr;
316  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
317  for (unsigned i = 0; i < Adj.size(); i++) {
318    GlobalDecl OGD = Adj[i].first;
319    const CXXMethodDecl *OMD = cast<CXXMethodDecl>(OGD.getDecl());
320    QualType nc_oret = OMD->getType()->getAs<FunctionType>()->getResultType();
321    CanQualType oret = getContext().getCanonicalType(nc_oret);
322    QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType();
323    CanQualType ret = getContext().getCanonicalType(nc_ret);
324    ThunkAdjustment ReturnAdjustment;
325    if (oret != ret) {
326      QualType qD = nc_ret->getPointeeType();
327      QualType qB = nc_oret->getPointeeType();
328      CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
329      CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
330      ReturnAdjustment = ComputeThunkAdjustment(D, B);
331    }
332    ThunkAdjustment ThisAdjustment = Adj[i].second;
333    bool Extern = !cast<CXXRecordDecl>(OMD->getDeclContext())->isInAnonymousNamespace();
334    if (!ReturnAdjustment.isEmpty() || !ThisAdjustment.isEmpty()) {
335      CovariantThunkAdjustment CoAdj(ThisAdjustment, ReturnAdjustment);
336      llvm::Constant *FnConst;
337      if (!ReturnAdjustment.isEmpty())
338        FnConst = GetAddrOfCovariantThunk(GD, CoAdj);
339      else
340        FnConst = GetAddrOfThunk(GD, ThisAdjustment);
341      if (!isa<llvm::Function>(FnConst)) {
342        llvm::Constant *SubExpr =
343            cast<llvm::ConstantExpr>(FnConst)->getOperand(0);
344        llvm::Function *OldFn = cast<llvm::Function>(SubExpr);
345        std::string Name = OldFn->getNameStr();
346        GlobalDeclMap.erase(UniqueMangledName(Name.data(),
347                                              Name.data() + Name.size() + 1));
348        llvm::Constant *NewFnConst;
349        if (!ReturnAdjustment.isEmpty())
350          NewFnConst = GetAddrOfCovariantThunk(GD, CoAdj);
351        else
352          NewFnConst = GetAddrOfThunk(GD, ThisAdjustment);
353        llvm::Function *NewFn = cast<llvm::Function>(NewFnConst);
354        NewFn->takeName(OldFn);
355        llvm::Constant *NewPtrForOldDecl =
356            llvm::ConstantExpr::getBitCast(NewFn, OldFn->getType());
357        OldFn->replaceAllUsesWith(NewPtrForOldDecl);
358        OldFn->eraseFromParent();
359        FnConst = NewFn;
360      }
361      llvm::Function *Fn = cast<llvm::Function>(FnConst);
362      if (Fn->isDeclaration()) {
363        llvm::GlobalVariable::LinkageTypes linktype;
364        linktype = llvm::GlobalValue::WeakAnyLinkage;
365        if (!Extern)
366          linktype = llvm::GlobalValue::InternalLinkage;
367        Fn->setLinkage(linktype);
368        if (!Features.Exceptions && !Features.ObjCNonFragileABI)
369          Fn->addFnAttr(llvm::Attribute::NoUnwind);
370        Fn->setAlignment(2);
371        CodeGenFunction(*this).GenerateCovariantThunk(Fn, GD, Extern, CoAdj);
372      }
373    }
374  }
375}
376
377llvm::Constant *
378CodeGenModule::BuildThunk(GlobalDecl GD, bool Extern,
379                          const ThunkAdjustment &ThisAdjustment) {
380  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
381  llvm::SmallString<256> OutName;
382  if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(MD)) {
383    getMangleContext().mangleCXXDtorThunk(D, GD.getDtorType(), ThisAdjustment,
384                                          OutName);
385  } else
386    getMangleContext().mangleThunk(MD, ThisAdjustment, OutName);
387
388  llvm::GlobalVariable::LinkageTypes linktype;
389  linktype = llvm::GlobalValue::WeakAnyLinkage;
390  if (!Extern)
391    linktype = llvm::GlobalValue::InternalLinkage;
392  llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
393  const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
394  const llvm::FunctionType *FTy =
395    getTypes().GetFunctionType(getTypes().getFunctionInfo(MD),
396                               FPT->isVariadic());
397
398  llvm::Function *Fn = llvm::Function::Create(FTy, linktype, OutName.str(),
399                                              &getModule());
400  CodeGenFunction(*this).GenerateThunk(Fn, GD, Extern, ThisAdjustment);
401  llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
402  return m;
403}
404
405llvm::Constant *
406CodeGenModule::BuildCovariantThunk(const GlobalDecl &GD, bool Extern,
407                                   const CovariantThunkAdjustment &Adjustment) {
408  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
409  llvm::SmallString<256> OutName;
410  getMangleContext().mangleCovariantThunk(MD, Adjustment, OutName);
411  llvm::GlobalVariable::LinkageTypes linktype;
412  linktype = llvm::GlobalValue::WeakAnyLinkage;
413  if (!Extern)
414    linktype = llvm::GlobalValue::InternalLinkage;
415  llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0);
416  const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
417  const llvm::FunctionType *FTy =
418    getTypes().GetFunctionType(getTypes().getFunctionInfo(MD),
419                               FPT->isVariadic());
420
421  llvm::Function *Fn = llvm::Function::Create(FTy, linktype, OutName.str(),
422                                              &getModule());
423  CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, Adjustment);
424  llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty);
425  return m;
426}
427
428static llvm::Value *BuildVirtualCall(CodeGenFunction &CGF, uint64_t VtableIndex,
429                                     llvm::Value *This, const llvm::Type *Ty) {
430  Ty = Ty->getPointerTo()->getPointerTo()->getPointerTo();
431
432  llvm::Value *Vtable = CGF.Builder.CreateBitCast(This, Ty);
433  Vtable = CGF.Builder.CreateLoad(Vtable);
434
435  llvm::Value *VFuncPtr =
436    CGF.Builder.CreateConstInBoundsGEP1_64(Vtable, VtableIndex, "vfn");
437  return CGF.Builder.CreateLoad(VFuncPtr);
438}
439
440llvm::Value *
441CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This,
442                                  const llvm::Type *Ty) {
443  MD = MD->getCanonicalDecl();
444  uint64_t VtableIndex = CGM.getVtableInfo().getMethodVtableIndex(MD);
445
446  return ::BuildVirtualCall(*this, VtableIndex, This, Ty);
447}
448
449llvm::Value *
450CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
451                                  llvm::Value *&This, const llvm::Type *Ty) {
452  DD = cast<CXXDestructorDecl>(DD->getCanonicalDecl());
453  uint64_t VtableIndex =
454    CGM.getVtableInfo().getMethodVtableIndex(GlobalDecl(DD, Type));
455
456  return ::BuildVirtualCall(*this, VtableIndex, This, Ty);
457}
458