CGDeclCXX.cpp revision 210299
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/Frontend/CodeGenOptions.h" 16#include "llvm/Intrinsics.h" 17 18using namespace clang; 19using namespace CodeGen; 20 21static 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 27 ASTContext &Context = CGF.getContext(); 28 29 const Expr *Init = D.getInit(); 30 QualType T = D.getType(); 31 bool isVolatile = Context.getCanonicalType(T).isVolatileQualified(); 32 33 if (!CGF.hasAggregateLLVMType(T)) { 34 llvm::Value *V = CGF.EmitScalarExpr(Init); 35 CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, T); 36 } else if (T->isAnyComplexType()) { 37 CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile); 38 } else { 39 CGF.EmitAggExpr(Init, DeclPtr, isVolatile); 40 } 41} 42 43static 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(); 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 RValue RV = EmitReferenceBindingToExpr(Init, &D); 98 EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, T); 99} 100 101void 102CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, 103 llvm::Constant *DeclPtr) { 104 // Generate a global destructor entry if not using __cxa_atexit. 105 if (!CGM.getCodeGenOpts().CXAAtExit) { 106 CGM.AddCXXDtorEntry(DtorFn, DeclPtr); 107 return; 108 } 109 110 const llvm::Type *Int8PtrTy = 111 llvm::Type::getInt8Ty(VMContext)->getPointerTo(); 112 113 std::vector<const llvm::Type *> Params; 114 Params.push_back(Int8PtrTy); 115 116 // Get the destructor function type 117 const llvm::Type *DtorFnTy = 118 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); 119 DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy); 120 121 Params.clear(); 122 Params.push_back(DtorFnTy); 123 Params.push_back(Int8PtrTy); 124 Params.push_back(Int8PtrTy); 125 126 // Get the __cxa_atexit function type 127 // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d ); 128 const llvm::FunctionType *AtExitFnTy = 129 llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false); 130 131 llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy, 132 "__cxa_atexit"); 133 134 llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy, 135 "__dso_handle"); 136 llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy), 137 llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy), 138 llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) }; 139 Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args)); 140} 141 142static llvm::Function * 143CreateGlobalInitOrDestructFunction(CodeGenModule &CGM, 144 const llvm::FunctionType *FTy, 145 llvm::StringRef Name) { 146 llvm::Function *Fn = 147 llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, 148 Name, &CGM.getModule()); 149 150 // Set the section if needed. 151 if (const char *Section = 152 CGM.getContext().Target.getStaticInitSectionSpecifier()) 153 Fn->setSection(Section); 154 155 if (!CGM.getLangOptions().Exceptions) 156 Fn->setDoesNotThrow(); 157 158 return Fn; 159} 160 161void 162CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) { 163 const llvm::FunctionType *FTy 164 = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 165 false); 166 167 // Create a variable initialization function. 168 llvm::Function *Fn = 169 CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init"); 170 171 CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D); 172 173 if (D->hasAttr<InitPriorityAttr>()) { 174 unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority(); 175 OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size()); 176 PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn)); 177 } 178 else 179 CXXGlobalInits.push_back(Fn); 180} 181 182void 183CodeGenModule::EmitCXXGlobalInitFunc() { 184 if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty()) 185 return; 186 187 const llvm::FunctionType *FTy 188 = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 189 false); 190 191 // Create our global initialization function. 192 llvm::Function *Fn = 193 CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a"); 194 195 if (!PrioritizedCXXGlobalInits.empty()) { 196 llvm::SmallVector<llvm::Constant*, 8> LocalCXXGlobalInits; 197 llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(), 198 PrioritizedCXXGlobalInits.end()); 199 for (unsigned i = 0; i < PrioritizedCXXGlobalInits.size(); i++) { 200 llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second; 201 LocalCXXGlobalInits.push_back(Fn); 202 } 203 for (unsigned i = 0; i < CXXGlobalInits.size(); i++) 204 LocalCXXGlobalInits.push_back(CXXGlobalInits[i]); 205 CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, 206 &LocalCXXGlobalInits[0], 207 LocalCXXGlobalInits.size()); 208 } 209 else 210 CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, 211 &CXXGlobalInits[0], 212 CXXGlobalInits.size()); 213 AddGlobalCtor(Fn); 214} 215 216void CodeGenModule::EmitCXXGlobalDtorFunc() { 217 if (CXXGlobalDtors.empty()) 218 return; 219 220 const llvm::FunctionType *FTy 221 = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 222 false); 223 224 // Create our global destructor function. 225 llvm::Function *Fn = 226 CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a"); 227 228 CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors); 229 AddGlobalDtor(Fn); 230} 231 232void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, 233 const VarDecl *D) { 234 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 235 SourceLocation()); 236 237 llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D); 238 EmitCXXGlobalVarDeclInit(*D, DeclPtr); 239 240 FinishFunction(); 241} 242 243void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, 244 llvm::Constant **Decls, 245 unsigned NumDecls) { 246 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 247 SourceLocation()); 248 249 for (unsigned i = 0; i != NumDecls; ++i) 250 Builder.CreateCall(Decls[i]); 251 252 FinishFunction(); 253} 254 255void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn, 256 const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> > 257 &DtorsAndObjects) { 258 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 259 SourceLocation()); 260 261 // Emit the dtors, in reverse order from construction. 262 for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) { 263 llvm::Value *Callee = DtorsAndObjects[e - i - 1].first; 264 llvm::CallInst *CI = Builder.CreateCall(Callee, 265 DtorsAndObjects[e - i - 1].second); 266 // Make sure the call and the callee agree on calling convention. 267 if (llvm::Function *F = dyn_cast<llvm::Function>(Callee)) 268 CI->setCallingConv(F->getCallingConv()); 269 } 270 271 FinishFunction(); 272} 273 274static llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) { 275 // int __cxa_guard_acquire(__int64_t *guard_object); 276 277 const llvm::Type *Int64PtrTy = 278 llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); 279 280 std::vector<const llvm::Type*> Args(1, Int64PtrTy); 281 282 const llvm::FunctionType *FTy = 283 llvm::FunctionType::get(CGF.ConvertType(CGF.getContext().IntTy), 284 Args, /*isVarArg=*/false); 285 286 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire"); 287} 288 289static llvm::Constant *getGuardReleaseFn(CodeGenFunction &CGF) { 290 // void __cxa_guard_release(__int64_t *guard_object); 291 292 const llvm::Type *Int64PtrTy = 293 llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); 294 295 std::vector<const llvm::Type*> Args(1, Int64PtrTy); 296 297 const llvm::FunctionType *FTy = 298 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 299 Args, /*isVarArg=*/false); 300 301 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release"); 302} 303 304static llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) { 305 // void __cxa_guard_abort(__int64_t *guard_object); 306 307 const llvm::Type *Int64PtrTy = 308 llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); 309 310 std::vector<const llvm::Type*> Args(1, Int64PtrTy); 311 312 const llvm::FunctionType *FTy = 313 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 314 Args, /*isVarArg=*/false); 315 316 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort"); 317} 318 319void 320CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D, 321 llvm::GlobalVariable *GV) { 322 // Bail out early if this initializer isn't reachable. 323 if (!Builder.GetInsertBlock()) return; 324 325 bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics; 326 327 llvm::SmallString<256> GuardVName; 328 CGM.getMangleContext().mangleGuardVariable(&D, GuardVName); 329 330 // Create the guard variable. 331 llvm::GlobalValue *GuardVariable = 332 new llvm::GlobalVariable(CGM.getModule(), Int64Ty, 333 false, GV->getLinkage(), 334 llvm::Constant::getNullValue(Int64Ty), 335 GuardVName.str()); 336 337 // Load the first byte of the guard variable. 338 const llvm::Type *PtrTy 339 = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); 340 llvm::Value *V = 341 Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp"); 342 343 llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check"); 344 llvm::BasicBlock *EndBlock = createBasicBlock("init.end"); 345 346 // Check if the first byte of the guard variable is zero. 347 Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"), 348 InitCheckBlock, EndBlock); 349 350 EmitBlock(InitCheckBlock); 351 352 // Variables used when coping with thread-safe statics and exceptions. 353 if (ThreadsafeStatics) { 354 // Call __cxa_guard_acquire. 355 V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable); 356 357 llvm::BasicBlock *InitBlock = createBasicBlock("init"); 358 359 Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), 360 InitBlock, EndBlock); 361 362 // Call __cxa_guard_abort along the exceptional edge. 363 if (Exceptions) { 364 CleanupBlock Cleanup(*this, EHCleanup); 365 Builder.CreateCall(getGuardAbortFn(*this), GuardVariable); 366 } 367 368 EmitBlock(InitBlock); 369 } 370 371 if (D.getType()->isReferenceType()) { 372 QualType T = D.getType(); 373 RValue RV = EmitReferenceBindingToExpr(D.getInit(), &D); 374 EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, T); 375 376 } else 377 EmitDeclInit(*this, D, GV); 378 379 if (ThreadsafeStatics) { 380 // Call __cxa_guard_release. This cannot throw. 381 Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable); 382 } else { 383 llvm::Value *One = 384 llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1); 385 Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy)); 386 } 387 388 // Register the call to the destructor. 389 if (!D.getType()->isReferenceType()) 390 EmitDeclDestroy(*this, D, GV); 391 392 EmitBlock(EndBlock); 393} 394 395/// GenerateCXXAggrDestructorHelper - Generates a helper function which when 396/// invoked, calls the default destructor on array elements in reverse order of 397/// construction. 398llvm::Function * 399CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D, 400 const ArrayType *Array, 401 llvm::Value *This) { 402 FunctionArgList Args; 403 ImplicitParamDecl *Dst = 404 ImplicitParamDecl::Create(getContext(), 0, 405 SourceLocation(), 0, 406 getContext().getPointerType(getContext().VoidTy)); 407 Args.push_back(std::make_pair(Dst, Dst->getType())); 408 409 const CGFunctionInfo &FI = 410 CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args, 411 FunctionType::ExtInfo()); 412 const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false); 413 llvm::Function *Fn = 414 CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor"); 415 416 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, Args, SourceLocation()); 417 418 QualType BaseElementTy = getContext().getBaseElementType(Array); 419 const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo(); 420 llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr); 421 422 EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr); 423 424 FinishFunction(); 425 426 return Fn; 427} 428