CGDeclCXX.cpp revision e67d1512f299e7f32182553f9941d61dae4f433e
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 "CGObjCRuntime.h"
16#include "CGCXXABI.h"
17#include "clang/Frontend/CodeGenOptions.h"
18#include "llvm/Intrinsics.h"
19
20using namespace clang;
21using namespace CodeGen;
22
23static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
24                         llvm::Constant *DeclPtr) {
25  assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
26  assert(!D.getType()->isReferenceType() &&
27         "Should not call EmitDeclInit on a reference!");
28
29  ASTContext &Context = CGF.getContext();
30
31  unsigned alignment = Context.getDeclAlign(&D).getQuantity();
32  QualType type = D.getType();
33  LValue lv = CGF.MakeAddrLValue(DeclPtr, type, alignment);
34
35  const Expr *Init = D.getInit();
36  if (!CGF.hasAggregateLLVMType(type)) {
37    CodeGenModule &CGM = CGF.CGM;
38    if (lv.isObjCStrong())
39      CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, CGF.EmitScalarExpr(Init),
40                                                DeclPtr, D.isThreadSpecified());
41    else if (lv.isObjCWeak())
42      CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, CGF.EmitScalarExpr(Init),
43                                              DeclPtr);
44    else
45      CGF.EmitScalarInit(Init, &D, lv, false);
46  } else if (type->isAnyComplexType()) {
47    CGF.EmitComplexExprIntoAddr(Init, DeclPtr, lv.isVolatile());
48  } else {
49    CGF.EmitAggExpr(Init, AggValueSlot::forLValue(lv, true));
50  }
51}
52
53/// Emit code to cause the destruction of the given variable with
54/// static storage duration.
55static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
56                            llvm::Constant *DeclPtr) {
57  CodeGenModule &CGM = CGF.CGM;
58  ASTContext &Context = CGF.getContext();
59
60  QualType T = D.getType();
61
62  // Drill down past array types.
63  const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
64  if (Array)
65    T = Context.getBaseElementType(Array);
66
67  /// If that's not a record, we're done.
68  /// FIXME:  __attribute__((cleanup)) ?
69  const RecordType *RT = T->getAs<RecordType>();
70  if (!RT)
71    return;
72
73  CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
74  if (RD->hasTrivialDestructor())
75    return;
76
77  CXXDestructorDecl *Dtor = RD->getDestructor();
78
79  llvm::Constant *DtorFn;
80  if (Array) {
81    DtorFn =
82      CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, Array,
83                                                           DeclPtr);
84    const llvm::Type *Int8PtrTy =
85      llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
86    DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
87  } else
88    DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
89
90  CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
91}
92
93void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
94                                               llvm::Constant *DeclPtr) {
95
96  const Expr *Init = D.getInit();
97  QualType T = D.getType();
98
99  if (!T->isReferenceType()) {
100    EmitDeclInit(*this, D, DeclPtr);
101    EmitDeclDestroy(*this, D, DeclPtr);
102    return;
103  }
104
105  unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
106  RValue RV = EmitReferenceBindingToExpr(Init, &D);
107  EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T);
108}
109
110void
111CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
112                                               llvm::Constant *DeclPtr) {
113  // Generate a global destructor entry if not using __cxa_atexit.
114  if (!CGM.getCodeGenOpts().CXAAtExit) {
115    CGM.AddCXXDtorEntry(DtorFn, DeclPtr);
116    return;
117  }
118
119  // Get the destructor function type
120  const llvm::Type *DtorFnTy =
121    llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()),
122                            Int8PtrTy, false);
123  DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);
124
125  const llvm::Type *Params[] = { DtorFnTy, Int8PtrTy, Int8PtrTy };
126
127  // Get the __cxa_atexit function type
128  // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
129  const llvm::FunctionType *AtExitFnTy =
130    llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false);
131
132  llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy,
133                                                       "__cxa_atexit");
134  if (llvm::Function *Fn = dyn_cast<llvm::Function>(AtExitFn))
135    Fn->setDoesNotThrow();
136
137  llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
138                                                     "__dso_handle");
139  llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
140                           llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
141                           llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
142  Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
143}
144
145void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
146                                         llvm::GlobalVariable *DeclPtr) {
147  // If we've been asked to forbid guard variables, emit an error now.
148  // This diagnostic is hard-coded for Darwin's use case;  we can find
149  // better phrasing if someone else needs it.
150  if (CGM.getCodeGenOpts().ForbidGuardVariables)
151    CGM.Error(D.getLocation(),
152              "this initialization requires a guard variable, which "
153              "the kernel does not support");
154
155  CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr);
156}
157
158static llvm::Function *
159CreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
160                                   const llvm::FunctionType *FTy,
161                                   llvm::StringRef Name) {
162  llvm::Function *Fn =
163    llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
164                           Name, &CGM.getModule());
165  if (!CGM.getContext().getLangOptions().AppleKext) {
166    // Set the section if needed.
167    if (const char *Section =
168          CGM.getContext().Target.getStaticInitSectionSpecifier())
169      Fn->setSection(Section);
170  }
171
172  if (!CGM.getLangOptions().Exceptions)
173    Fn->setDoesNotThrow();
174
175  return Fn;
176}
177
178void
179CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
180                                            llvm::GlobalVariable *Addr) {
181  const llvm::FunctionType *FTy
182    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
183                              false);
184
185  // Create a variable initialization function.
186  llvm::Function *Fn =
187    CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init");
188
189  CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr);
190
191  if (D->hasAttr<InitPriorityAttr>()) {
192    unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
193    OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());
194    PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
195    DelayedCXXInitPosition.erase(D);
196  }
197  else {
198    llvm::DenseMap<const Decl *, unsigned>::iterator I =
199      DelayedCXXInitPosition.find(D);
200    if (I == DelayedCXXInitPosition.end()) {
201      CXXGlobalInits.push_back(Fn);
202    } else {
203      assert(CXXGlobalInits[I->second] == 0);
204      CXXGlobalInits[I->second] = Fn;
205      DelayedCXXInitPosition.erase(I);
206    }
207  }
208}
209
210void
211CodeGenModule::EmitCXXGlobalInitFunc() {
212  while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
213    CXXGlobalInits.pop_back();
214
215  if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
216    return;
217
218  const llvm::FunctionType *FTy
219    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
220                              false);
221
222  // Create our global initialization function.
223  llvm::Function *Fn =
224    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a");
225
226  if (!PrioritizedCXXGlobalInits.empty()) {
227    llvm::SmallVector<llvm::Constant*, 8> LocalCXXGlobalInits;
228    llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
229                         PrioritizedCXXGlobalInits.end());
230    for (unsigned i = 0; i < PrioritizedCXXGlobalInits.size(); i++) {
231      llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second;
232      LocalCXXGlobalInits.push_back(Fn);
233    }
234    LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end());
235    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
236                                                    &LocalCXXGlobalInits[0],
237                                                    LocalCXXGlobalInits.size());
238  }
239  else
240    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
241                                                     &CXXGlobalInits[0],
242                                                     CXXGlobalInits.size());
243  AddGlobalCtor(Fn);
244  CXXGlobalInits.clear();
245  PrioritizedCXXGlobalInits.clear();
246}
247
248void CodeGenModule::EmitCXXGlobalDtorFunc() {
249  if (CXXGlobalDtors.empty())
250    return;
251
252  const llvm::FunctionType *FTy
253    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
254                              false);
255
256  // Create our global destructor function.
257  llvm::Function *Fn =
258    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a");
259
260  CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors);
261  AddGlobalDtor(Fn);
262}
263
264/// Emit the code necessary to initialize the given global variable.
265void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
266                                                       const VarDecl *D,
267                                                 llvm::GlobalVariable *Addr) {
268  StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
269                getTypes().getNullaryFunctionInfo(),
270                FunctionArgList(), SourceLocation());
271
272  // Use guarded initialization if the global variable is weak. This
273  // occurs for, e.g., instantiated static data members and
274  // definitions explicitly marked weak.
275  if (Addr->getLinkage() == llvm::GlobalValue::WeakODRLinkage ||
276      Addr->getLinkage() == llvm::GlobalValue::WeakAnyLinkage) {
277    EmitCXXGuardedInit(*D, Addr);
278  } else {
279    EmitCXXGlobalVarDeclInit(*D, Addr);
280  }
281
282  FinishFunction();
283}
284
285void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
286                                                llvm::Constant **Decls,
287                                                unsigned NumDecls) {
288  StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
289                getTypes().getNullaryFunctionInfo(),
290                FunctionArgList(), SourceLocation());
291
292  RunCleanupsScope Scope(*this);
293
294  // When building in Objective-C++ ARC mode, create an autorelease pool
295  // around the global initializers.
296  if (getLangOptions().ObjCAutoRefCount && getLangOptions().CPlusPlus) {
297    llvm::Value *token = EmitObjCAutoreleasePoolPush();
298    EmitObjCAutoreleasePoolCleanup(token);
299  }
300
301  for (unsigned i = 0; i != NumDecls; ++i)
302    if (Decls[i])
303      Builder.CreateCall(Decls[i]);
304
305  Scope.ForceCleanup();
306
307  FinishFunction();
308}
309
310void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
311                  const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
312                                                &DtorsAndObjects) {
313  StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
314                getTypes().getNullaryFunctionInfo(),
315                FunctionArgList(), SourceLocation());
316
317  // Emit the dtors, in reverse order from construction.
318  for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
319    llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
320    llvm::CallInst *CI = Builder.CreateCall(Callee,
321                                            DtorsAndObjects[e - i - 1].second);
322    // Make sure the call and the callee agree on calling convention.
323    if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
324      CI->setCallingConv(F->getCallingConv());
325  }
326
327  FinishFunction();
328}
329
330/// GenerateCXXAggrDestructorHelper - Generates a helper function which when
331/// invoked, calls the default destructor on array elements in reverse order of
332/// construction.
333llvm::Function *
334CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
335                                                 const ArrayType *Array,
336                                                 llvm::Value *This) {
337  FunctionArgList args;
338  ImplicitParamDecl dst(0, SourceLocation(), 0, getContext().VoidPtrTy);
339  args.push_back(&dst);
340
341  const CGFunctionInfo &FI =
342    CGM.getTypes().getFunctionInfo(getContext().VoidTy, args,
343                                   FunctionType::ExtInfo());
344  const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
345  llvm::Function *Fn =
346    CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor");
347
348  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FI, args,
349                SourceLocation());
350
351  QualType BaseElementTy = getContext().getBaseElementType(Array);
352  const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo();
353  llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr);
354
355  EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
356
357  FinishFunction();
358
359  return Fn;
360}
361