CGDeclCXX.cpp revision 91a16fa3265686b90054715eea504d9b4a13438b
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 unsigned Alignment = Context.getDeclAlign(&D).getQuantity(); 34 if (!CGF.hasAggregateLLVMType(T)) { 35 llvm::Value *V = CGF.EmitScalarExpr(Init); 36 CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, Alignment, T); 37 } else if (T->isAnyComplexType()) { 38 CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile); 39 } else { 40 CGF.EmitAggExpr(Init, DeclPtr, isVolatile); 41 } 42} 43 44static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D, 45 llvm::Constant *DeclPtr) { 46 CodeGenModule &CGM = CGF.CGM; 47 ASTContext &Context = CGF.getContext(); 48 49 QualType T = D.getType(); 50 51 // Drill down past array types. 52 const ConstantArrayType *Array = Context.getAsConstantArrayType(T); 53 if (Array) 54 T = Context.getBaseElementType(Array); 55 56 /// If that's not a record, we're done. 57 /// FIXME: __attribute__((cleanup)) ? 58 const RecordType *RT = T->getAs<RecordType>(); 59 if (!RT) 60 return; 61 62 CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); 63 if (RD->hasTrivialDestructor()) 64 return; 65 66 CXXDestructorDecl *Dtor = RD->getDestructor(); 67 68 llvm::Constant *DtorFn; 69 if (Array) { 70 DtorFn = 71 CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, Array, 72 DeclPtr); 73 const llvm::Type *Int8PtrTy = 74 llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); 75 DeclPtr = llvm::Constant::getNullValue(Int8PtrTy); 76 } else 77 DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete); 78 79 CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr); 80} 81 82void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, 83 llvm::Constant *DeclPtr) { 84 85 const Expr *Init = D.getInit(); 86 QualType T = D.getType(); 87 88 if (!T->isReferenceType()) { 89 EmitDeclInit(*this, D, DeclPtr); 90 EmitDeclDestroy(*this, D, DeclPtr); 91 return; 92 } 93 94 unsigned Alignment = getContext().getDeclAlign(&D).getQuantity(); 95 RValue RV = EmitReferenceBindingToExpr(Init, &D); 96 EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T); 97} 98 99void 100CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, 101 llvm::Constant *DeclPtr) { 102 // Generate a global destructor entry if not using __cxa_atexit. 103 if (!CGM.getCodeGenOpts().CXAAtExit) { 104 CGM.AddCXXDtorEntry(DtorFn, DeclPtr); 105 return; 106 } 107 108 const llvm::Type *Int8PtrTy = 109 llvm::Type::getInt8Ty(VMContext)->getPointerTo(); 110 111 std::vector<const llvm::Type *> Params; 112 Params.push_back(Int8PtrTy); 113 114 // Get the destructor function type 115 const llvm::Type *DtorFnTy = 116 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); 117 DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy); 118 119 Params.clear(); 120 Params.push_back(DtorFnTy); 121 Params.push_back(Int8PtrTy); 122 Params.push_back(Int8PtrTy); 123 124 // Get the __cxa_atexit function type 125 // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d ); 126 const llvm::FunctionType *AtExitFnTy = 127 llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false); 128 129 llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy, 130 "__cxa_atexit"); 131 132 llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy, 133 "__dso_handle"); 134 llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy), 135 llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy), 136 llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) }; 137 Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args)); 138} 139 140static llvm::Function * 141CreateGlobalInitOrDestructFunction(CodeGenModule &CGM, 142 const llvm::FunctionType *FTy, 143 llvm::StringRef Name) { 144 llvm::Function *Fn = 145 llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, 146 Name, &CGM.getModule()); 147 148 // Set the section if needed. 149 if (const char *Section = 150 CGM.getContext().Target.getStaticInitSectionSpecifier()) 151 Fn->setSection(Section); 152 153 if (!CGM.getLangOptions().Exceptions) 154 Fn->setDoesNotThrow(); 155 156 return Fn; 157} 158 159void 160CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) { 161 const llvm::FunctionType *FTy 162 = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 163 false); 164 165 // Create a variable initialization function. 166 llvm::Function *Fn = 167 CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init"); 168 169 CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D); 170 171 if (D->hasAttr<InitPriorityAttr>()) { 172 unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority(); 173 OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size()); 174 PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn)); 175 DelayedCXXInitPosition.erase(D); 176 } 177 else { 178 llvm::DenseMap<const Decl *, unsigned>::iterator I = 179 DelayedCXXInitPosition.find(D); 180 if (I == DelayedCXXInitPosition.end()) { 181 CXXGlobalInits.push_back(Fn); 182 } else { 183 assert(CXXGlobalInits[I->second] == 0); 184 CXXGlobalInits[I->second] = Fn; 185 DelayedCXXInitPosition.erase(I); 186 } 187 } 188} 189 190void 191CodeGenModule::EmitCXXGlobalInitFunc() { 192 while (!CXXGlobalInits.empty() && !CXXGlobalInits.back()) 193 CXXGlobalInits.pop_back(); 194 195 if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty()) 196 return; 197 198 const llvm::FunctionType *FTy 199 = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 200 false); 201 202 // Create our global initialization function. 203 llvm::Function *Fn = 204 CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a"); 205 206 if (!PrioritizedCXXGlobalInits.empty()) { 207 llvm::SmallVector<llvm::Constant*, 8> LocalCXXGlobalInits; 208 llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(), 209 PrioritizedCXXGlobalInits.end()); 210 for (unsigned i = 0; i < PrioritizedCXXGlobalInits.size(); i++) { 211 llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second; 212 LocalCXXGlobalInits.push_back(Fn); 213 } 214 LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end()); 215 CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, 216 &LocalCXXGlobalInits[0], 217 LocalCXXGlobalInits.size()); 218 } 219 else 220 CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, 221 &CXXGlobalInits[0], 222 CXXGlobalInits.size()); 223 AddGlobalCtor(Fn); 224} 225 226void CodeGenModule::EmitCXXGlobalDtorFunc() { 227 if (CXXGlobalDtors.empty()) 228 return; 229 230 const llvm::FunctionType *FTy 231 = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 232 false); 233 234 // Create our global destructor function. 235 llvm::Function *Fn = 236 CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a"); 237 238 CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors); 239 AddGlobalDtor(Fn); 240} 241 242void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, 243 const VarDecl *D) { 244 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 245 SourceLocation()); 246 247 llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D); 248 EmitCXXGlobalVarDeclInit(*D, DeclPtr); 249 250 FinishFunction(); 251} 252 253void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, 254 llvm::Constant **Decls, 255 unsigned NumDecls) { 256 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 257 SourceLocation()); 258 259 for (unsigned i = 0; i != NumDecls; ++i) 260 if (Decls[i]) 261 Builder.CreateCall(Decls[i]); 262 263 FinishFunction(); 264} 265 266void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn, 267 const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> > 268 &DtorsAndObjects) { 269 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 270 SourceLocation()); 271 272 // Emit the dtors, in reverse order from construction. 273 for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) { 274 llvm::Value *Callee = DtorsAndObjects[e - i - 1].first; 275 llvm::CallInst *CI = Builder.CreateCall(Callee, 276 DtorsAndObjects[e - i - 1].second); 277 // Make sure the call and the callee agree on calling convention. 278 if (llvm::Function *F = dyn_cast<llvm::Function>(Callee)) 279 CI->setCallingConv(F->getCallingConv()); 280 } 281 282 FinishFunction(); 283} 284 285static llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) { 286 // int __cxa_guard_acquire(__int64_t *guard_object); 287 288 const llvm::Type *Int64PtrTy = 289 llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); 290 291 std::vector<const llvm::Type*> Args(1, Int64PtrTy); 292 293 const llvm::FunctionType *FTy = 294 llvm::FunctionType::get(CGF.ConvertType(CGF.getContext().IntTy), 295 Args, /*isVarArg=*/false); 296 297 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire"); 298} 299 300static llvm::Constant *getGuardReleaseFn(CodeGenFunction &CGF) { 301 // void __cxa_guard_release(__int64_t *guard_object); 302 303 const llvm::Type *Int64PtrTy = 304 llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); 305 306 std::vector<const llvm::Type*> Args(1, Int64PtrTy); 307 308 const llvm::FunctionType *FTy = 309 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 310 Args, /*isVarArg=*/false); 311 312 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release"); 313} 314 315static llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) { 316 // void __cxa_guard_abort(__int64_t *guard_object); 317 318 const llvm::Type *Int64PtrTy = 319 llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); 320 321 std::vector<const llvm::Type*> Args(1, Int64PtrTy); 322 323 const llvm::FunctionType *FTy = 324 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 325 Args, /*isVarArg=*/false); 326 327 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort"); 328} 329 330namespace { 331 struct CallGuardAbort : EHScopeStack::Cleanup { 332 llvm::GlobalVariable *Guard; 333 CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {} 334 335 void Emit(CodeGenFunction &CGF, bool IsForEH) { 336 // It shouldn't be possible for this to throw, but if it can, 337 // this should allow for the possibility of an invoke. 338 CGF.Builder.CreateCall(getGuardAbortFn(CGF), Guard) 339 ->setDoesNotThrow(); 340 } 341 }; 342} 343 344void 345CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D, 346 llvm::GlobalVariable *GV) { 347 // Bail out early if this initializer isn't reachable. 348 if (!Builder.GetInsertBlock()) return; 349 350 bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics; 351 352 llvm::SmallString<256> GuardVName; 353 CGM.getMangleContext().mangleGuardVariable(&D, GuardVName); 354 355 // Create the guard variable. 356 llvm::GlobalVariable *GuardVariable = 357 new llvm::GlobalVariable(CGM.getModule(), Int64Ty, 358 false, GV->getLinkage(), 359 llvm::Constant::getNullValue(Int64Ty), 360 GuardVName.str()); 361 362 // Load the first byte of the guard variable. 363 const llvm::Type *PtrTy 364 = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); 365 llvm::Value *V = 366 Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp"); 367 368 llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check"); 369 llvm::BasicBlock *EndBlock = createBasicBlock("init.end"); 370 371 // Check if the first byte of the guard variable is zero. 372 Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"), 373 InitCheckBlock, EndBlock); 374 375 EmitBlock(InitCheckBlock); 376 377 // Variables used when coping with thread-safe statics and exceptions. 378 if (ThreadsafeStatics) { 379 // Call __cxa_guard_acquire. 380 V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable); 381 382 llvm::BasicBlock *InitBlock = createBasicBlock("init"); 383 384 Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), 385 InitBlock, EndBlock); 386 387 // Call __cxa_guard_abort along the exceptional edge. 388 if (Exceptions) 389 EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable); 390 391 EmitBlock(InitBlock); 392 } 393 394 if (D.getType()->isReferenceType()) { 395 unsigned Alignment = getContext().getDeclAlign(&D).getQuantity(); 396 QualType T = D.getType(); 397 RValue RV = EmitReferenceBindingToExpr(D.getInit(), &D); 398 EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, Alignment, T); 399 } else 400 EmitDeclInit(*this, D, GV); 401 402 if (ThreadsafeStatics) { 403 // Pop the guard-abort cleanup if we pushed one. 404 if (Exceptions) 405 PopCleanupBlock(); 406 407 // Call __cxa_guard_release. This cannot throw. 408 Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable); 409 } else { 410 llvm::Value *One = 411 llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1); 412 Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy)); 413 } 414 415 // Register the call to the destructor. 416 if (!D.getType()->isReferenceType()) 417 EmitDeclDestroy(*this, D, GV); 418 419 EmitBlock(EndBlock); 420} 421 422/// GenerateCXXAggrDestructorHelper - Generates a helper function which when 423/// invoked, calls the default destructor on array elements in reverse order of 424/// construction. 425llvm::Function * 426CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D, 427 const ArrayType *Array, 428 llvm::Value *This) { 429 FunctionArgList Args; 430 ImplicitParamDecl *Dst = 431 ImplicitParamDecl::Create(getContext(), 0, 432 SourceLocation(), 0, 433 getContext().getPointerType(getContext().VoidTy)); 434 Args.push_back(std::make_pair(Dst, Dst->getType())); 435 436 const CGFunctionInfo &FI = 437 CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args, 438 FunctionType::ExtInfo()); 439 const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false); 440 llvm::Function *Fn = 441 CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor"); 442 443 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, Args, SourceLocation()); 444 445 QualType BaseElementTy = getContext().getBaseElementType(Array); 446 const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo(); 447 llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr); 448 449 EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr); 450 451 FinishFunction(); 452 453 return Fn; 454} 455