CGDeclCXX.cpp revision 772913659894551b02f342e3577e7219e4f9a701
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/CodeGen/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  if (!CGF.hasAggregateLLVMType(T)) {
34    llvm::Value *V = CGF.EmitScalarExpr(Init);
35    CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, T);
36  } else if (T->isAnyComplexType()) {
37    CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
38  } else {
39    CGF.EmitAggExpr(Init, DeclPtr, isVolatile);
40  }
41}
42
43static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
44                            llvm::Constant *DeclPtr) {
45  CodeGenModule &CGM = CGF.CGM;
46  ASTContext &Context = CGF.getContext();
47
48  const Expr *Init = D.getInit();
49  QualType T = D.getType();
50  if (!CGF.hasAggregateLLVMType(T) || T->isAnyComplexType())
51    return;
52
53  // Avoid generating destructor(s) for initialized objects.
54  if (!isa<CXXConstructExpr>(Init))
55    return;
56
57  const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
58  if (Array)
59    T = Context.getBaseElementType(Array);
60
61  const RecordType *RT = T->getAs<RecordType>();
62  if (!RT)
63    return;
64
65  CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
66  if (RD->hasTrivialDestructor())
67    return;
68
69  CXXDestructorDecl *Dtor = RD->getDestructor(Context);
70
71  llvm::Constant *DtorFn;
72  if (Array) {
73    DtorFn =
74      CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, Array,
75                                                           DeclPtr);
76    const llvm::Type *Int8PtrTy =
77      llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
78    DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
79  } else
80    DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
81
82  CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
83}
84
85void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
86                                               llvm::Constant *DeclPtr) {
87
88  const Expr *Init = D.getInit();
89  QualType T = D.getType();
90
91  if (!T->isReferenceType()) {
92    EmitDeclInit(*this, D, DeclPtr);
93    EmitDeclDestroy(*this, D, DeclPtr);
94    return;
95  }
96  if (Init->isLvalue(getContext()) == Expr::LV_Valid) {
97    RValue RV = EmitReferenceBindingToExpr(Init, /*IsInitializer=*/true);
98    EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, T);
99    return;
100  }
101  ErrorUnsupported(Init,
102                   "global variable that binds reference to a non-lvalue");
103}
104
105void
106CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
107                                               llvm::Constant *DeclPtr) {
108  // Generate a global destructor entry if not using __cxa_atexit.
109  if (!CGM.getCodeGenOpts().CXAAtExit) {
110    CGM.AddCXXDtorEntry(DtorFn, DeclPtr);
111    return;
112  }
113
114  const llvm::Type *Int8PtrTy =
115    llvm::Type::getInt8Ty(VMContext)->getPointerTo();
116
117  std::vector<const llvm::Type *> Params;
118  Params.push_back(Int8PtrTy);
119
120  // Get the destructor function type
121  const llvm::Type *DtorFnTy =
122    llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
123  DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);
124
125  Params.clear();
126  Params.push_back(DtorFnTy);
127  Params.push_back(Int8PtrTy);
128  Params.push_back(Int8PtrTy);
129
130  // Get the __cxa_atexit function type
131  // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
132  const llvm::FunctionType *AtExitFnTy =
133    llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false);
134
135  llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy,
136                                                       "__cxa_atexit");
137
138  llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
139                                                     "__dso_handle");
140  llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
141                           llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
142                           llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
143  Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
144}
145
146void
147CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
148  const llvm::FunctionType *FTy
149    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
150                              false);
151
152  // Create a variable initialization function.
153  llvm::Function *Fn =
154    llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
155                           "__cxx_global_var_init", &TheModule);
156
157  CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D);
158
159  CXXGlobalInits.push_back(Fn);
160}
161
162void
163CodeGenModule::EmitCXXGlobalInitFunc() {
164  if (CXXGlobalInits.empty())
165    return;
166
167  const llvm::FunctionType *FTy
168    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
169                              false);
170
171  // Create our global initialization function.
172  llvm::Function *Fn =
173    llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
174                           "_GLOBAL__I_a", &TheModule);
175
176  CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
177                                                   &CXXGlobalInits[0],
178                                                   CXXGlobalInits.size());
179  AddGlobalCtor(Fn);
180}
181
182void CodeGenModule::AddCXXDtorEntry(llvm::Constant *DtorFn,
183                                    llvm::Constant *Object) {
184  CXXGlobalDtors.push_back(std::make_pair(DtorFn, Object));
185}
186
187void CodeGenModule::EmitCXXGlobalDtorFunc() {
188  if (CXXGlobalDtors.empty())
189    return;
190
191  const llvm::FunctionType *FTy
192    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
193                              false);
194
195  // Create our global destructor function.
196  llvm::Function *Fn =
197    llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
198                           "_GLOBAL__D_a", &TheModule);
199
200  CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors);
201  AddGlobalDtor(Fn);
202}
203
204void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
205                                                       const VarDecl *D) {
206  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
207                SourceLocation());
208
209  llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D);
210  EmitCXXGlobalVarDeclInit(*D, DeclPtr);
211
212  FinishFunction();
213}
214
215void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
216                                                llvm::Constant **Decls,
217                                                unsigned NumDecls) {
218  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
219                SourceLocation());
220
221  for (unsigned i = 0; i != NumDecls; ++i)
222    Builder.CreateCall(Decls[i]);
223
224  FinishFunction();
225}
226
227void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
228                const std::vector<std::pair<llvm::Constant*, llvm::Constant*> >
229                                                &DtorsAndObjects) {
230  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
231                SourceLocation());
232
233  // Emit the dtors, in reverse order from construction.
234  for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
235    llvm::Constant *Callee = DtorsAndObjects[e - i - 1].first;
236    llvm::CallInst *CI = Builder.CreateCall(Callee,
237                                            DtorsAndObjects[e - i - 1].second);
238    // Make sure the call and the callee agree on calling convention.
239    if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
240      CI->setCallingConv(F->getCallingConv());
241  }
242
243  FinishFunction();
244}
245
246static llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) {
247  // int __cxa_guard_acquire(__int64_t *guard_object);
248
249  const llvm::Type *Int64PtrTy =
250    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
251
252  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
253
254  const llvm::FunctionType *FTy =
255    llvm::FunctionType::get(CGF.ConvertType(CGF.getContext().IntTy),
256                            Args, /*isVarArg=*/false);
257
258  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire");
259}
260
261static llvm::Constant *getGuardReleaseFn(CodeGenFunction &CGF) {
262  // void __cxa_guard_release(__int64_t *guard_object);
263
264  const llvm::Type *Int64PtrTy =
265    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
266
267  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
268
269  const llvm::FunctionType *FTy =
270  llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
271                          Args, /*isVarArg=*/false);
272
273  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release");
274}
275
276static llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) {
277  // void __cxa_guard_abort(__int64_t *guard_object);
278
279  const llvm::Type *Int64PtrTy =
280    llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
281
282  std::vector<const llvm::Type*> Args(1, Int64PtrTy);
283
284  const llvm::FunctionType *FTy =
285  llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
286                          Args, /*isVarArg=*/false);
287
288  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort");
289}
290
291void
292CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
293                                               llvm::GlobalVariable *GV) {
294  // Bail out early if this initializer isn't reachable.
295  if (!Builder.GetInsertBlock()) return;
296
297  bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
298
299  llvm::SmallString<256> GuardVName;
300  CGM.getMangleContext().mangleGuardVariable(&D, GuardVName);
301
302  // Create the guard variable.
303  const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(VMContext);
304  llvm::GlobalValue *GuardVariable =
305    new llvm::GlobalVariable(CGM.getModule(), Int64Ty,
306                             false, GV->getLinkage(),
307                             llvm::Constant::getNullValue(Int64Ty),
308                             GuardVName.str());
309
310  // Load the first byte of the guard variable.
311  const llvm::Type *PtrTy
312    = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
313  llvm::Value *V =
314    Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp");
315
316  llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check");
317  llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
318
319  // Check if the first byte of the guard variable is zero.
320  Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"),
321                       InitCheckBlock, EndBlock);
322
323  EmitBlock(InitCheckBlock);
324
325  // Variables used when coping with thread-safe statics and exceptions.
326  llvm::BasicBlock *SavedLandingPad = 0;
327  llvm::BasicBlock *LandingPad = 0;
328  if (ThreadsafeStatics) {
329    // Call __cxa_guard_acquire.
330    V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable);
331
332    llvm::BasicBlock *InitBlock = createBasicBlock("init");
333
334    Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
335                         InitBlock, EndBlock);
336
337    if (Exceptions) {
338      SavedLandingPad = getInvokeDest();
339      LandingPad = createBasicBlock("guard.lpad");
340      setInvokeDest(LandingPad);
341    }
342
343    EmitBlock(InitBlock);
344  }
345
346  if (D.getType()->isReferenceType()) {
347    QualType T = D.getType();
348    // We don't want to pass true for IsInitializer here, because a static
349    // reference to a temporary does not extend its lifetime.
350    RValue RV = EmitReferenceBindingToExpr(D.getInit(),
351                                           /*IsInitializer=*/false);
352    EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, T);
353
354  } else
355    EmitDeclInit(*this, D, GV);
356
357  if (ThreadsafeStatics) {
358    // Call __cxa_guard_release.
359    Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable);
360  } else {
361    llvm::Value *One =
362      llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1);
363    Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy));
364  }
365
366  // Register the call to the destructor.
367  if (!D.getType()->isReferenceType())
368    EmitDeclDestroy(*this, D, GV);
369
370  if (ThreadsafeStatics && Exceptions) {
371    // If an exception is thrown during initialization, call __cxa_guard_abort
372    // along the exceptional edge.
373    EmitBranch(EndBlock);
374
375    // Construct the landing pad.
376    EmitBlock(LandingPad);
377
378    // Personality function and LLVM intrinsics.
379    llvm::Constant *Personality =
380      CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
381                                                        (VMContext),
382                                                        true),
383                                "__gxx_personality_v0");
384    Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty);
385    llvm::Value *llvm_eh_exception =
386      CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
387    llvm::Value *llvm_eh_selector =
388      CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
389
390    // Exception object
391    llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
392    llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow");
393
394    // Call the selector function.
395    const llvm::PointerType *PtrToInt8Ty
396      = llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(VMContext));
397    llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
398    llvm::Value* SelectorArgs[3] = { Exc, Personality, Null };
399    Builder.CreateCall(llvm_eh_selector, SelectorArgs, SelectorArgs + 3,
400                           "selector");
401    Builder.CreateStore(Exc, RethrowPtr);
402
403    // Call __cxa_guard_abort along the exceptional edge.
404    Builder.CreateCall(getGuardAbortFn(*this), GuardVariable);
405
406    setInvokeDest(SavedLandingPad);
407
408    // Rethrow the current exception.
409    if (getInvokeDest()) {
410      llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
411      Builder.CreateInvoke(getUnwindResumeOrRethrowFn(), Cont,
412                           getInvokeDest(),
413                           Builder.CreateLoad(RethrowPtr));
414      EmitBlock(Cont);
415    } else
416      Builder.CreateCall(getUnwindResumeOrRethrowFn(),
417                         Builder.CreateLoad(RethrowPtr));
418
419    Builder.CreateUnreachable();
420  }
421
422  EmitBlock(EndBlock);
423}
424
425/// GenerateCXXAggrDestructorHelper - Generates a helper function which when
426/// invoked, calls the default destructor on array elements in reverse order of
427/// construction.
428llvm::Function *
429CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
430                                                 const ArrayType *Array,
431                                                 llvm::Value *This) {
432  FunctionArgList Args;
433  ImplicitParamDecl *Dst =
434    ImplicitParamDecl::Create(getContext(), 0,
435                              SourceLocation(), 0,
436                              getContext().getPointerType(getContext().VoidTy));
437  Args.push_back(std::make_pair(Dst, Dst->getType()));
438
439  llvm::SmallString<16> Name;
440  llvm::raw_svector_ostream(Name) << "__tcf_" << (++UniqueAggrDestructorCount);
441  const CGFunctionInfo &FI =
442    CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args,
443                                   FunctionType::ExtInfo());
444  const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
445  llvm::Function *Fn =
446    llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, Name.str(),
447                           &CGM.getModule());
448
449  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, Args, SourceLocation());
450
451  QualType BaseElementTy = getContext().getBaseElementType(Array);
452  const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo();
453  llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr);
454
455  EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
456
457  FinishFunction();
458
459  return Fn;
460}
461