CGCXX.cpp revision 8e51a1f5da6ef4a1a168d14116c6eed3a578a263
1//===--- CGDecl.cpp - Emit LLVM Code for 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 C++ code generation. 11// 12//===----------------------------------------------------------------------===// 13 14// We might split this into multiple files if it gets too unwieldy 15 16#include "CodeGenFunction.h" 17#include "CodeGenModule.h" 18#include "Mangle.h" 19#include "clang/AST/ASTContext.h" 20#include "clang/AST/RecordLayout.h" 21#include "clang/AST/Decl.h" 22#include "clang/AST/DeclCXX.h" 23#include "clang/AST/DeclObjC.h" 24#include "clang/AST/StmtCXX.h" 25#include "llvm/ADT/StringExtras.h" 26using namespace clang; 27using namespace CodeGen; 28 29 30 31void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) { 32 EmitGlobal(GlobalDecl(D, Ctor_Complete)); 33 EmitGlobal(GlobalDecl(D, Ctor_Base)); 34} 35 36void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D, 37 CXXCtorType Type) { 38 39 llvm::Function *Fn = GetAddrOfCXXConstructor(D, Type); 40 41 CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn); 42 43 SetFunctionDefinitionAttributes(D, Fn); 44 SetLLVMFunctionAttributesForDefinition(D, Fn); 45} 46 47llvm::Function * 48CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D, 49 CXXCtorType Type) { 50 const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>(); 51 const llvm::FunctionType *FTy = 52 getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), 53 FPT->isVariadic()); 54 55 const char *Name = getMangledCXXCtorName(D, Type); 56 return cast<llvm::Function>( 57 GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); 58} 59 60const char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D, 61 CXXCtorType Type) { 62 llvm::SmallString<256> Name; 63 getMangleContext().mangleCXXCtor(D, Type, Name); 64 65 Name += '\0'; 66 return UniqueMangledName(Name.begin(), Name.end()); 67} 68 69void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) { 70 if (D->isVirtual()) 71 EmitGlobal(GlobalDecl(D, Dtor_Deleting)); 72 EmitGlobal(GlobalDecl(D, Dtor_Complete)); 73 EmitGlobal(GlobalDecl(D, Dtor_Base)); 74} 75 76void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D, 77 CXXDtorType Type) { 78 llvm::Function *Fn = GetAddrOfCXXDestructor(D, Type); 79 80 CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn); 81 82 SetFunctionDefinitionAttributes(D, Fn); 83 SetLLVMFunctionAttributesForDefinition(D, Fn); 84} 85 86llvm::Function * 87CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D, 88 CXXDtorType Type) { 89 const llvm::FunctionType *FTy = 90 getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), false); 91 92 const char *Name = getMangledCXXDtorName(D, Type); 93 return cast<llvm::Function>( 94 GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); 95} 96 97const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D, 98 CXXDtorType Type) { 99 llvm::SmallString<256> Name; 100 getMangleContext().mangleCXXDtor(D, Type, Name); 101 102 Name += '\0'; 103 return UniqueMangledName(Name.begin(), Name.end()); 104} 105 106llvm::Constant * 107CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD, 108 bool Extern, 109 const ThunkAdjustment &ThisAdjustment) { 110 return GenerateCovariantThunk(Fn, GD, Extern, 111 CovariantThunkAdjustment(ThisAdjustment, 112 ThunkAdjustment())); 113} 114 115llvm::Value * 116CodeGenFunction::DynamicTypeAdjust(llvm::Value *V, 117 const ThunkAdjustment &Adjustment) { 118 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); 119 120 const llvm::Type *OrigTy = V->getType(); 121 if (Adjustment.NonVirtual) { 122 // Do the non-virtual adjustment 123 V = Builder.CreateBitCast(V, Int8PtrTy); 124 V = Builder.CreateConstInBoundsGEP1_64(V, Adjustment.NonVirtual); 125 V = Builder.CreateBitCast(V, OrigTy); 126 } 127 128 if (!Adjustment.Virtual) 129 return V; 130 131 assert(Adjustment.Virtual % (LLVMPointerWidth / 8) == 0 && 132 "vtable entry unaligned"); 133 134 // Do the virtual this adjustment 135 const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType()); 136 const llvm::Type *PtrDiffPtrTy = PtrDiffTy->getPointerTo(); 137 138 llvm::Value *ThisVal = Builder.CreateBitCast(V, Int8PtrTy); 139 V = Builder.CreateBitCast(V, PtrDiffPtrTy->getPointerTo()); 140 V = Builder.CreateLoad(V, "vtable"); 141 142 llvm::Value *VTablePtr = V; 143 uint64_t VirtualAdjustment = Adjustment.Virtual / (LLVMPointerWidth / 8); 144 V = Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment); 145 V = Builder.CreateLoad(V); 146 V = Builder.CreateGEP(ThisVal, V); 147 148 return Builder.CreateBitCast(V, OrigTy); 149} 150 151llvm::Constant * 152CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn, 153 GlobalDecl GD, bool Extern, 154 const CovariantThunkAdjustment &Adjustment) { 155 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 156 const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 157 QualType ResultType = FPT->getResultType(); 158 159 FunctionArgList Args; 160 ImplicitParamDecl *ThisDecl = 161 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, 162 MD->getThisType(getContext())); 163 Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType())); 164 for (FunctionDecl::param_const_iterator i = MD->param_begin(), 165 e = MD->param_end(); 166 i != e; ++i) { 167 ParmVarDecl *D = *i; 168 Args.push_back(std::make_pair(D, D->getType())); 169 } 170 IdentifierInfo *II 171 = &CGM.getContext().Idents.get("__thunk_named_foo_"); 172 FunctionDecl *FD = FunctionDecl::Create(getContext(), 173 getContext().getTranslationUnitDecl(), 174 SourceLocation(), II, ResultType, 0, 175 Extern 176 ? FunctionDecl::Extern 177 : FunctionDecl::Static, 178 false, true); 179 StartFunction(FD, ResultType, Fn, Args, SourceLocation()); 180 181 // generate body 182 const llvm::Type *Ty = 183 CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 184 FPT->isVariadic()); 185 llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty); 186 187 CallArgList CallArgs; 188 189 bool ShouldAdjustReturnPointer = true; 190 QualType ArgType = MD->getThisType(getContext()); 191 llvm::Value *Arg = Builder.CreateLoad(LocalDeclMap[ThisDecl], "this"); 192 if (!Adjustment.ThisAdjustment.isEmpty()) { 193 // Do the this adjustment. 194 const llvm::Type *OrigTy = Callee->getType(); 195 Arg = DynamicTypeAdjust(Arg, Adjustment.ThisAdjustment); 196 197 if (!Adjustment.ReturnAdjustment.isEmpty()) { 198 const CovariantThunkAdjustment &ReturnAdjustment = 199 CovariantThunkAdjustment(ThunkAdjustment(), 200 Adjustment.ReturnAdjustment); 201 202 Callee = CGM.BuildCovariantThunk(GD, Extern, ReturnAdjustment); 203 204 Callee = Builder.CreateBitCast(Callee, OrigTy); 205 ShouldAdjustReturnPointer = false; 206 } 207 } 208 209 CallArgs.push_back(std::make_pair(RValue::get(Arg), ArgType)); 210 211 for (FunctionDecl::param_const_iterator i = MD->param_begin(), 212 e = MD->param_end(); 213 i != e; ++i) { 214 ParmVarDecl *D = *i; 215 QualType ArgType = D->getType(); 216 217 // llvm::Value *Arg = CGF.GetAddrOfLocalVar(Dst); 218 Expr *Arg = new (getContext()) DeclRefExpr(D, ArgType.getNonReferenceType(), 219 SourceLocation()); 220 CallArgs.push_back(std::make_pair(EmitCallArg(Arg, ArgType), ArgType)); 221 } 222 223 RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs, 224 FPT->getCallConv(), 225 FPT->getNoReturnAttr()), 226 Callee, ReturnValueSlot(), CallArgs, MD); 227 if (ShouldAdjustReturnPointer && !Adjustment.ReturnAdjustment.isEmpty()) { 228 bool CanBeZero = !(ResultType->isReferenceType() 229 // FIXME: attr nonnull can't be zero either 230 /* || ResultType->hasAttr<NonNullAttr>() */ ); 231 // Do the return result adjustment. 232 if (CanBeZero) { 233 llvm::BasicBlock *NonZeroBlock = createBasicBlock(); 234 llvm::BasicBlock *ZeroBlock = createBasicBlock(); 235 llvm::BasicBlock *ContBlock = createBasicBlock(); 236 237 const llvm::Type *Ty = RV.getScalarVal()->getType(); 238 llvm::Value *Zero = llvm::Constant::getNullValue(Ty); 239 Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero), 240 NonZeroBlock, ZeroBlock); 241 EmitBlock(NonZeroBlock); 242 llvm::Value *NZ = 243 DynamicTypeAdjust(RV.getScalarVal(), Adjustment.ReturnAdjustment); 244 EmitBranch(ContBlock); 245 EmitBlock(ZeroBlock); 246 llvm::Value *Z = RV.getScalarVal(); 247 EmitBlock(ContBlock); 248 llvm::PHINode *RVOrZero = Builder.CreatePHI(Ty); 249 RVOrZero->reserveOperandSpace(2); 250 RVOrZero->addIncoming(NZ, NonZeroBlock); 251 RVOrZero->addIncoming(Z, ZeroBlock); 252 RV = RValue::get(RVOrZero); 253 } else 254 RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), 255 Adjustment.ReturnAdjustment)); 256 } 257 258 if (!ResultType->isVoidType()) 259 EmitReturnOfRValue(RV, ResultType); 260 261 FinishFunction(); 262 return Fn; 263} 264 265llvm::Constant * 266CodeGenModule::GetAddrOfThunk(GlobalDecl GD, 267 const ThunkAdjustment &ThisAdjustment) { 268 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 269 270 // Compute mangled name 271 llvm::SmallString<256> OutName; 272 if (const CXXDestructorDecl* DD = dyn_cast<CXXDestructorDecl>(MD)) 273 getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(), ThisAdjustment, 274 OutName); 275 else 276 getMangleContext().mangleThunk(MD, ThisAdjustment, OutName); 277 OutName += '\0'; 278 const char* Name = UniqueMangledName(OutName.begin(), OutName.end()); 279 280 // Get function for mangled name 281 const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD); 282 return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl()); 283} 284 285llvm::Constant * 286CodeGenModule::GetAddrOfCovariantThunk(GlobalDecl GD, 287 const CovariantThunkAdjustment &Adjustment) { 288 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 289 290 // Compute mangled name 291 llvm::SmallString<256> OutName; 292 getMangleContext().mangleCovariantThunk(MD, Adjustment, OutName); 293 OutName += '\0'; 294 const char* Name = UniqueMangledName(OutName.begin(), OutName.end()); 295 296 // Get function for mangled name 297 const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD); 298 return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl()); 299} 300 301void CodeGenModule::BuildThunksForVirtual(GlobalDecl GD) { 302 CGVtableInfo::AdjustmentVectorTy *AdjPtr = getVtableInfo().getAdjustments(GD); 303 if (!AdjPtr) 304 return; 305 CGVtableInfo::AdjustmentVectorTy &Adj = *AdjPtr; 306 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 307 for (unsigned i = 0; i < Adj.size(); i++) { 308 GlobalDecl OGD = Adj[i].first; 309 const CXXMethodDecl *OMD = cast<CXXMethodDecl>(OGD.getDecl()); 310 QualType nc_oret = OMD->getType()->getAs<FunctionType>()->getResultType(); 311 CanQualType oret = getContext().getCanonicalType(nc_oret); 312 QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType(); 313 CanQualType ret = getContext().getCanonicalType(nc_ret); 314 ThunkAdjustment ReturnAdjustment; 315 if (oret != ret) { 316 QualType qD = nc_ret->getPointeeType(); 317 QualType qB = nc_oret->getPointeeType(); 318 CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl()); 319 CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl()); 320 ReturnAdjustment = ComputeThunkAdjustment(D, B); 321 } 322 ThunkAdjustment ThisAdjustment = Adj[i].second; 323 bool Extern = !cast<CXXRecordDecl>(OMD->getDeclContext())->isInAnonymousNamespace(); 324 if (!ReturnAdjustment.isEmpty() || !ThisAdjustment.isEmpty()) { 325 CovariantThunkAdjustment CoAdj(ThisAdjustment, ReturnAdjustment); 326 llvm::Constant *FnConst; 327 if (!ReturnAdjustment.isEmpty()) 328 FnConst = GetAddrOfCovariantThunk(GD, CoAdj); 329 else 330 FnConst = GetAddrOfThunk(GD, ThisAdjustment); 331 if (!isa<llvm::Function>(FnConst)) { 332 llvm::Constant *SubExpr = 333 cast<llvm::ConstantExpr>(FnConst)->getOperand(0); 334 llvm::Function *OldFn = cast<llvm::Function>(SubExpr); 335 std::string Name = OldFn->getNameStr(); 336 GlobalDeclMap.erase(UniqueMangledName(Name.data(), 337 Name.data() + Name.size() + 1)); 338 llvm::Constant *NewFnConst; 339 if (!ReturnAdjustment.isEmpty()) 340 NewFnConst = GetAddrOfCovariantThunk(GD, CoAdj); 341 else 342 NewFnConst = GetAddrOfThunk(GD, ThisAdjustment); 343 llvm::Function *NewFn = cast<llvm::Function>(NewFnConst); 344 NewFn->takeName(OldFn); 345 llvm::Constant *NewPtrForOldDecl = 346 llvm::ConstantExpr::getBitCast(NewFn, OldFn->getType()); 347 OldFn->replaceAllUsesWith(NewPtrForOldDecl); 348 OldFn->eraseFromParent(); 349 FnConst = NewFn; 350 } 351 llvm::Function *Fn = cast<llvm::Function>(FnConst); 352 if (Fn->isDeclaration()) { 353 llvm::GlobalVariable::LinkageTypes linktype; 354 linktype = llvm::GlobalValue::WeakAnyLinkage; 355 if (!Extern) 356 linktype = llvm::GlobalValue::InternalLinkage; 357 Fn->setLinkage(linktype); 358 if (!Features.Exceptions && !Features.ObjCNonFragileABI) 359 Fn->addFnAttr(llvm::Attribute::NoUnwind); 360 Fn->setAlignment(2); 361 CodeGenFunction(*this).GenerateCovariantThunk(Fn, GD, Extern, CoAdj); 362 } 363 } 364 } 365} 366 367llvm::Constant * 368CodeGenModule::BuildThunk(GlobalDecl GD, bool Extern, 369 const ThunkAdjustment &ThisAdjustment) { 370 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 371 llvm::SmallString<256> OutName; 372 if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(MD)) { 373 getMangleContext().mangleCXXDtorThunk(D, GD.getDtorType(), ThisAdjustment, 374 OutName); 375 } else 376 getMangleContext().mangleThunk(MD, ThisAdjustment, OutName); 377 378 llvm::GlobalVariable::LinkageTypes linktype; 379 linktype = llvm::GlobalValue::WeakAnyLinkage; 380 if (!Extern) 381 linktype = llvm::GlobalValue::InternalLinkage; 382 llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); 383 const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 384 const llvm::FunctionType *FTy = 385 getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), 386 FPT->isVariadic()); 387 388 llvm::Function *Fn = llvm::Function::Create(FTy, linktype, OutName.str(), 389 &getModule()); 390 CodeGenFunction(*this).GenerateThunk(Fn, GD, Extern, ThisAdjustment); 391 llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty); 392 return m; 393} 394 395llvm::Constant * 396CodeGenModule::BuildCovariantThunk(const GlobalDecl &GD, bool Extern, 397 const CovariantThunkAdjustment &Adjustment) { 398 const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 399 llvm::SmallString<256> OutName; 400 getMangleContext().mangleCovariantThunk(MD, Adjustment, OutName); 401 llvm::GlobalVariable::LinkageTypes linktype; 402 linktype = llvm::GlobalValue::WeakAnyLinkage; 403 if (!Extern) 404 linktype = llvm::GlobalValue::InternalLinkage; 405 llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); 406 const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 407 const llvm::FunctionType *FTy = 408 getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), 409 FPT->isVariadic()); 410 411 llvm::Function *Fn = llvm::Function::Create(FTy, linktype, OutName.str(), 412 &getModule()); 413 CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, Adjustment); 414 llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty); 415 return m; 416} 417 418static llvm::Value *BuildVirtualCall(CodeGenFunction &CGF, uint64_t VtableIndex, 419 llvm::Value *This, const llvm::Type *Ty) { 420 Ty = Ty->getPointerTo()->getPointerTo()->getPointerTo(); 421 422 llvm::Value *Vtable = CGF.Builder.CreateBitCast(This, Ty); 423 Vtable = CGF.Builder.CreateLoad(Vtable); 424 425 llvm::Value *VFuncPtr = 426 CGF.Builder.CreateConstInBoundsGEP1_64(Vtable, VtableIndex, "vfn"); 427 return CGF.Builder.CreateLoad(VFuncPtr); 428} 429 430llvm::Value * 431CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This, 432 const llvm::Type *Ty) { 433 MD = MD->getCanonicalDecl(); 434 uint64_t VtableIndex = CGM.getVtableInfo().getMethodVtableIndex(MD); 435 436 return ::BuildVirtualCall(*this, VtableIndex, This, Ty); 437} 438 439llvm::Value * 440CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type, 441 llvm::Value *&This, const llvm::Type *Ty) { 442 DD = cast<CXXDestructorDecl>(DD->getCanonicalDecl()); 443 uint64_t VtableIndex = 444 CGM.getVtableInfo().getMethodVtableIndex(GlobalDecl(DD, Type)); 445 446 return ::BuildVirtualCall(*this, VtableIndex, This, Ty); 447} 448