CGDeclCXX.cpp revision 91a16fa3265686b90054715eea504d9b4a13438b
1//===--- CGDeclCXX.cpp - Emit LLVM Code for C++ 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 code generation of C++ declarations
11//
12//===----------------------------------------------------------------------===//
13
14#include "CodeGenFunction.h"
15#include "clang/Frontend/CodeGenOptions.h"
16#include "llvm/Intrinsics.h"
17
18using namespace clang;
19using namespace CodeGen;
20
21static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
22                         llvm::Constant *DeclPtr) {
23  assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
24  assert(!D.getType()->isReferenceType() &&
25         "Should not call EmitDeclInit on a reference!");
26
27  ASTContext &Context = CGF.getContext();
28
29  const Expr *Init = D.getInit();
30  QualType T = D.getType();
31  bool isVolatile = Context.getCanonicalType(T).isVolatileQualified();
32
33  unsigned Alignment = Context.getDeclAlign(&D).getQuantity();
34  if (!CGF.hasAggregateLLVMType(T)) {
35    llvm::Value *V = CGF.EmitScalarExpr(Init);
36    CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, Alignment, T);
37  } else if (T->isAnyComplexType()) {
38    CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
39  } else {
40    CGF.EmitAggExpr(Init, DeclPtr, isVolatile);
41  }
42}
43
44static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
45                            llvm::Constant *DeclPtr) {
46  CodeGenModule &CGM = CGF.CGM;
47  ASTContext &Context = CGF.getContext();
48
49  QualType T = D.getType();
50
51  // Drill down past array types.
52  const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
53  if (Array)
54    T = Context.getBaseElementType(Array);
55
56  /// If that's not a record, we're done.
57  /// FIXME:  __attribute__((cleanup)) ?
58  const RecordType *RT = T->getAs<RecordType>();
59  if (!RT)
60    return;
61
62  CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
63  if (RD->hasTrivialDestructor())
64    return;
65
66  CXXDestructorDecl *Dtor = RD->getDestructor();
67
68  llvm::Constant *DtorFn;
69  if (Array) {
70    DtorFn =
71      CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, Array,
72                                                           DeclPtr);
73    const llvm::Type *Int8PtrTy =
74      llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
75    DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
76  } else
77    DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
78
79  CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
80}
81
82void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
83                                               llvm::Constant *DeclPtr) {
84
85  const Expr *Init = D.getInit();
86  QualType T = D.getType();
87
88  if (!T->isReferenceType()) {
89    EmitDeclInit(*this, D, DeclPtr);
90    EmitDeclDestroy(*this, D, DeclPtr);
91    return;
92  }
93
94  unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
95  RValue RV = EmitReferenceBindingToExpr(Init, &D);
96  EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T);
97}
98
99void
100CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
101                                               llvm::Constant *DeclPtr) {
102  // Generate a global destructor entry if not using __cxa_atexit.
103  if (!CGM.getCodeGenOpts().CXAAtExit) {
104    CGM.AddCXXDtorEntry(DtorFn, DeclPtr);
105    return;
106  }
107
108  const llvm::Type *Int8PtrTy =
109    llvm::Type::getInt8Ty(VMContext)->getPointerTo();
110
111  std::vector<const llvm::Type *> Params;
112  Params.push_back(Int8PtrTy);
113
114  // Get the destructor function type
115  const llvm::Type *DtorFnTy =
116    llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
117  DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);
118
119  Params.clear();
120  Params.push_back(DtorFnTy);
121  Params.push_back(Int8PtrTy);
122  Params.push_back(Int8PtrTy);
123
124  // Get the __cxa_atexit function type
125  // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
126  const llvm::FunctionType *AtExitFnTy =
127    llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false);
128
129  llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy,
130                                                       "__cxa_atexit");
131
132  llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
133                                                     "__dso_handle");
134  llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
135                           llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
136                           llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
137  Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
138}
139
140static llvm::Function *
141CreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
142                                   const llvm::FunctionType *FTy,
143                                   llvm::StringRef Name) {
144  llvm::Function *Fn =
145    llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
146                           Name, &CGM.getModule());
147
148  // Set the section if needed.
149  if (const char *Section =
150        CGM.getContext().Target.getStaticInitSectionSpecifier())
151    Fn->setSection(Section);
152
153  if (!CGM.getLangOptions().Exceptions)
154    Fn->setDoesNotThrow();
155
156  return Fn;
157}
158
159void
160CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
161  const llvm::FunctionType *FTy
162    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
163                              false);
164
165  // Create a variable initialization function.
166  llvm::Function *Fn =
167    CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init");
168
169  CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D);
170
171  if (D->hasAttr<InitPriorityAttr>()) {
172    unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
173    OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());
174    PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
175    DelayedCXXInitPosition.erase(D);
176  }
177  else {
178    llvm::DenseMap<const Decl *, unsigned>::iterator I =
179      DelayedCXXInitPosition.find(D);
180    if (I == DelayedCXXInitPosition.end()) {
181      CXXGlobalInits.push_back(Fn);
182    } else {
183      assert(CXXGlobalInits[I->second] == 0);
184      CXXGlobalInits[I->second] = Fn;
185      DelayedCXXInitPosition.erase(I);
186    }
187  }
188}
189
190void
191CodeGenModule::EmitCXXGlobalInitFunc() {
192  while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
193    CXXGlobalInits.pop_back();
194
195  if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
196    return;
197
198  const llvm::FunctionType *FTy
199    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
200                              false);
201
202  // Create our global initialization function.
203  llvm::Function *Fn =
204    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a");
205
206  if (!PrioritizedCXXGlobalInits.empty()) {
207    llvm::SmallVector<llvm::Constant*, 8> LocalCXXGlobalInits;
208    llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
209                         PrioritizedCXXGlobalInits.end());
210    for (unsigned i = 0; i < PrioritizedCXXGlobalInits.size(); i++) {
211      llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second;
212      LocalCXXGlobalInits.push_back(Fn);
213    }
214    LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end());
215    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
216                                                    &LocalCXXGlobalInits[0],
217                                                    LocalCXXGlobalInits.size());
218  }
219  else
220    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
221                                                     &CXXGlobalInits[0],
222                                                     CXXGlobalInits.size());
223  AddGlobalCtor(Fn);
224}
225
226void CodeGenModule::EmitCXXGlobalDtorFunc() {
227  if (CXXGlobalDtors.empty())
228    return;
229
230  const llvm::FunctionType *FTy
231    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
232                              false);
233
234  // Create our global destructor function.
235  llvm::Function *Fn =
236    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a");
237
238  CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors);
239  AddGlobalDtor(Fn);
240}
241
242void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
243                                                       const VarDecl *D) {
244  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
245                SourceLocation());
246
247  llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D);
248  EmitCXXGlobalVarDeclInit(*D, DeclPtr);
249
250  FinishFunction();
251}
252
253void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
254                                                llvm::Constant **Decls,
255                                                unsigned NumDecls) {
256  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
257                SourceLocation());
258
259  for (unsigned i = 0; i != NumDecls; ++i)
260    if (Decls[i])
261      Builder.CreateCall(Decls[i]);
262
263  FinishFunction();
264}
265
266void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
267                  const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
268                                                &DtorsAndObjects) {
269  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
270                SourceLocation());
271
272  // Emit the dtors, in reverse order from construction.
273  for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
274    llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
275    llvm::CallInst *CI = Builder.CreateCall(Callee,
276                                            DtorsAndObjects[e - i - 1].second);
277    // Make sure the call and the callee agree on calling convention.
278    if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
279      CI->setCallingConv(F->getCallingConv());
280  }
281
282  FinishFunction();
283}
284
285static llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) {
286  // int __cxa_guard_acquire(__int64_t *guard_object);
287
288  const llvm::Type *Int64PtrTy =
289    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
290
291  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
292
293  const llvm::FunctionType *FTy =
294    llvm::FunctionType::get(CGF.ConvertType(CGF.getContext().IntTy),
295                            Args, /*isVarArg=*/false);
296
297  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire");
298}
299
300static llvm::Constant *getGuardReleaseFn(CodeGenFunction &CGF) {
301  // void __cxa_guard_release(__int64_t *guard_object);
302
303  const llvm::Type *Int64PtrTy =
304    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
305
306  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
307
308  const llvm::FunctionType *FTy =
309  llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
310                          Args, /*isVarArg=*/false);
311
312  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release");
313}
314
315static llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) {
316  // void __cxa_guard_abort(__int64_t *guard_object);
317
318  const llvm::Type *Int64PtrTy =
319    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
320
321  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
322
323  const llvm::FunctionType *FTy =
324  llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
325                          Args, /*isVarArg=*/false);
326
327  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort");
328}
329
330namespace {
331  struct CallGuardAbort : EHScopeStack::Cleanup {
332    llvm::GlobalVariable *Guard;
333    CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
334
335    void Emit(CodeGenFunction &CGF, bool IsForEH) {
336      // It shouldn't be possible for this to throw, but if it can,
337      // this should allow for the possibility of an invoke.
338      CGF.Builder.CreateCall(getGuardAbortFn(CGF), Guard)
339        ->setDoesNotThrow();
340    }
341  };
342}
343
344void
345CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
346                                               llvm::GlobalVariable *GV) {
347  // Bail out early if this initializer isn't reachable.
348  if (!Builder.GetInsertBlock()) return;
349
350  bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
351
352  llvm::SmallString<256> GuardVName;
353  CGM.getMangleContext().mangleGuardVariable(&D, GuardVName);
354
355  // Create the guard variable.
356  llvm::GlobalVariable *GuardVariable =
357    new llvm::GlobalVariable(CGM.getModule(), Int64Ty,
358                             false, GV->getLinkage(),
359                             llvm::Constant::getNullValue(Int64Ty),
360                             GuardVName.str());
361
362  // Load the first byte of the guard variable.
363  const llvm::Type *PtrTy
364    = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
365  llvm::Value *V =
366    Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp");
367
368  llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check");
369  llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
370
371  // Check if the first byte of the guard variable is zero.
372  Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"),
373                       InitCheckBlock, EndBlock);
374
375  EmitBlock(InitCheckBlock);
376
377  // Variables used when coping with thread-safe statics and exceptions.
378  if (ThreadsafeStatics) {
379    // Call __cxa_guard_acquire.
380    V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable);
381
382    llvm::BasicBlock *InitBlock = createBasicBlock("init");
383
384    Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
385                         InitBlock, EndBlock);
386
387    // Call __cxa_guard_abort along the exceptional edge.
388    if (Exceptions)
389      EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable);
390
391    EmitBlock(InitBlock);
392  }
393
394  if (D.getType()->isReferenceType()) {
395    unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
396    QualType T = D.getType();
397    RValue RV = EmitReferenceBindingToExpr(D.getInit(), &D);
398    EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, Alignment, T);
399  } else
400    EmitDeclInit(*this, D, GV);
401
402  if (ThreadsafeStatics) {
403    // Pop the guard-abort cleanup if we pushed one.
404    if (Exceptions)
405      PopCleanupBlock();
406
407    // Call __cxa_guard_release.  This cannot throw.
408    Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable);
409  } else {
410    llvm::Value *One =
411      llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1);
412    Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy));
413  }
414
415  // Register the call to the destructor.
416  if (!D.getType()->isReferenceType())
417    EmitDeclDestroy(*this, D, GV);
418
419  EmitBlock(EndBlock);
420}
421
422/// GenerateCXXAggrDestructorHelper - Generates a helper function which when
423/// invoked, calls the default destructor on array elements in reverse order of
424/// construction.
425llvm::Function *
426CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
427                                                 const ArrayType *Array,
428                                                 llvm::Value *This) {
429  FunctionArgList Args;
430  ImplicitParamDecl *Dst =
431    ImplicitParamDecl::Create(getContext(), 0,
432                              SourceLocation(), 0,
433                              getContext().getPointerType(getContext().VoidTy));
434  Args.push_back(std::make_pair(Dst, Dst->getType()));
435
436  const CGFunctionInfo &FI =
437    CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args,
438                                   FunctionType::ExtInfo());
439  const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
440  llvm::Function *Fn =
441    CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor");
442
443  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, Args, SourceLocation());
444
445  QualType BaseElementTy = getContext().getBaseElementType(Array);
446  const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo();
447  llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr);
448
449  EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
450
451  FinishFunction();
452
453  return Fn;
454}
455