blob: 036be9288525c696b32813408939989d2380e8e1 [file] [log] [blame]
Anders Carlsson5ec2e7c2009-12-10 00:16:00 +00001//===--- 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"
Daniel Dunbarefb0fa92010-03-20 04:15:41 +000015#include "clang/CodeGen/CodeGenOptions.h"
Anders Carlsson5ec2e7c2009-12-10 00:16:00 +000016using namespace clang;
17using namespace CodeGen;
18
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000019static 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
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000025 ASTContext &Context = CGF.getContext();
26
Anders Carlsson5ec2e7c2009-12-10 00:16:00 +000027 const Expr *Init = D.getInit();
28 QualType T = D.getType();
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000029 bool isVolatile = Context.getCanonicalType(T).isVolatileQualified();
Anders Carlsson5ec2e7c2009-12-10 00:16:00 +000030
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000031 if (!CGF.hasAggregateLLVMType(T)) {
32 llvm::Value *V = CGF.EmitScalarExpr(Init);
33 CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, T);
Anders Carlsson5ec2e7c2009-12-10 00:16:00 +000034 } else if (T->isAnyComplexType()) {
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000035 CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
Anders Carlsson5ec2e7c2009-12-10 00:16:00 +000036 } else {
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000037 CGF.EmitAggExpr(Init, DeclPtr, isVolatile);
Anders Carlsson5ec2e7c2009-12-10 00:16:00 +000038 }
39}
40
Douglas Gregorcc6a44b2010-05-05 15:38:32 +000041static 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
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000084void 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);
Douglas Gregorcc6a44b2010-05-05 15:38:32 +000092 EmitDeclDestroy(*this, D, DeclPtr);
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000093 return;
94 }
Fariborz Jahanian616c1732010-01-25 21:40:39 +000095 if (Init->isLvalue(getContext()) == Expr::LV_Valid) {
Anders Carlssona64a8692010-02-03 16:38:03 +000096 RValue RV = EmitReferenceBindingToExpr(Init, /*IsInitializer=*/true);
Fariborz Jahanian616c1732010-01-25 21:40:39 +000097 EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, T);
98 return;
99 }
100 ErrorUnsupported(Init,
101 "global variable that binds reference to a non-lvalue");
Anders Carlssonfcbfdc12009-12-10 00:57:45 +0000102}
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000103
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000104void
105CodeGenFunction::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
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000113 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
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000145void
146CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
Eli Friedman6c6bda32010-01-08 00:50:11 +0000147 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
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000156 CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D);
Eli Friedman6c6bda32010-01-08 00:50:11 +0000157
158 CXXGlobalInits.push_back(Fn);
159}
160
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000161void
162CodeGenModule::EmitCXXGlobalInitFunc() {
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000163 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.
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000171 llvm::Function *Fn =
172 llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000173 "_GLOBAL__I_a", &TheModule);
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000174
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000175 CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
176 &CXXGlobalInits[0],
177 CXXGlobalInits.size());
178 AddGlobalCtor(Fn);
179}
180
181void CodeGenModule::AddCXXDtorEntry(llvm::Constant *DtorFn,
182 llvm::Constant *Object) {
183 CXXGlobalDtors.push_back(std::make_pair(DtorFn, Object));
184}
185
186void 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
203void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
204 const VarDecl *D) {
Daniel Dunbar5c6846e2010-03-20 04:15:29 +0000205 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
206 SourceLocation());
207
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000208 llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D);
209 EmitCXXGlobalVarDeclInit(*D, DeclPtr);
Daniel Dunbar5c6846e2010-03-20 04:15:29 +0000210
211 FinishFunction();
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000212}
Daniel Dunbar5c6846e2010-03-20 04:15:29 +0000213
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000214void 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
226void 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.
Chris Lattnerc9a85f92010-04-26 20:35:54 +0000233 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 }
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000241
242 FinishFunction();
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000243}
244
Anders Carlssona508b7d2010-02-06 23:23:06 +0000245static 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
260static 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
275static 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
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000290void
291CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
292 llvm::GlobalVariable *GV) {
John McCallfe67f3b2010-05-04 20:45:42 +0000293 // Bail out early if this initializer isn't reachable.
294 if (!Builder.GetInsertBlock()) return;
295
Anders Carlssona508b7d2010-02-06 23:23:06 +0000296 bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
297
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000298 llvm::SmallString<256> GuardVName;
299 CGM.getMangleContext().mangleGuardVariable(&D, GuardVName);
300
301 // Create the guard variable.
Anders Carlssona508b7d2010-02-06 23:23:06 +0000302 const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(VMContext);
303 llvm::GlobalValue *GuardVariable =
304 new llvm::GlobalVariable(CGM.getModule(), Int64Ty,
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000305 false, GV->getLinkage(),
Anders Carlssona508b7d2010-02-06 23:23:06 +0000306 llvm::Constant::getNullValue(Int64Ty),
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000307 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);
Anders Carlssona508b7d2010-02-06 23:23:06 +0000312 llvm::Value *V =
313 Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp");
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000314
Anders Carlssona508b7d2010-02-06 23:23:06 +0000315 llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check");
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000316 llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
317
Anders Carlssona508b7d2010-02-06 23:23:06 +0000318 // Check if the first byte of the guard variable is zero.
319 Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"),
320 InitCheckBlock, EndBlock);
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000321
Anders Carlssona508b7d2010-02-06 23:23:06 +0000322 EmitBlock(InitCheckBlock);
323
Douglas Gregor1eb2e592010-05-16 00:44:00 +0000324 if (ThreadsafeStatics) {
Anders Carlssona508b7d2010-02-06 23:23:06 +0000325 // 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
Douglas Gregorbfcc8232010-05-15 17:55:51 +0000333 EmitBlock(InitBlock);
Douglas Gregor1eb2e592010-05-16 00:44:00 +0000334
335 if (Exceptions) {
336 EHCleanupBlock Cleanup(*this);
337
338 // Call __cxa_guard_abort.
339 Builder.CreateCall(getGuardAbortFn(*this), GuardVariable);
340 }
Anders Carlssona508b7d2010-02-06 23:23:06 +0000341 }
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000342
Anders Carlssonfcbfdc12009-12-10 00:57:45 +0000343 if (D.getType()->isReferenceType()) {
Anders Carlsson864143f2009-12-10 01:58:33 +0000344 QualType T = D.getType();
Anders Carlssonc7974ca2009-12-10 01:05:11 +0000345 // We don't want to pass true for IsInitializer here, because a static
346 // reference to a temporary does not extend its lifetime.
Anders Carlssona64a8692010-02-03 16:38:03 +0000347 RValue RV = EmitReferenceBindingToExpr(D.getInit(),
Anders Carlsson864143f2009-12-10 01:58:33 +0000348 /*IsInitializer=*/false);
349 EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, T);
350
Anders Carlssonfcbfdc12009-12-10 00:57:45 +0000351 } else
352 EmitDeclInit(*this, D, GV);
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000353
Anders Carlssona508b7d2010-02-06 23:23:06 +0000354 if (ThreadsafeStatics) {
355 // Call __cxa_guard_release.
Douglas Gregor1eb2e592010-05-16 00:44:00 +0000356 Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable);
Anders Carlssona508b7d2010-02-06 23:23:06 +0000357 } else {
358 llvm::Value *One =
359 llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1);
360 Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy));
361 }
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000362
Douglas Gregorcc6a44b2010-05-05 15:38:32 +0000363 // Register the call to the destructor.
364 if (!D.getType()->isReferenceType())
365 EmitDeclDestroy(*this, D, GV);
366
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000367 EmitBlock(EndBlock);
368}