CGDeclCXX.cpp revision 354e712c81fbb07c0ce5f06180788b25fffa1b56
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 "CGCXXABI.h" 16#include "clang/Frontend/CodeGenOptions.h" 17#include "llvm/Intrinsics.h" 18 19using namespace clang; 20using namespace CodeGen; 21 22static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D, 23 llvm::Constant *DeclPtr) { 24 assert(D.hasGlobalStorage() && "VarDecl must have global storage!"); 25 assert(!D.getType()->isReferenceType() && 26 "Should not call EmitDeclInit on a reference!"); 27 28 ASTContext &Context = CGF.getContext(); 29 30 const Expr *Init = D.getInit(); 31 QualType T = D.getType(); 32 bool isVolatile = Context.getCanonicalType(T).isVolatileQualified(); 33 34 unsigned Alignment = Context.getDeclAlign(&D).getQuantity(); 35 if (!CGF.hasAggregateLLVMType(T)) { 36 llvm::Value *V = CGF.EmitScalarExpr(Init); 37 CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, Alignment, T); 38 } else if (T->isAnyComplexType()) { 39 CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile); 40 } else { 41 CGF.EmitAggExpr(Init, AggValueSlot::forAddr(DeclPtr, isVolatile, true)); 42 } 43} 44 45/// Emit code to cause the destruction of the given variable with 46/// static storage duration. 47static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D, 48 llvm::Constant *DeclPtr) { 49 CodeGenModule &CGM = CGF.CGM; 50 ASTContext &Context = CGF.getContext(); 51 52 QualType T = D.getType(); 53 54 // Drill down past array types. 55 const ConstantArrayType *Array = Context.getAsConstantArrayType(T); 56 if (Array) 57 T = Context.getBaseElementType(Array); 58 59 /// If that's not a record, we're done. 60 /// FIXME: __attribute__((cleanup)) ? 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(); 70 71 llvm::Constant *DtorFn; 72 if (Array) { 73 DtorFn = 74 CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, Array, 75 DeclPtr); 76 const llvm::Type *Int8PtrTy = 77 llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); 78 DeclPtr = llvm::Constant::getNullValue(Int8PtrTy); 79 } else 80 DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete); 81 82 CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr); 83} 84 85void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, 86 llvm::Constant *DeclPtr) { 87 88 const Expr *Init = D.getInit(); 89 QualType T = D.getType(); 90 91 if (!T->isReferenceType()) { 92 EmitDeclInit(*this, D, DeclPtr); 93 EmitDeclDestroy(*this, D, DeclPtr); 94 return; 95 } 96 97 unsigned Alignment = getContext().getDeclAlign(&D).getQuantity(); 98 RValue RV = EmitReferenceBindingToExpr(Init, &D); 99 EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T); 100} 101 102void 103CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, 104 llvm::Constant *DeclPtr) { 105 // Generate a global destructor entry if not using __cxa_atexit. 106 if (!CGM.getCodeGenOpts().CXAAtExit) { 107 CGM.AddCXXDtorEntry(DtorFn, DeclPtr); 108 return; 109 } 110 111 const llvm::Type *Int8PtrTy = 112 llvm::Type::getInt8Ty(VMContext)->getPointerTo(); 113 114 std::vector<const llvm::Type *> Params; 115 Params.push_back(Int8PtrTy); 116 117 // Get the destructor function type 118 const llvm::Type *DtorFnTy = 119 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); 120 DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy); 121 122 Params.clear(); 123 Params.push_back(DtorFnTy); 124 Params.push_back(Int8PtrTy); 125 Params.push_back(Int8PtrTy); 126 127 // Get the __cxa_atexit function type 128 // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d ); 129 const llvm::FunctionType *AtExitFnTy = 130 llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false); 131 132 llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy, 133 "__cxa_atexit"); 134 135 llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy, 136 "__dso_handle"); 137 llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy), 138 llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy), 139 llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) }; 140 Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args)); 141} 142 143void CodeGenFunction::EmitCXXStaticLocalInit(const VarDecl &D, 144 llvm::GlobalVariable *DeclPtr) { 145 CGM.getCXXABI().EmitStaticLocalInit(*this, D, DeclPtr); 146} 147 148static llvm::Function * 149CreateGlobalInitOrDestructFunction(CodeGenModule &CGM, 150 const llvm::FunctionType *FTy, 151 llvm::StringRef Name) { 152 llvm::Function *Fn = 153 llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, 154 Name, &CGM.getModule()); 155 156 // Set the section if needed. 157 if (const char *Section = 158 CGM.getContext().Target.getStaticInitSectionSpecifier()) 159 Fn->setSection(Section); 160 161 if (!CGM.getLangOptions().Exceptions) 162 Fn->setDoesNotThrow(); 163 164 return Fn; 165} 166 167void 168CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) { 169 const llvm::FunctionType *FTy 170 = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 171 false); 172 173 // Create a variable initialization function. 174 llvm::Function *Fn = 175 CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init"); 176 177 CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D); 178 179 if (D->hasAttr<InitPriorityAttr>()) { 180 unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority(); 181 OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size()); 182 PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn)); 183 DelayedCXXInitPosition.erase(D); 184 } 185 else { 186 llvm::DenseMap<const Decl *, unsigned>::iterator I = 187 DelayedCXXInitPosition.find(D); 188 if (I == DelayedCXXInitPosition.end()) { 189 CXXGlobalInits.push_back(Fn); 190 } else { 191 assert(CXXGlobalInits[I->second] == 0); 192 CXXGlobalInits[I->second] = Fn; 193 DelayedCXXInitPosition.erase(I); 194 } 195 } 196} 197 198void 199CodeGenModule::EmitCXXGlobalInitFunc() { 200 while (!CXXGlobalInits.empty() && !CXXGlobalInits.back()) 201 CXXGlobalInits.pop_back(); 202 203 if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty()) 204 return; 205 206 const llvm::FunctionType *FTy 207 = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 208 false); 209 210 // Create our global initialization function. 211 llvm::Function *Fn = 212 CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a"); 213 214 if (!PrioritizedCXXGlobalInits.empty()) { 215 llvm::SmallVector<llvm::Constant*, 8> LocalCXXGlobalInits; 216 llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(), 217 PrioritizedCXXGlobalInits.end()); 218 for (unsigned i = 0; i < PrioritizedCXXGlobalInits.size(); i++) { 219 llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second; 220 LocalCXXGlobalInits.push_back(Fn); 221 } 222 LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end()); 223 CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, 224 &LocalCXXGlobalInits[0], 225 LocalCXXGlobalInits.size()); 226 } 227 else 228 CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, 229 &CXXGlobalInits[0], 230 CXXGlobalInits.size()); 231 AddGlobalCtor(Fn); 232} 233 234void CodeGenModule::EmitCXXGlobalDtorFunc() { 235 if (CXXGlobalDtors.empty()) 236 return; 237 238 const llvm::FunctionType *FTy 239 = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 240 false); 241 242 // Create our global destructor function. 243 llvm::Function *Fn = 244 CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a"); 245 246 CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors); 247 AddGlobalDtor(Fn); 248} 249 250void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, 251 const VarDecl *D) { 252 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 253 SourceLocation()); 254 255 llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D); 256 if (D->isStaticDataMember() && 257 D->getInstantiatedFromStaticDataMember() && D->getInit()){ 258 llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(DeclPtr); 259 assert(GV && "GenerateCXXGlobalVarDeclInitFunc - GV is null"); 260 llvm::GlobalValue::LinkageTypes Linkage = 261 CGM.GetLLVMLinkageVarDefinition(D, GV); 262 if (Linkage == llvm::GlobalVariable::WeakAnyLinkage) { 263 GV->setConstant(false); 264 EmitCXXStaticLocalInit(*D, GV); 265 FinishFunction(); 266 return; 267 } 268 } 269 EmitCXXGlobalVarDeclInit(*D, DeclPtr); 270 271 FinishFunction(); 272} 273 274void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, 275 llvm::Constant **Decls, 276 unsigned NumDecls) { 277 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 278 SourceLocation()); 279 280 for (unsigned i = 0; i != NumDecls; ++i) 281 if (Decls[i]) 282 Builder.CreateCall(Decls[i]); 283 284 FinishFunction(); 285} 286 287void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn, 288 const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> > 289 &DtorsAndObjects) { 290 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 291 SourceLocation()); 292 293 // Emit the dtors, in reverse order from construction. 294 for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) { 295 llvm::Value *Callee = DtorsAndObjects[e - i - 1].first; 296 llvm::CallInst *CI = Builder.CreateCall(Callee, 297 DtorsAndObjects[e - i - 1].second); 298 // Make sure the call and the callee agree on calling convention. 299 if (llvm::Function *F = dyn_cast<llvm::Function>(Callee)) 300 CI->setCallingConv(F->getCallingConv()); 301 } 302 303 FinishFunction(); 304} 305 306/// GenerateCXXAggrDestructorHelper - Generates a helper function which when 307/// invoked, calls the default destructor on array elements in reverse order of 308/// construction. 309llvm::Function * 310CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D, 311 const ArrayType *Array, 312 llvm::Value *This) { 313 FunctionArgList Args; 314 ImplicitParamDecl *Dst = 315 ImplicitParamDecl::Create(getContext(), 0, 316 SourceLocation(), 0, 317 getContext().getPointerType(getContext().VoidTy)); 318 Args.push_back(std::make_pair(Dst, Dst->getType())); 319 320 const CGFunctionInfo &FI = 321 CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args, 322 FunctionType::ExtInfo()); 323 const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false); 324 llvm::Function *Fn = 325 CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor"); 326 327 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, Args, SourceLocation()); 328 329 QualType BaseElementTy = getContext().getBaseElementType(Array); 330 const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo(); 331 llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr); 332 333 EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr); 334 335 FinishFunction(); 336 337 return Fn; 338} 339