blob: a09e836389ac47b787c93c4148e07f9bb6bfa591 [file] [log] [blame]
Anders Carlssonbc49cfe2009-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"
15using namespace clang;
16using namespace CodeGen;
17
18void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
19 llvm::Constant *DeclPtr) {
20 assert(D.hasGlobalStorage() &&
21 "VarDecl must have global storage!");
22
23 const Expr *Init = D.getInit();
24 QualType T = D.getType();
25 bool isVolatile = getContext().getCanonicalType(T).isVolatileQualified();
26
27 if (T->isReferenceType()) {
28 ErrorUnsupported(Init, "global variable that binds to a reference");
29 } else if (!hasAggregateLLVMType(T)) {
30 llvm::Value *V = EmitScalarExpr(Init);
31 EmitStoreOfScalar(V, DeclPtr, isVolatile, T);
32 } else if (T->isAnyComplexType()) {
33 EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
34 } else {
35 EmitAggExpr(Init, DeclPtr, isVolatile);
36 // Avoid generating destructor(s) for initialized objects.
37 if (!isa<CXXConstructExpr>(Init))
38 return;
39 const ConstantArrayType *Array = getContext().getAsConstantArrayType(T);
40 if (Array)
41 T = getContext().getBaseElementType(Array);
42
43 if (const RecordType *RT = T->getAs<RecordType>()) {
44 CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
45 if (!RD->hasTrivialDestructor()) {
46 llvm::Constant *DtorFn;
47 if (Array) {
48 DtorFn = CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(
49 RD->getDestructor(getContext()),
50 Array, DeclPtr);
51 DeclPtr =
52 llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
53 }
54 else
55 DtorFn = CGM.GetAddrOfCXXDestructor(RD->getDestructor(getContext()),
56 Dtor_Complete);
57 EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
58 }
59 }
60 }
61}
62
Anders Carlsson633c6f62009-12-10 00:30:05 +000063
64void
65CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
66 llvm::Constant *DeclPtr) {
67 const llvm::Type *Int8PtrTy =
68 llvm::Type::getInt8Ty(VMContext)->getPointerTo();
69
70 std::vector<const llvm::Type *> Params;
71 Params.push_back(Int8PtrTy);
72
73 // Get the destructor function type
74 const llvm::Type *DtorFnTy =
75 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
76 DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);
77
78 Params.clear();
79 Params.push_back(DtorFnTy);
80 Params.push_back(Int8PtrTy);
81 Params.push_back(Int8PtrTy);
82
83 // Get the __cxa_atexit function type
84 // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
85 const llvm::FunctionType *AtExitFnTy =
86 llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false);
87
88 llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy,
89 "__cxa_atexit");
90
91 llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
92 "__dso_handle");
93 llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
94 llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
95 llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
96 Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
97}
98
99void
100CodeGenModule::EmitCXXGlobalInitFunc() {
101 if (CXXGlobalInits.empty())
102 return;
103
104 const llvm::FunctionType *FTy
105 = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
106 false);
107
108 // Create our global initialization function.
109 // FIXME: Should this be tweakable by targets?
110 llvm::Function *Fn =
111 llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
112 "__cxx_global_initialization", &TheModule);
113
114 CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
115 &CXXGlobalInits[0],
116 CXXGlobalInits.size());
117 AddGlobalCtor(Fn);
118}
119
120void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
121 const VarDecl **Decls,
122 unsigned NumDecls) {
123 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
124 SourceLocation());
125
126 for (unsigned i = 0; i != NumDecls; ++i) {
127 const VarDecl *D = Decls[i];
128
129 llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D);
130 EmitCXXGlobalVarDeclInit(*D, DeclPtr);
131 }
132 FinishFunction();
133}
134
135void
136CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
137 llvm::GlobalVariable *GV) {
138 // FIXME: This should use __cxa_guard_{acquire,release}?
139
140 assert(!getContext().getLangOptions().ThreadsafeStatics &&
141 "thread safe statics are currently not supported!");
142
143 llvm::SmallString<256> GuardVName;
144 CGM.getMangleContext().mangleGuardVariable(&D, GuardVName);
145
146 // Create the guard variable.
147 llvm::GlobalValue *GuardV =
148 new llvm::GlobalVariable(CGM.getModule(), llvm::Type::getInt64Ty(VMContext),
149 false, GV->getLinkage(),
150 llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)),
151 GuardVName.str());
152
153 // Load the first byte of the guard variable.
154 const llvm::Type *PtrTy
155 = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
156 llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy),
157 "tmp");
158
159 // Compare it against 0.
160 llvm::Value *nullValue
161 = llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext));
162 llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool");
163
164 llvm::BasicBlock *InitBlock = createBasicBlock("init");
165 llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
166
167 // If the guard variable is 0, jump to the initializer code.
168 Builder.CreateCondBr(ICmp, InitBlock, EndBlock);
169
170 EmitBlock(InitBlock);
171
172 EmitCXXGlobalVarDeclInit(D, GV);
173
174 Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext),
175 1),
176 Builder.CreateBitCast(GuardV, PtrTy));
177
178 EmitBlock(EndBlock);
179}