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 using namespace clang;
17 using namespace CodeGen;
18 
19 static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
20                          llvm::Constant *DeclPtr) {
21   assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
22   assert(!D.getType()->isReferenceType() &&
23          "Should not call EmitDeclInit on a reference!");
24 
25   ASTContext &Context = CGF.getContext();
26 
27   const Expr *Init = D.getInit();
28   QualType T = D.getType();
29   bool isVolatile = Context.getCanonicalType(T).isVolatileQualified();
30 
31   if (!CGF.hasAggregateLLVMType(T)) {
32     llvm::Value *V = CGF.EmitScalarExpr(Init);
33     CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, T);
34   } else if (T->isAnyComplexType()) {
35     CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
36   } else {
37     CGF.EmitAggExpr(Init, DeclPtr, isVolatile);
38   }
39 }
40 
41 static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
42                             llvm::Constant *DeclPtr) {
43   CodeGenModule &CGM = CGF.CGM;
44   ASTContext &Context = CGF.getContext();
45 
46   const Expr *Init = D.getInit();
47   QualType T = D.getType();
48   if (!CGF.hasAggregateLLVMType(T) || T->isAnyComplexType())
49     return;
50 
51   // Avoid generating destructor(s) for initialized objects.
52   if (!isa<CXXConstructExpr>(Init))
53     return;
54 
55   const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
56   if (Array)
57     T = Context.getBaseElementType(Array);
58 
59   const RecordType *RT = T->getAs<RecordType>();
60   if (!RT)
61     return;
62 
63   CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
64   if (RD->hasTrivialDestructor())
65     return;
66 
67   CXXDestructorDecl *Dtor = RD->getDestructor(Context);
68 
69   llvm::Constant *DtorFn;
70   if (Array) {
71     DtorFn =
72     CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor,
73                                                          Array,
74                                                          DeclPtr);
75     const llvm::Type *Int8PtrTy =
76     llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
77     DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
78   } else
79     DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
80 
81   CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
82 }
83 
84 void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
85                                                llvm::Constant *DeclPtr) {
86 
87   const Expr *Init = D.getInit();
88   QualType T = D.getType();
89 
90   if (!T->isReferenceType()) {
91     EmitDeclInit(*this, D, DeclPtr);
92     EmitDeclDestroy(*this, D, DeclPtr);
93     return;
94   }
95   if (Init->isLvalue(getContext()) == Expr::LV_Valid) {
96     RValue RV = EmitReferenceBindingToExpr(Init, /*IsInitializer=*/true);
97     EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, T);
98     return;
99   }
100   ErrorUnsupported(Init,
101                    "global variable that binds reference to a non-lvalue");
102 }
103 
104 void
105 CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
106                                                llvm::Constant *DeclPtr) {
107   // Generate a global destructor entry if not using __cxa_atexit.
108   if (!CGM.getCodeGenOpts().CXAAtExit) {
109     CGM.AddCXXDtorEntry(DtorFn, DeclPtr);
110     return;
111   }
112 
113   const llvm::Type *Int8PtrTy =
114     llvm::Type::getInt8Ty(VMContext)->getPointerTo();
115 
116   std::vector<const llvm::Type *> Params;
117   Params.push_back(Int8PtrTy);
118 
119   // Get the destructor function type
120   const llvm::Type *DtorFnTy =
121     llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
122   DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);
123 
124   Params.clear();
125   Params.push_back(DtorFnTy);
126   Params.push_back(Int8PtrTy);
127   Params.push_back(Int8PtrTy);
128 
129   // Get the __cxa_atexit function type
130   // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
131   const llvm::FunctionType *AtExitFnTy =
132     llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false);
133 
134   llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy,
135                                                        "__cxa_atexit");
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 
145 void
146 CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
147   const llvm::FunctionType *FTy
148     = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
149                               false);
150 
151   // Create a variable initialization function.
152   llvm::Function *Fn =
153     llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
154                            "__cxx_global_var_init", &TheModule);
155 
156   CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D);
157 
158   CXXGlobalInits.push_back(Fn);
159 }
160 
161 void
162 CodeGenModule::EmitCXXGlobalInitFunc() {
163   if (CXXGlobalInits.empty())
164     return;
165 
166   const llvm::FunctionType *FTy
167     = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
168                               false);
169 
170   // Create our global initialization function.
171   llvm::Function *Fn =
172     llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
173                            "_GLOBAL__I_a", &TheModule);
174 
175   CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
176                                                    &CXXGlobalInits[0],
177                                                    CXXGlobalInits.size());
178   AddGlobalCtor(Fn);
179 }
180 
181 void CodeGenModule::AddCXXDtorEntry(llvm::Constant *DtorFn,
182                                     llvm::Constant *Object) {
183   CXXGlobalDtors.push_back(std::make_pair(DtorFn, Object));
184 }
185 
186 void CodeGenModule::EmitCXXGlobalDtorFunc() {
187   if (CXXGlobalDtors.empty())
188     return;
189 
190   const llvm::FunctionType *FTy
191     = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
192                               false);
193 
194   // Create our global destructor function.
195   llvm::Function *Fn =
196     llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
197                            "_GLOBAL__D_a", &TheModule);
198 
199   CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors);
200   AddGlobalDtor(Fn);
201 }
202 
203 void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
204                                                        const VarDecl *D) {
205   StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
206                 SourceLocation());
207 
208   llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D);
209   EmitCXXGlobalVarDeclInit(*D, DeclPtr);
210 
211   FinishFunction();
212 }
213 
214 void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
215                                                 llvm::Constant **Decls,
216                                                 unsigned NumDecls) {
217   StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
218                 SourceLocation());
219 
220   for (unsigned i = 0; i != NumDecls; ++i)
221     Builder.CreateCall(Decls[i]);
222 
223   FinishFunction();
224 }
225 
226 void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
227                 const std::vector<std::pair<llvm::Constant*, llvm::Constant*> >
228                                                 &DtorsAndObjects) {
229   StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
230                 SourceLocation());
231 
232   // Emit the dtors, in reverse order from construction.
233   for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
234     llvm::Constant *Callee = DtorsAndObjects[e - i - 1].first;
235     llvm::CallInst *CI = Builder.CreateCall(Callee,
236                                             DtorsAndObjects[e - i - 1].second);
237     // Make sure the call and the callee agree on calling convention.
238     if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
239       CI->setCallingConv(F->getCallingConv());
240   }
241 
242   FinishFunction();
243 }
244 
245 static llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) {
246   // int __cxa_guard_acquire(__int64_t *guard_object);
247 
248   const llvm::Type *Int64PtrTy =
249     llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
250 
251   std::vector<const llvm::Type*> Args(1, Int64PtrTy);
252 
253   const llvm::FunctionType *FTy =
254     llvm::FunctionType::get(CGF.ConvertType(CGF.getContext().IntTy),
255                             Args, /*isVarArg=*/false);
256 
257   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire");
258 }
259 
260 static llvm::Constant *getGuardReleaseFn(CodeGenFunction &CGF) {
261   // void __cxa_guard_release(__int64_t *guard_object);
262 
263   const llvm::Type *Int64PtrTy =
264     llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
265 
266   std::vector<const llvm::Type*> Args(1, Int64PtrTy);
267 
268   const llvm::FunctionType *FTy =
269   llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
270                           Args, /*isVarArg=*/false);
271 
272   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release");
273 }
274 
275 static llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) {
276   // void __cxa_guard_abort(__int64_t *guard_object);
277 
278   const llvm::Type *Int64PtrTy =
279     llvm::Type::getInt64PtrTy(CGF.getLLVMContext());
280 
281   std::vector<const llvm::Type*> Args(1, Int64PtrTy);
282 
283   const llvm::FunctionType *FTy =
284   llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
285                           Args, /*isVarArg=*/false);
286 
287   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort");
288 }
289 
290 void
291 CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
292                                                llvm::GlobalVariable *GV) {
293   // Bail out early if this initializer isn't reachable.
294   if (!Builder.GetInsertBlock()) return;
295 
296   bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
297 
298   llvm::SmallString<256> GuardVName;
299   CGM.getMangleContext().mangleGuardVariable(&D, GuardVName);
300 
301   // Create the guard variable.
302   const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(VMContext);
303   llvm::GlobalValue *GuardVariable =
304     new llvm::GlobalVariable(CGM.getModule(), Int64Ty,
305                              false, GV->getLinkage(),
306                              llvm::Constant::getNullValue(Int64Ty),
307                              GuardVName.str());
308 
309   // Load the first byte of the guard variable.
310   const llvm::Type *PtrTy
311     = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
312   llvm::Value *V =
313     Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp");
314 
315   llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check");
316   llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
317 
318   // Check if the first byte of the guard variable is zero.
319   Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"),
320                        InitCheckBlock, EndBlock);
321 
322   EmitBlock(InitCheckBlock);
323 
324   if (ThreadsafeStatics) {
325     // Call __cxa_guard_acquire.
326     V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable);
327 
328     llvm::BasicBlock *InitBlock = createBasicBlock("init");
329 
330     Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
331                          InitBlock, EndBlock);
332 
333     EmitBlock(InitBlock);
334 
335     if (Exceptions) {
336       EHCleanupBlock Cleanup(*this);
337 
338       // Call __cxa_guard_abort.
339       Builder.CreateCall(getGuardAbortFn(*this), GuardVariable);
340     }
341   }
342 
343   if (D.getType()->isReferenceType()) {
344     QualType T = D.getType();
345     // We don't want to pass true for IsInitializer here, because a static
346     // reference to a temporary does not extend its lifetime.
347     RValue RV = EmitReferenceBindingToExpr(D.getInit(),
348                                            /*IsInitializer=*/false);
349     EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, T);
350 
351   } else
352     EmitDeclInit(*this, D, GV);
353 
354   if (ThreadsafeStatics) {
355     // Call __cxa_guard_release.
356     Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable);
357   } else {
358     llvm::Value *One =
359       llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1);
360     Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy));
361   }
362 
363   // Register the call to the destructor.
364   if (!D.getType()->isReferenceType())
365     EmitDeclDestroy(*this, D, GV);
366 
367   EmitBlock(EndBlock);
368 }
369