blob: f94ddd988662ba7a1856d245931ef9dd2c960fcf [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"
Douglas Gregor86a3a032010-05-16 01:24:12 +000016#include "llvm/Intrinsics.h"
17
Anders Carlsson5ec2e7c2009-12-10 00:16:00 +000018using namespace clang;
19using namespace CodeGen;
20
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000021static 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
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000027 ASTContext &Context = CGF.getContext();
28
Anders Carlsson5ec2e7c2009-12-10 00:16:00 +000029 const Expr *Init = D.getInit();
30 QualType T = D.getType();
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000031 bool isVolatile = Context.getCanonicalType(T).isVolatileQualified();
Anders Carlsson5ec2e7c2009-12-10 00:16:00 +000032
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000033 if (!CGF.hasAggregateLLVMType(T)) {
34 llvm::Value *V = CGF.EmitScalarExpr(Init);
35 CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, T);
Anders Carlsson5ec2e7c2009-12-10 00:16:00 +000036 } else if (T->isAnyComplexType()) {
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000037 CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
Anders Carlsson5ec2e7c2009-12-10 00:16:00 +000038 } else {
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000039 CGF.EmitAggExpr(Init, DeclPtr, isVolatile);
Anders Carlsson5ec2e7c2009-12-10 00:16:00 +000040 }
41}
42
Douglas Gregorcc6a44b2010-05-05 15:38:32 +000043static 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
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000086void 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);
Douglas Gregorcc6a44b2010-05-05 15:38:32 +000094 EmitDeclDestroy(*this, D, DeclPtr);
Anders Carlssonfcbfdc12009-12-10 00:57:45 +000095 return;
96 }
Fariborz Jahanian616c1732010-01-25 21:40:39 +000097 if (Init->isLvalue(getContext()) == Expr::LV_Valid) {
Anders Carlssona64a8692010-02-03 16:38:03 +000098 RValue RV = EmitReferenceBindingToExpr(Init, /*IsInitializer=*/true);
Fariborz Jahanian616c1732010-01-25 21:40:39 +000099 EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, T);
100 return;
101 }
102 ErrorUnsupported(Init,
103 "global variable that binds reference to a non-lvalue");
Anders Carlssonfcbfdc12009-12-10 00:57:45 +0000104}
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000105
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000106void
107CodeGenFunction::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
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000115 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
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000147void
148CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
Eli Friedman6c6bda32010-01-08 00:50:11 +0000149 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
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000158 CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D);
Eli Friedman6c6bda32010-01-08 00:50:11 +0000159
160 CXXGlobalInits.push_back(Fn);
161}
162
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000163void
164CodeGenModule::EmitCXXGlobalInitFunc() {
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000165 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.
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000173 llvm::Function *Fn =
174 llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000175 "_GLOBAL__I_a", &TheModule);
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000176
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000177 CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
178 &CXXGlobalInits[0],
179 CXXGlobalInits.size());
180 AddGlobalCtor(Fn);
181}
182
183void CodeGenModule::AddCXXDtorEntry(llvm::Constant *DtorFn,
184 llvm::Constant *Object) {
185 CXXGlobalDtors.push_back(std::make_pair(DtorFn, Object));
186}
187
188void 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
205void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
206 const VarDecl *D) {
Daniel Dunbar5c6846e2010-03-20 04:15:29 +0000207 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
208 SourceLocation());
209
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000210 llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D);
211 EmitCXXGlobalVarDeclInit(*D, DeclPtr);
Daniel Dunbar5c6846e2010-03-20 04:15:29 +0000212
213 FinishFunction();
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000214}
Daniel Dunbar5c6846e2010-03-20 04:15:29 +0000215
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000216void 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
228void 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.
Chris Lattnerc9a85f92010-04-26 20:35:54 +0000235 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 }
Daniel Dunbarefb0fa92010-03-20 04:15:41 +0000243
244 FinishFunction();
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000245}
246
Anders Carlssona508b7d2010-02-06 23:23:06 +0000247static 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
262static 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
277static 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
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000292void
293CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
294 llvm::GlobalVariable *GV) {
John McCallfe67f3b2010-05-04 20:45:42 +0000295 // Bail out early if this initializer isn't reachable.
296 if (!Builder.GetInsertBlock()) return;
297
Anders Carlssona508b7d2010-02-06 23:23:06 +0000298 bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
299
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000300 llvm::SmallString<256> GuardVName;
301 CGM.getMangleContext().mangleGuardVariable(&D, GuardVName);
302
303 // Create the guard variable.
Anders Carlssona508b7d2010-02-06 23:23:06 +0000304 const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(VMContext);
305 llvm::GlobalValue *GuardVariable =
306 new llvm::GlobalVariable(CGM.getModule(), Int64Ty,
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000307 false, GV->getLinkage(),
Anders Carlssona508b7d2010-02-06 23:23:06 +0000308 llvm::Constant::getNullValue(Int64Ty),
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000309 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);
Anders Carlssona508b7d2010-02-06 23:23:06 +0000314 llvm::Value *V =
315 Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp");
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000316
Anders Carlssona508b7d2010-02-06 23:23:06 +0000317 llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check");
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000318 llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
319
Anders Carlssona508b7d2010-02-06 23:23:06 +0000320 // Check if the first byte of the guard variable is zero.
321 Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"),
322 InitCheckBlock, EndBlock);
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000323
Anders Carlssona508b7d2010-02-06 23:23:06 +0000324 EmitBlock(InitCheckBlock);
325
Douglas Gregor86a3a032010-05-16 01:24:12 +0000326 // Variables used when coping with thread-safe statics and exceptions.
327 llvm::BasicBlock *SavedLandingPad = 0;
328 llvm::BasicBlock *LandingPad = 0;
329 if (ThreadsafeStatics) {
Anders Carlssona508b7d2010-02-06 23:23:06 +0000330 // 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
Douglas Gregor1eb2e592010-05-16 00:44:00 +0000338 if (Exceptions) {
Douglas Gregor86a3a032010-05-16 01:24:12 +0000339 SavedLandingPad = getInvokeDest();
340 LandingPad = createBasicBlock("guard.lpad");
341 setInvokeDest(LandingPad);
Douglas Gregor1eb2e592010-05-16 00:44:00 +0000342 }
Douglas Gregor86a3a032010-05-16 01:24:12 +0000343
344 EmitBlock(InitBlock);
Anders Carlssona508b7d2010-02-06 23:23:06 +0000345 }
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000346
Anders Carlssonfcbfdc12009-12-10 00:57:45 +0000347 if (D.getType()->isReferenceType()) {
Anders Carlsson864143f2009-12-10 01:58:33 +0000348 QualType T = D.getType();
Anders Carlssonc7974ca2009-12-10 01:05:11 +0000349 // We don't want to pass true for IsInitializer here, because a static
350 // reference to a temporary does not extend its lifetime.
Anders Carlssona64a8692010-02-03 16:38:03 +0000351 RValue RV = EmitReferenceBindingToExpr(D.getInit(),
Anders Carlsson864143f2009-12-10 01:58:33 +0000352 /*IsInitializer=*/false);
353 EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, T);
354
Anders Carlssonfcbfdc12009-12-10 00:57:45 +0000355 } else
356 EmitDeclInit(*this, D, GV);
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000357
Anders Carlssona508b7d2010-02-06 23:23:06 +0000358 if (ThreadsafeStatics) {
359 // Call __cxa_guard_release.
Douglas Gregor86a3a032010-05-16 01:24:12 +0000360 Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable);
Anders Carlssona508b7d2010-02-06 23:23:06 +0000361 } else {
362 llvm::Value *One =
363 llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1);
364 Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy));
365 }
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000366
Douglas Gregorcc6a44b2010-05-05 15:38:32 +0000367 // Register the call to the destructor.
368 if (!D.getType()->isReferenceType())
369 EmitDeclDestroy(*this, D, GV);
370
Douglas Gregor86a3a032010-05-16 01:24:12 +0000371 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
Anders Carlssoneb4072e2009-12-10 00:30:05 +0000423 EmitBlock(EndBlock);
424}