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