CGDeclCXX.cpp revision 207619
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/CodeGen/CodeGenOptions.h" 16using namespace clang; 17using namespace CodeGen; 18 19static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D, 20 llvm::Constant *DeclPtr) { 21 assert(D.hasGlobalStorage() && "VarDecl must have global storage!"); 22 assert(!D.getType()->isReferenceType() && 23 "Should not call EmitDeclInit on a reference!"); 24 25 CodeGenModule &CGM = CGF.CGM; 26 ASTContext &Context = CGF.getContext(); 27 28 const Expr *Init = D.getInit(); 29 QualType T = D.getType(); 30 bool isVolatile = Context.getCanonicalType(T).isVolatileQualified(); 31 32 if (!CGF.hasAggregateLLVMType(T)) { 33 llvm::Value *V = CGF.EmitScalarExpr(Init); 34 CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, T); 35 } else if (T->isAnyComplexType()) { 36 CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile); 37 } else { 38 CGF.EmitAggExpr(Init, DeclPtr, isVolatile); 39 40 // Avoid generating destructor(s) for initialized objects. 41 if (!isa<CXXConstructExpr>(Init)) 42 return; 43 44 const ConstantArrayType *Array = Context.getAsConstantArrayType(T); 45 if (Array) 46 T = Context.getBaseElementType(Array); 47 48 const RecordType *RT = T->getAs<RecordType>(); 49 if (!RT) 50 return; 51 52 CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); 53 if (RD->hasTrivialDestructor()) 54 return; 55 56 CXXDestructorDecl *Dtor = RD->getDestructor(Context); 57 58 llvm::Constant *DtorFn; 59 if (Array) { 60 DtorFn = 61 CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, 62 Array, 63 DeclPtr); 64 const llvm::Type *Int8PtrTy = 65 llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); 66 DeclPtr = llvm::Constant::getNullValue(Int8PtrTy); 67 } else 68 DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete); 69 70 CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr); 71 } 72} 73 74void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, 75 llvm::Constant *DeclPtr) { 76 77 const Expr *Init = D.getInit(); 78 QualType T = D.getType(); 79 80 if (!T->isReferenceType()) { 81 EmitDeclInit(*this, D, DeclPtr); 82 return; 83 } 84 if (Init->isLvalue(getContext()) == Expr::LV_Valid) { 85 RValue RV = EmitReferenceBindingToExpr(Init, /*IsInitializer=*/true); 86 EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, T); 87 return; 88 } 89 ErrorUnsupported(Init, 90 "global variable that binds reference to a non-lvalue"); 91} 92 93void 94CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, 95 llvm::Constant *DeclPtr) { 96 // Generate a global destructor entry if not using __cxa_atexit. 97 if (!CGM.getCodeGenOpts().CXAAtExit) { 98 CGM.AddCXXDtorEntry(DtorFn, DeclPtr); 99 return; 100 } 101 102 const llvm::Type *Int8PtrTy = 103 llvm::Type::getInt8Ty(VMContext)->getPointerTo(); 104 105 std::vector<const llvm::Type *> Params; 106 Params.push_back(Int8PtrTy); 107 108 // Get the destructor function type 109 const llvm::Type *DtorFnTy = 110 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); 111 DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy); 112 113 Params.clear(); 114 Params.push_back(DtorFnTy); 115 Params.push_back(Int8PtrTy); 116 Params.push_back(Int8PtrTy); 117 118 // Get the __cxa_atexit function type 119 // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d ); 120 const llvm::FunctionType *AtExitFnTy = 121 llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false); 122 123 llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy, 124 "__cxa_atexit"); 125 126 llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy, 127 "__dso_handle"); 128 llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy), 129 llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy), 130 llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) }; 131 Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args)); 132} 133 134void 135CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) { 136 const llvm::FunctionType *FTy 137 = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 138 false); 139 140 // Create a variable initialization function. 141 llvm::Function *Fn = 142 llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, 143 "__cxx_global_var_init", &TheModule); 144 145 CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D); 146 147 CXXGlobalInits.push_back(Fn); 148} 149 150void 151CodeGenModule::EmitCXXGlobalInitFunc() { 152 if (CXXGlobalInits.empty()) 153 return; 154 155 const llvm::FunctionType *FTy 156 = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 157 false); 158 159 // Create our global initialization function. 160 llvm::Function *Fn = 161 llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, 162 "_GLOBAL__I_a", &TheModule); 163 164 CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, 165 &CXXGlobalInits[0], 166 CXXGlobalInits.size()); 167 AddGlobalCtor(Fn); 168} 169 170void CodeGenModule::AddCXXDtorEntry(llvm::Constant *DtorFn, 171 llvm::Constant *Object) { 172 CXXGlobalDtors.push_back(std::make_pair(DtorFn, Object)); 173} 174 175void CodeGenModule::EmitCXXGlobalDtorFunc() { 176 if (CXXGlobalDtors.empty()) 177 return; 178 179 const llvm::FunctionType *FTy 180 = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 181 false); 182 183 // Create our global destructor function. 184 llvm::Function *Fn = 185 llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, 186 "_GLOBAL__D_a", &TheModule); 187 188 CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors); 189 AddGlobalDtor(Fn); 190} 191 192void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, 193 const VarDecl *D) { 194 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 195 SourceLocation()); 196 197 llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D); 198 EmitCXXGlobalVarDeclInit(*D, DeclPtr); 199 200 FinishFunction(); 201} 202 203void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, 204 llvm::Constant **Decls, 205 unsigned NumDecls) { 206 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 207 SourceLocation()); 208 209 for (unsigned i = 0; i != NumDecls; ++i) 210 Builder.CreateCall(Decls[i]); 211 212 FinishFunction(); 213} 214 215void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn, 216 const std::vector<std::pair<llvm::Constant*, llvm::Constant*> > 217 &DtorsAndObjects) { 218 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 219 SourceLocation()); 220 221 // Emit the dtors, in reverse order from construction. 222 for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) { 223 llvm::Constant *Callee = DtorsAndObjects[e - i - 1].first; 224 llvm::CallInst *CI = Builder.CreateCall(Callee, 225 DtorsAndObjects[e - i - 1].second); 226 // Make sure the call and the callee agree on calling convention. 227 if (llvm::Function *F = dyn_cast<llvm::Function>(Callee)) 228 CI->setCallingConv(F->getCallingConv()); 229 } 230 231 FinishFunction(); 232} 233 234static llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) { 235 // int __cxa_guard_acquire(__int64_t *guard_object); 236 237 const llvm::Type *Int64PtrTy = 238 llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); 239 240 std::vector<const llvm::Type*> Args(1, Int64PtrTy); 241 242 const llvm::FunctionType *FTy = 243 llvm::FunctionType::get(CGF.ConvertType(CGF.getContext().IntTy), 244 Args, /*isVarArg=*/false); 245 246 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire"); 247} 248 249static llvm::Constant *getGuardReleaseFn(CodeGenFunction &CGF) { 250 // void __cxa_guard_release(__int64_t *guard_object); 251 252 const llvm::Type *Int64PtrTy = 253 llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); 254 255 std::vector<const llvm::Type*> Args(1, Int64PtrTy); 256 257 const llvm::FunctionType *FTy = 258 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 259 Args, /*isVarArg=*/false); 260 261 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release"); 262} 263 264static llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) { 265 // void __cxa_guard_abort(__int64_t *guard_object); 266 267 const llvm::Type *Int64PtrTy = 268 llvm::Type::getInt64PtrTy(CGF.getLLVMContext()); 269 270 std::vector<const llvm::Type*> Args(1, Int64PtrTy); 271 272 const llvm::FunctionType *FTy = 273 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 274 Args, /*isVarArg=*/false); 275 276 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort"); 277} 278 279void 280CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D, 281 llvm::GlobalVariable *GV) { 282 bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics; 283 284 llvm::SmallString<256> GuardVName; 285 CGM.getMangleContext().mangleGuardVariable(&D, GuardVName); 286 287 // Create the guard variable. 288 const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(VMContext); 289 llvm::GlobalValue *GuardVariable = 290 new llvm::GlobalVariable(CGM.getModule(), Int64Ty, 291 false, GV->getLinkage(), 292 llvm::Constant::getNullValue(Int64Ty), 293 GuardVName.str()); 294 295 // Load the first byte of the guard variable. 296 const llvm::Type *PtrTy 297 = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); 298 llvm::Value *V = 299 Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp"); 300 301 llvm::BasicBlock *InitCheckBlock = createBasicBlock("init.check"); 302 llvm::BasicBlock *EndBlock = createBasicBlock("init.end"); 303 304 // Check if the first byte of the guard variable is zero. 305 Builder.CreateCondBr(Builder.CreateIsNull(V, "tobool"), 306 InitCheckBlock, EndBlock); 307 308 EmitBlock(InitCheckBlock); 309 310 if (ThreadsafeStatics) { 311 // Call __cxa_guard_acquire. 312 V = Builder.CreateCall(getGuardAcquireFn(*this), GuardVariable); 313 314 llvm::BasicBlock *InitBlock = createBasicBlock("init"); 315 316 Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), 317 InitBlock, EndBlock); 318 319 EmitBlock(InitBlock); 320 321 if (Exceptions) { 322 EHCleanupBlock Cleanup(*this); 323 324 // Call __cxa_guard_abort. 325 Builder.CreateCall(getGuardAbortFn(*this), GuardVariable); 326 } 327 } 328 329 if (D.getType()->isReferenceType()) { 330 QualType T = D.getType(); 331 // We don't want to pass true for IsInitializer here, because a static 332 // reference to a temporary does not extend its lifetime. 333 RValue RV = EmitReferenceBindingToExpr(D.getInit(), 334 /*IsInitializer=*/false); 335 EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, T); 336 337 } else 338 EmitDeclInit(*this, D, GV); 339 340 if (ThreadsafeStatics) { 341 // Call __cxa_guard_release. 342 Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable); 343 } else { 344 llvm::Value *One = 345 llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1); 346 Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy)); 347 } 348 349 EmitBlock(EndBlock); 350} 351