1207619Srdivacky//===--- CGVTables.cpp - Emit LLVM Code for C++ vtables -------------------===// 2207619Srdivacky// 3207619Srdivacky// The LLVM Compiler Infrastructure 4207619Srdivacky// 5207619Srdivacky// This file is distributed under the University of Illinois Open Source 6207619Srdivacky// License. See LICENSE.TXT for details. 7207619Srdivacky// 8207619Srdivacky//===----------------------------------------------------------------------===// 9207619Srdivacky// 10207619Srdivacky// This contains code dealing with C++ code generation of virtual tables. 11207619Srdivacky// 12207619Srdivacky//===----------------------------------------------------------------------===// 13207619Srdivacky 14207619Srdivacky#include "CodeGenFunction.h" 15212904Sdim#include "CGCXXABI.h" 16249423Sdim#include "CodeGenModule.h" 17207619Srdivacky#include "clang/AST/CXXInheritance.h" 18207619Srdivacky#include "clang/AST/RecordLayout.h" 19212904Sdim#include "clang/Frontend/CodeGenOptions.h" 20207619Srdivacky#include "llvm/ADT/DenseSet.h" 21207619Srdivacky#include "llvm/ADT/SetVector.h" 22207619Srdivacky#include "llvm/Support/Compiler.h" 23207619Srdivacky#include "llvm/Support/Format.h" 24223017Sdim#include "llvm/Transforms/Utils/Cloning.h" 25207619Srdivacky#include <algorithm> 26207619Srdivacky#include <cstdio> 27207619Srdivacky 28207619Srdivackyusing namespace clang; 29207619Srdivackyusing namespace CodeGen; 30207619Srdivacky 31226633SdimCodeGenVTables::CodeGenVTables(CodeGenModule &CGM) 32226633Sdim : CGM(CGM), VTContext(CGM.getContext()) { } 33207619Srdivacky 34207619Srdivackyllvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD, 35207619Srdivacky const ThunkInfo &Thunk) { 36207619Srdivacky const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 37207619Srdivacky 38207619Srdivacky // Compute the mangled name. 39234353Sdim SmallString<256> Name; 40218893Sdim llvm::raw_svector_ostream Out(Name); 41207619Srdivacky if (const CXXDestructorDecl* DD = dyn_cast<CXXDestructorDecl>(MD)) 42212904Sdim getCXXABI().getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(), 43218893Sdim Thunk.This, Out); 44207619Srdivacky else 45218893Sdim getCXXABI().getMangleContext().mangleThunk(MD, Thunk, Out); 46218893Sdim Out.flush(); 47218893Sdim 48226633Sdim llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(GD); 49218893Sdim return GetOrCreateLLVMFunction(Name, Ty, GD, /*ForVTable=*/true); 50207619Srdivacky} 51207619Srdivacky 52207619Srdivackystatic llvm::Value *PerformTypeAdjustment(CodeGenFunction &CGF, 53207619Srdivacky llvm::Value *Ptr, 54207619Srdivacky int64_t NonVirtualAdjustment, 55243830Sdim int64_t VirtualAdjustment, 56243830Sdim bool IsReturnAdjustment) { 57207619Srdivacky if (!NonVirtualAdjustment && !VirtualAdjustment) 58207619Srdivacky return Ptr; 59207619Srdivacky 60234353Sdim llvm::Type *Int8PtrTy = CGF.Int8PtrTy; 61207619Srdivacky llvm::Value *V = CGF.Builder.CreateBitCast(Ptr, Int8PtrTy); 62207619Srdivacky 63243830Sdim if (NonVirtualAdjustment && !IsReturnAdjustment) { 64243830Sdim // Perform the non-virtual adjustment for a base-to-derived cast. 65207619Srdivacky V = CGF.Builder.CreateConstInBoundsGEP1_64(V, NonVirtualAdjustment); 66207619Srdivacky } 67207619Srdivacky 68207619Srdivacky if (VirtualAdjustment) { 69226633Sdim llvm::Type *PtrDiffTy = 70207619Srdivacky CGF.ConvertType(CGF.getContext().getPointerDiffType()); 71207619Srdivacky 72243830Sdim // Perform the virtual adjustment. 73207619Srdivacky llvm::Value *VTablePtrPtr = 74207619Srdivacky CGF.Builder.CreateBitCast(V, Int8PtrTy->getPointerTo()); 75207619Srdivacky 76207619Srdivacky llvm::Value *VTablePtr = CGF.Builder.CreateLoad(VTablePtrPtr); 77207619Srdivacky 78207619Srdivacky llvm::Value *OffsetPtr = 79207619Srdivacky CGF.Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment); 80207619Srdivacky 81207619Srdivacky OffsetPtr = CGF.Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo()); 82207619Srdivacky 83207619Srdivacky // Load the adjustment offset from the vtable. 84207619Srdivacky llvm::Value *Offset = CGF.Builder.CreateLoad(OffsetPtr); 85207619Srdivacky 86207619Srdivacky // Adjust our pointer. 87207619Srdivacky V = CGF.Builder.CreateInBoundsGEP(V, Offset); 88207619Srdivacky } 89207619Srdivacky 90243830Sdim if (NonVirtualAdjustment && IsReturnAdjustment) { 91243830Sdim // Perform the non-virtual adjustment for a derived-to-base cast. 92243830Sdim V = CGF.Builder.CreateConstInBoundsGEP1_64(V, NonVirtualAdjustment); 93243830Sdim } 94243830Sdim 95207619Srdivacky // Cast back to the original type. 96207619Srdivacky return CGF.Builder.CreateBitCast(V, Ptr->getType()); 97207619Srdivacky} 98207619Srdivacky 99212904Sdimstatic void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD, 100212904Sdim const ThunkInfo &Thunk, llvm::Function *Fn) { 101212904Sdim CGM.setGlobalVisibility(Fn, MD); 102212904Sdim 103212904Sdim if (!CGM.getCodeGenOpts().HiddenWeakVTables) 104212904Sdim return; 105212904Sdim 106212904Sdim // If the thunk has weak/linkonce linkage, but the function must be 107212904Sdim // emitted in every translation unit that references it, then we can 108212904Sdim // emit its thunks with hidden visibility, since its thunks must be 109212904Sdim // emitted when the function is. 110212904Sdim 111212904Sdim // This follows CodeGenModule::setTypeVisibility; see the comments 112212904Sdim // there for explanation. 113212904Sdim 114212904Sdim if ((Fn->getLinkage() != llvm::GlobalVariable::LinkOnceODRLinkage && 115212904Sdim Fn->getLinkage() != llvm::GlobalVariable::WeakODRLinkage) || 116212904Sdim Fn->getVisibility() != llvm::GlobalVariable::DefaultVisibility) 117212904Sdim return; 118212904Sdim 119249423Sdim if (MD->getExplicitVisibility(ValueDecl::VisibilityForValue)) 120212904Sdim return; 121212904Sdim 122212904Sdim switch (MD->getTemplateSpecializationKind()) { 123212904Sdim case TSK_ExplicitInstantiationDefinition: 124212904Sdim case TSK_ExplicitInstantiationDeclaration: 125212904Sdim return; 126212904Sdim 127212904Sdim case TSK_Undeclared: 128212904Sdim break; 129212904Sdim 130212904Sdim case TSK_ExplicitSpecialization: 131212904Sdim case TSK_ImplicitInstantiation: 132243830Sdim return; 133212904Sdim break; 134212904Sdim } 135212904Sdim 136212904Sdim // If there's an explicit definition, and that definition is 137212904Sdim // out-of-line, then we can't assume that all users will have a 138212904Sdim // definition to emit. 139212904Sdim const FunctionDecl *Def = 0; 140212904Sdim if (MD->hasBody(Def) && Def->isOutOfLine()) 141212904Sdim return; 142212904Sdim 143212904Sdim Fn->setVisibility(llvm::GlobalValue::HiddenVisibility); 144212904Sdim} 145212904Sdim 146221345Sdim#ifndef NDEBUG 147221345Sdimstatic bool similar(const ABIArgInfo &infoL, CanQualType typeL, 148221345Sdim const ABIArgInfo &infoR, CanQualType typeR) { 149221345Sdim return (infoL.getKind() == infoR.getKind() && 150221345Sdim (typeL == typeR || 151221345Sdim (isa<PointerType>(typeL) && isa<PointerType>(typeR)) || 152221345Sdim (isa<ReferenceType>(typeL) && isa<ReferenceType>(typeR)))); 153221345Sdim} 154221345Sdim#endif 155221345Sdim 156223017Sdimstatic RValue PerformReturnAdjustment(CodeGenFunction &CGF, 157223017Sdim QualType ResultType, RValue RV, 158223017Sdim const ThunkInfo &Thunk) { 159223017Sdim // Emit the return adjustment. 160223017Sdim bool NullCheckValue = !ResultType->isReferenceType(); 161223017Sdim 162223017Sdim llvm::BasicBlock *AdjustNull = 0; 163223017Sdim llvm::BasicBlock *AdjustNotNull = 0; 164223017Sdim llvm::BasicBlock *AdjustEnd = 0; 165223017Sdim 166223017Sdim llvm::Value *ReturnValue = RV.getScalarVal(); 167223017Sdim 168223017Sdim if (NullCheckValue) { 169223017Sdim AdjustNull = CGF.createBasicBlock("adjust.null"); 170223017Sdim AdjustNotNull = CGF.createBasicBlock("adjust.notnull"); 171223017Sdim AdjustEnd = CGF.createBasicBlock("adjust.end"); 172223017Sdim 173223017Sdim llvm::Value *IsNull = CGF.Builder.CreateIsNull(ReturnValue); 174223017Sdim CGF.Builder.CreateCondBr(IsNull, AdjustNull, AdjustNotNull); 175223017Sdim CGF.EmitBlock(AdjustNotNull); 176223017Sdim } 177223017Sdim 178223017Sdim ReturnValue = PerformTypeAdjustment(CGF, ReturnValue, 179223017Sdim Thunk.Return.NonVirtual, 180243830Sdim Thunk.Return.VBaseOffsetOffset, 181243830Sdim /*IsReturnAdjustment*/true); 182223017Sdim 183223017Sdim if (NullCheckValue) { 184223017Sdim CGF.Builder.CreateBr(AdjustEnd); 185223017Sdim CGF.EmitBlock(AdjustNull); 186223017Sdim CGF.Builder.CreateBr(AdjustEnd); 187223017Sdim CGF.EmitBlock(AdjustEnd); 188223017Sdim 189223017Sdim llvm::PHINode *PHI = CGF.Builder.CreatePHI(ReturnValue->getType(), 2); 190223017Sdim PHI->addIncoming(ReturnValue, AdjustNotNull); 191223017Sdim PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()), 192223017Sdim AdjustNull); 193223017Sdim ReturnValue = PHI; 194223017Sdim } 195223017Sdim 196223017Sdim return RValue::get(ReturnValue); 197223017Sdim} 198223017Sdim 199223017Sdim// This function does roughly the same thing as GenerateThunk, but in a 200223017Sdim// very different way, so that va_start and va_end work correctly. 201223017Sdim// FIXME: This function assumes "this" is the first non-sret LLVM argument of 202223017Sdim// a function, and that there is an alloca built in the entry block 203223017Sdim// for all accesses to "this". 204223017Sdim// FIXME: This function assumes there is only one "ret" statement per function. 205223017Sdim// FIXME: Cloning isn't correct in the presence of indirect goto! 206223017Sdim// FIXME: This implementation of thunks bloats codesize by duplicating the 207223017Sdim// function definition. There are alternatives: 208223017Sdim// 1. Add some sort of stub support to LLVM for cases where we can 209223017Sdim// do a this adjustment, then a sibcall. 210223017Sdim// 2. We could transform the definition to take a va_list instead of an 211223017Sdim// actual variable argument list, then have the thunks (including a 212223017Sdim// no-op thunk for the regular definition) call va_start/va_end. 213223017Sdim// There's a bit of per-call overhead for this solution, but it's 214223017Sdim// better for codesize if the definition is long. 215223017Sdimvoid CodeGenFunction::GenerateVarArgsThunk( 216223017Sdim llvm::Function *Fn, 217223017Sdim const CGFunctionInfo &FnInfo, 218223017Sdim GlobalDecl GD, const ThunkInfo &Thunk) { 219223017Sdim const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 220223017Sdim const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 221223017Sdim QualType ResultType = FPT->getResultType(); 222223017Sdim 223223017Sdim // Get the original function 224234353Sdim assert(FnInfo.isVariadic()); 225234353Sdim llvm::Type *Ty = CGM.getTypes().GetFunctionType(FnInfo); 226223017Sdim llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true); 227223017Sdim llvm::Function *BaseFn = cast<llvm::Function>(Callee); 228223017Sdim 229223017Sdim // Clone to thunk. 230243830Sdim llvm::ValueToValueMapTy VMap; 231243830Sdim llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap, 232243830Sdim /*ModuleLevelChanges=*/false); 233223017Sdim CGM.getModule().getFunctionList().push_back(NewFn); 234223017Sdim Fn->replaceAllUsesWith(NewFn); 235223017Sdim NewFn->takeName(Fn); 236223017Sdim Fn->eraseFromParent(); 237223017Sdim Fn = NewFn; 238223017Sdim 239223017Sdim // "Initialize" CGF (minimally). 240223017Sdim CurFn = Fn; 241223017Sdim 242223017Sdim // Get the "this" value 243223017Sdim llvm::Function::arg_iterator AI = Fn->arg_begin(); 244223017Sdim if (CGM.ReturnTypeUsesSRet(FnInfo)) 245223017Sdim ++AI; 246223017Sdim 247223017Sdim // Find the first store of "this", which will be to the alloca associated 248223017Sdim // with "this". 249223017Sdim llvm::Value *ThisPtr = &*AI; 250223017Sdim llvm::BasicBlock *EntryBB = Fn->begin(); 251223017Sdim llvm::Instruction *ThisStore = 0; 252223017Sdim for (llvm::BasicBlock::iterator I = EntryBB->begin(), E = EntryBB->end(); 253223017Sdim I != E; I++) { 254223017Sdim if (isa<llvm::StoreInst>(I) && I->getOperand(0) == ThisPtr) { 255223017Sdim ThisStore = cast<llvm::StoreInst>(I); 256223017Sdim break; 257223017Sdim } 258223017Sdim } 259223017Sdim assert(ThisStore && "Store of this should be in entry block?"); 260223017Sdim // Adjust "this", if necessary. 261223017Sdim Builder.SetInsertPoint(ThisStore); 262223017Sdim llvm::Value *AdjustedThisPtr = 263223017Sdim PerformTypeAdjustment(*this, ThisPtr, 264223017Sdim Thunk.This.NonVirtual, 265243830Sdim Thunk.This.VCallOffsetOffset, 266243830Sdim /*IsReturnAdjustment*/false); 267223017Sdim ThisStore->setOperand(0, AdjustedThisPtr); 268223017Sdim 269223017Sdim if (!Thunk.Return.isEmpty()) { 270223017Sdim // Fix up the returned value, if necessary. 271223017Sdim for (llvm::Function::iterator I = Fn->begin(), E = Fn->end(); I != E; I++) { 272223017Sdim llvm::Instruction *T = I->getTerminator(); 273223017Sdim if (isa<llvm::ReturnInst>(T)) { 274223017Sdim RValue RV = RValue::get(T->getOperand(0)); 275223017Sdim T->eraseFromParent(); 276223017Sdim Builder.SetInsertPoint(&*I); 277223017Sdim RV = PerformReturnAdjustment(*this, ResultType, RV, Thunk); 278223017Sdim Builder.CreateRet(RV.getScalarVal()); 279223017Sdim break; 280223017Sdim } 281223017Sdim } 282223017Sdim } 283223017Sdim} 284223017Sdim 285221345Sdimvoid CodeGenFunction::GenerateThunk(llvm::Function *Fn, 286221345Sdim const CGFunctionInfo &FnInfo, 287221345Sdim GlobalDecl GD, const ThunkInfo &Thunk) { 288207619Srdivacky const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 289207619Srdivacky const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 290207619Srdivacky QualType ResultType = FPT->getResultType(); 291207619Srdivacky QualType ThisType = MD->getThisType(getContext()); 292207619Srdivacky 293207619Srdivacky FunctionArgList FunctionArgs; 294207619Srdivacky 295207619Srdivacky // FIXME: It would be nice if more of this code could be shared with 296207619Srdivacky // CodeGenFunction::GenerateCode. 297207619Srdivacky 298207619Srdivacky // Create the implicit 'this' parameter declaration. 299212904Sdim CurGD = GD; 300212904Sdim CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResultType, FunctionArgs); 301207619Srdivacky 302207619Srdivacky // Add the rest of the parameters. 303207619Srdivacky for (FunctionDecl::param_const_iterator I = MD->param_begin(), 304207619Srdivacky E = MD->param_end(); I != E; ++I) { 305207619Srdivacky ParmVarDecl *Param = *I; 306207619Srdivacky 307221345Sdim FunctionArgs.push_back(Param); 308207619Srdivacky } 309243830Sdim 310243830Sdim // Initialize debug info if needed. 311243830Sdim maybeInitializeDebugInfo(); 312243830Sdim 313221345Sdim StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs, 314221345Sdim SourceLocation()); 315207619Srdivacky 316212904Sdim CGM.getCXXABI().EmitInstanceFunctionProlog(*this); 317234353Sdim CXXThisValue = CXXABIThisValue; 318212904Sdim 319207619Srdivacky // Adjust the 'this' pointer if necessary. 320207619Srdivacky llvm::Value *AdjustedThisPtr = 321207619Srdivacky PerformTypeAdjustment(*this, LoadCXXThis(), 322207619Srdivacky Thunk.This.NonVirtual, 323243830Sdim Thunk.This.VCallOffsetOffset, 324243830Sdim /*IsReturnAdjustment*/false); 325207619Srdivacky 326207619Srdivacky CallArgList CallArgs; 327207619Srdivacky 328207619Srdivacky // Add our adjusted 'this' pointer. 329221345Sdim CallArgs.add(RValue::get(AdjustedThisPtr), ThisType); 330207619Srdivacky 331207619Srdivacky // Add the rest of the parameters. 332207619Srdivacky for (FunctionDecl::param_const_iterator I = MD->param_begin(), 333207619Srdivacky E = MD->param_end(); I != E; ++I) { 334221345Sdim ParmVarDecl *param = *I; 335221345Sdim EmitDelegateCallArg(CallArgs, param); 336207619Srdivacky } 337207619Srdivacky 338207619Srdivacky // Get our callee. 339226633Sdim llvm::Type *Ty = 340234353Sdim CGM.getTypes().GetFunctionType(CGM.getTypes().arrangeGlobalDeclaration(GD)); 341218893Sdim llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true); 342207619Srdivacky 343221345Sdim#ifndef NDEBUG 344239462Sdim const CGFunctionInfo &CallFnInfo = 345239462Sdim CGM.getTypes().arrangeCXXMethodCall(CallArgs, FPT, 346234353Sdim RequiredArgs::forPrototypePlus(FPT, 1)); 347221345Sdim assert(CallFnInfo.getRegParm() == FnInfo.getRegParm() && 348221345Sdim CallFnInfo.isNoReturn() == FnInfo.isNoReturn() && 349221345Sdim CallFnInfo.getCallingConvention() == FnInfo.getCallingConvention()); 350239462Sdim assert(isa<CXXDestructorDecl>(MD) || // ignore dtor return types 351239462Sdim similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(), 352221345Sdim FnInfo.getReturnInfo(), FnInfo.getReturnType())); 353221345Sdim assert(CallFnInfo.arg_size() == FnInfo.arg_size()); 354221345Sdim for (unsigned i = 0, e = FnInfo.arg_size(); i != e; ++i) 355221345Sdim assert(similar(CallFnInfo.arg_begin()[i].info, 356221345Sdim CallFnInfo.arg_begin()[i].type, 357221345Sdim FnInfo.arg_begin()[i].info, FnInfo.arg_begin()[i].type)); 358221345Sdim#endif 359207619Srdivacky 360208600Srdivacky // Determine whether we have a return value slot to use. 361208600Srdivacky ReturnValueSlot Slot; 362208600Srdivacky if (!ResultType->isVoidType() && 363208600Srdivacky FnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect && 364249423Sdim !hasScalarEvaluationKind(CurFnInfo->getReturnType())) 365208600Srdivacky Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified()); 366208600Srdivacky 367207619Srdivacky // Now emit our call. 368208600Srdivacky RValue RV = EmitCall(FnInfo, Callee, Slot, CallArgs, MD); 369207619Srdivacky 370223017Sdim if (!Thunk.Return.isEmpty()) 371223017Sdim RV = PerformReturnAdjustment(*this, ResultType, RV, Thunk); 372207619Srdivacky 373208600Srdivacky if (!ResultType->isVoidType() && Slot.isNull()) 374218893Sdim CGM.getCXXABI().EmitReturnFromThunk(*this, RV, ResultType); 375207619Srdivacky 376239462Sdim // Disable the final ARC autorelease. 377239462Sdim AutoreleaseResult = false; 378239462Sdim 379207619Srdivacky FinishFunction(); 380207619Srdivacky 381207619Srdivacky // Set the right linkage. 382208600Srdivacky CGM.setFunctionLinkage(MD, Fn); 383207619Srdivacky 384207619Srdivacky // Set the right visibility. 385212904Sdim setThunkVisibility(CGM, MD, Thunk, Fn); 386207619Srdivacky} 387207619Srdivacky 388218893Sdimvoid CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk, 389218893Sdim bool UseAvailableExternallyLinkage) 390207619Srdivacky{ 391234353Sdim const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeGlobalDeclaration(GD); 392221345Sdim 393221345Sdim // FIXME: re-use FnInfo in this computation. 394207619Srdivacky llvm::Constant *Entry = CGM.GetAddrOfThunk(GD, Thunk); 395207619Srdivacky 396207619Srdivacky // Strip off a bitcast if we got one back. 397207619Srdivacky if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) { 398207619Srdivacky assert(CE->getOpcode() == llvm::Instruction::BitCast); 399207619Srdivacky Entry = CE->getOperand(0); 400207619Srdivacky } 401207619Srdivacky 402207619Srdivacky // There's already a declaration with the same name, check if it has the same 403207619Srdivacky // type or if we need to replace it. 404207619Srdivacky if (cast<llvm::GlobalValue>(Entry)->getType()->getElementType() != 405212904Sdim CGM.getTypes().GetFunctionTypeForVTable(GD)) { 406207619Srdivacky llvm::GlobalValue *OldThunkFn = cast<llvm::GlobalValue>(Entry); 407207619Srdivacky 408207619Srdivacky // If the types mismatch then we have to rewrite the definition. 409207619Srdivacky assert(OldThunkFn->isDeclaration() && 410207619Srdivacky "Shouldn't replace non-declaration"); 411207619Srdivacky 412207619Srdivacky // Remove the name from the old thunk function and get a new thunk. 413226633Sdim OldThunkFn->setName(StringRef()); 414207619Srdivacky Entry = CGM.GetAddrOfThunk(GD, Thunk); 415207619Srdivacky 416207619Srdivacky // If needed, replace the old thunk with a bitcast. 417207619Srdivacky if (!OldThunkFn->use_empty()) { 418207619Srdivacky llvm::Constant *NewPtrForOldDecl = 419207619Srdivacky llvm::ConstantExpr::getBitCast(Entry, OldThunkFn->getType()); 420207619Srdivacky OldThunkFn->replaceAllUsesWith(NewPtrForOldDecl); 421207619Srdivacky } 422207619Srdivacky 423207619Srdivacky // Remove the old thunk. 424207619Srdivacky OldThunkFn->eraseFromParent(); 425207619Srdivacky } 426207619Srdivacky 427218893Sdim llvm::Function *ThunkFn = cast<llvm::Function>(Entry); 428218893Sdim 429218893Sdim if (!ThunkFn->isDeclaration()) { 430218893Sdim if (UseAvailableExternallyLinkage) { 431218893Sdim // There is already a thunk emitted for this function, do nothing. 432218893Sdim return; 433218893Sdim } 434218893Sdim 435218893Sdim // If a function has a body, it should have available_externally linkage. 436218893Sdim assert(ThunkFn->hasAvailableExternallyLinkage() && 437218893Sdim "Function should have available_externally linkage!"); 438218893Sdim 439218893Sdim // Change the linkage. 440218893Sdim CGM.setFunctionLinkage(cast<CXXMethodDecl>(GD.getDecl()), ThunkFn); 441218893Sdim return; 442218893Sdim } 443218893Sdim 444243830Sdim CGM.SetLLVMFunctionAttributesForDefinition(GD.getDecl(), ThunkFn); 445243830Sdim 446223017Sdim if (ThunkFn->isVarArg()) { 447223017Sdim // Varargs thunks are special; we can't just generate a call because 448223017Sdim // we can't copy the varargs. Our implementation is rather 449223017Sdim // expensive/sucky at the moment, so don't generate the thunk unless 450223017Sdim // we have to. 451223017Sdim // FIXME: Do something better here; GenerateVarArgsThunk is extremely ugly. 452223017Sdim if (!UseAvailableExternallyLinkage) 453223017Sdim CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, Thunk); 454223017Sdim } else { 455223017Sdim // Normal thunk body generation. 456223017Sdim CodeGenFunction(CGM).GenerateThunk(ThunkFn, FnInfo, GD, Thunk); 457259278Sdim if (UseAvailableExternallyLinkage) 458259278Sdim ThunkFn->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage); 459223017Sdim } 460207619Srdivacky} 461207619Srdivacky 462218893Sdimvoid CodeGenVTables::MaybeEmitThunkAvailableExternally(GlobalDecl GD, 463218893Sdim const ThunkInfo &Thunk) { 464218893Sdim // We only want to do this when building with optimizations. 465218893Sdim if (!CGM.getCodeGenOpts().OptimizationLevel) 466218893Sdim return; 467218893Sdim 468218893Sdim // We can't emit thunks for member functions with incomplete types. 469218893Sdim const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 470224145Sdim if (!CGM.getTypes().isFuncTypeConvertible( 471224145Sdim cast<FunctionType>(MD->getType().getTypePtr()))) 472218893Sdim return; 473218893Sdim 474218893Sdim EmitThunk(GD, Thunk, /*UseAvailableExternallyLinkage=*/true); 475218893Sdim} 476218893Sdim 477207619Srdivackyvoid CodeGenVTables::EmitThunks(GlobalDecl GD) 478207619Srdivacky{ 479207619Srdivacky const CXXMethodDecl *MD = 480207619Srdivacky cast<CXXMethodDecl>(GD.getDecl())->getCanonicalDecl(); 481207619Srdivacky 482207619Srdivacky // We don't need to generate thunks for the base destructor. 483207619Srdivacky if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) 484207619Srdivacky return; 485207619Srdivacky 486226633Sdim const VTableContext::ThunkInfoVectorTy *ThunkInfoVector = 487226633Sdim VTContext.getThunkInfo(MD); 488226633Sdim if (!ThunkInfoVector) 489207619Srdivacky return; 490207619Srdivacky 491226633Sdim for (unsigned I = 0, E = ThunkInfoVector->size(); I != E; ++I) 492226633Sdim EmitThunk(GD, (*ThunkInfoVector)[I], 493226633Sdim /*UseAvailableExternallyLinkage=*/false); 494207619Srdivacky} 495207619Srdivacky 496207619Srdivackyllvm::Constant * 497207619SrdivackyCodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD, 498226633Sdim const VTableComponent *Components, 499207619Srdivacky unsigned NumComponents, 500226633Sdim const VTableLayout::VTableThunkTy *VTableThunks, 501226633Sdim unsigned NumVTableThunks) { 502226633Sdim SmallVector<llvm::Constant *, 64> Inits; 503207619Srdivacky 504234353Sdim llvm::Type *Int8PtrTy = CGM.Int8PtrTy; 505207619Srdivacky 506226633Sdim llvm::Type *PtrDiffTy = 507207619Srdivacky CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); 508207619Srdivacky 509207619Srdivacky QualType ClassType = CGM.getContext().getTagDeclType(RD); 510207619Srdivacky llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(ClassType); 511207619Srdivacky 512207619Srdivacky unsigned NextVTableThunkIndex = 0; 513207619Srdivacky 514243830Sdim llvm::Constant *PureVirtualFn = 0, *DeletedVirtualFn = 0; 515207619Srdivacky 516207619Srdivacky for (unsigned I = 0; I != NumComponents; ++I) { 517226633Sdim VTableComponent Component = Components[I]; 518207619Srdivacky 519207619Srdivacky llvm::Constant *Init = 0; 520207619Srdivacky 521207619Srdivacky switch (Component.getKind()) { 522207619Srdivacky case VTableComponent::CK_VCallOffset: 523221345Sdim Init = llvm::ConstantInt::get(PtrDiffTy, 524221345Sdim Component.getVCallOffset().getQuantity()); 525207619Srdivacky Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy); 526207619Srdivacky break; 527207619Srdivacky case VTableComponent::CK_VBaseOffset: 528221345Sdim Init = llvm::ConstantInt::get(PtrDiffTy, 529221345Sdim Component.getVBaseOffset().getQuantity()); 530207619Srdivacky Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy); 531207619Srdivacky break; 532207619Srdivacky case VTableComponent::CK_OffsetToTop: 533221345Sdim Init = llvm::ConstantInt::get(PtrDiffTy, 534221345Sdim Component.getOffsetToTop().getQuantity()); 535207619Srdivacky Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy); 536207619Srdivacky break; 537207619Srdivacky case VTableComponent::CK_RTTI: 538207619Srdivacky Init = llvm::ConstantExpr::getBitCast(RTTI, Int8PtrTy); 539207619Srdivacky break; 540207619Srdivacky case VTableComponent::CK_FunctionPointer: 541207619Srdivacky case VTableComponent::CK_CompleteDtorPointer: 542207619Srdivacky case VTableComponent::CK_DeletingDtorPointer: { 543207619Srdivacky GlobalDecl GD; 544207619Srdivacky 545207619Srdivacky // Get the right global decl. 546207619Srdivacky switch (Component.getKind()) { 547207619Srdivacky default: 548207619Srdivacky llvm_unreachable("Unexpected vtable component kind"); 549207619Srdivacky case VTableComponent::CK_FunctionPointer: 550207619Srdivacky GD = Component.getFunctionDecl(); 551207619Srdivacky break; 552207619Srdivacky case VTableComponent::CK_CompleteDtorPointer: 553207619Srdivacky GD = GlobalDecl(Component.getDestructorDecl(), Dtor_Complete); 554207619Srdivacky break; 555207619Srdivacky case VTableComponent::CK_DeletingDtorPointer: 556207619Srdivacky GD = GlobalDecl(Component.getDestructorDecl(), Dtor_Deleting); 557207619Srdivacky break; 558207619Srdivacky } 559207619Srdivacky 560207619Srdivacky if (cast<CXXMethodDecl>(GD.getDecl())->isPure()) { 561207619Srdivacky // We have a pure virtual member function. 562207619Srdivacky if (!PureVirtualFn) { 563243830Sdim llvm::FunctionType *Ty = 564243830Sdim llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); 565243830Sdim StringRef PureCallName = CGM.getCXXABI().GetPureVirtualCallName(); 566243830Sdim PureVirtualFn = CGM.CreateRuntimeFunction(Ty, PureCallName); 567243830Sdim PureVirtualFn = llvm::ConstantExpr::getBitCast(PureVirtualFn, 568239462Sdim CGM.Int8PtrTy); 569207619Srdivacky } 570207619Srdivacky Init = PureVirtualFn; 571243830Sdim } else if (cast<CXXMethodDecl>(GD.getDecl())->isDeleted()) { 572243830Sdim if (!DeletedVirtualFn) { 573243830Sdim llvm::FunctionType *Ty = 574243830Sdim llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); 575243830Sdim StringRef DeletedCallName = 576243830Sdim CGM.getCXXABI().GetDeletedVirtualCallName(); 577243830Sdim DeletedVirtualFn = CGM.CreateRuntimeFunction(Ty, DeletedCallName); 578243830Sdim DeletedVirtualFn = llvm::ConstantExpr::getBitCast(DeletedVirtualFn, 579243830Sdim CGM.Int8PtrTy); 580243830Sdim } 581243830Sdim Init = DeletedVirtualFn; 582207619Srdivacky } else { 583207619Srdivacky // Check if we should use a thunk. 584226633Sdim if (NextVTableThunkIndex < NumVTableThunks && 585207619Srdivacky VTableThunks[NextVTableThunkIndex].first == I) { 586207619Srdivacky const ThunkInfo &Thunk = VTableThunks[NextVTableThunkIndex].second; 587207619Srdivacky 588234353Sdim MaybeEmitThunkAvailableExternally(GD, Thunk); 589207619Srdivacky Init = CGM.GetAddrOfThunk(GD, Thunk); 590218893Sdim 591207619Srdivacky NextVTableThunkIndex++; 592207619Srdivacky } else { 593226633Sdim llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(GD); 594207619Srdivacky 595218893Sdim Init = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true); 596207619Srdivacky } 597207619Srdivacky 598207619Srdivacky Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy); 599207619Srdivacky } 600207619Srdivacky break; 601207619Srdivacky } 602207619Srdivacky 603207619Srdivacky case VTableComponent::CK_UnusedFunctionPointer: 604207619Srdivacky Init = llvm::ConstantExpr::getNullValue(Int8PtrTy); 605207619Srdivacky break; 606207619Srdivacky }; 607207619Srdivacky 608207619Srdivacky Inits.push_back(Init); 609207619Srdivacky } 610207619Srdivacky 611207619Srdivacky llvm::ArrayType *ArrayType = llvm::ArrayType::get(Int8PtrTy, NumComponents); 612224145Sdim return llvm::ConstantArray::get(ArrayType, Inits); 613207619Srdivacky} 614207619Srdivacky 615207619Srdivackyllvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) { 616226633Sdim llvm::GlobalVariable *&VTable = VTables[RD]; 617226633Sdim if (VTable) 618226633Sdim return VTable; 619226633Sdim 620249423Sdim // Queue up this v-table for possible deferred emission. 621249423Sdim CGM.addDeferredVTable(RD); 622226633Sdim 623234353Sdim SmallString<256> OutName; 624218893Sdim llvm::raw_svector_ostream Out(OutName); 625218893Sdim CGM.getCXXABI().getMangleContext().mangleCXXVTable(RD, Out); 626218893Sdim Out.flush(); 627226633Sdim StringRef Name = OutName.str(); 628207619Srdivacky 629207619Srdivacky llvm::ArrayType *ArrayType = 630234353Sdim llvm::ArrayType::get(CGM.Int8PtrTy, 631226633Sdim VTContext.getVTableLayout(RD).getNumVTableComponents()); 632207619Srdivacky 633226633Sdim VTable = 634218893Sdim CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, 635218893Sdim llvm::GlobalValue::ExternalLinkage); 636226633Sdim VTable->setUnnamedAddr(true); 637226633Sdim return VTable; 638207619Srdivacky} 639207619Srdivacky 640207619Srdivackyvoid 641207619SrdivackyCodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable, 642207619Srdivacky llvm::GlobalVariable::LinkageTypes Linkage, 643207619Srdivacky const CXXRecordDecl *RD) { 644226633Sdim const VTableLayout &VTLayout = VTContext.getVTableLayout(RD); 645207619Srdivacky 646207619Srdivacky // Create and set the initializer. 647207619Srdivacky llvm::Constant *Init = 648226633Sdim CreateVTableInitializer(RD, 649226633Sdim VTLayout.vtable_component_begin(), 650226633Sdim VTLayout.getNumVTableComponents(), 651226633Sdim VTLayout.vtable_thunk_begin(), 652226633Sdim VTLayout.getNumVTableThunks()); 653207619Srdivacky VTable->setInitializer(Init); 654207619Srdivacky 655207619Srdivacky // Set the correct linkage. 656207619Srdivacky VTable->setLinkage(Linkage); 657210299Sed 658210299Sed // Set the right visibility. 659218893Sdim CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForVTable); 660207619Srdivacky} 661207619Srdivacky 662207619Srdivackyllvm::GlobalVariable * 663207619SrdivackyCodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, 664207619Srdivacky const BaseSubobject &Base, 665207619Srdivacky bool BaseIsVirtual, 666221345Sdim llvm::GlobalVariable::LinkageTypes Linkage, 667207619Srdivacky VTableAddressPointsMapTy& AddressPoints) { 668234353Sdim OwningPtr<VTableLayout> VTLayout( 669226633Sdim VTContext.createConstructionVTableLayout(Base.getBase(), 670226633Sdim Base.getBaseOffset(), 671226633Sdim BaseIsVirtual, RD)); 672207619Srdivacky 673207619Srdivacky // Add the address points. 674226633Sdim AddressPoints = VTLayout->getAddressPoints(); 675207619Srdivacky 676207619Srdivacky // Get the mangled construction vtable name. 677234353Sdim SmallString<256> OutName; 678218893Sdim llvm::raw_svector_ostream Out(OutName); 679212904Sdim CGM.getCXXABI().getMangleContext(). 680221345Sdim mangleCXXCtorVTable(RD, Base.getBaseOffset().getQuantity(), Base.getBase(), 681221345Sdim Out); 682218893Sdim Out.flush(); 683226633Sdim StringRef Name = OutName.str(); 684207619Srdivacky 685207619Srdivacky llvm::ArrayType *ArrayType = 686234353Sdim llvm::ArrayType::get(CGM.Int8PtrTy, VTLayout->getNumVTableComponents()); 687207619Srdivacky 688249423Sdim // Construction vtable symbols are not part of the Itanium ABI, so we cannot 689249423Sdim // guarantee that they actually will be available externally. Instead, when 690249423Sdim // emitting an available_externally VTT, we provide references to an internal 691249423Sdim // linkage construction vtable. The ABI only requires complete-object vtables 692249423Sdim // to be the same for all instances of a type, not construction vtables. 693249423Sdim if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage) 694249423Sdim Linkage = llvm::GlobalVariable::InternalLinkage; 695249423Sdim 696207619Srdivacky // Create the variable that will hold the construction vtable. 697207619Srdivacky llvm::GlobalVariable *VTable = 698221345Sdim CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, Linkage); 699221345Sdim CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForConstructionVTable); 700207619Srdivacky 701221345Sdim // V-tables are always unnamed_addr. 702221345Sdim VTable->setUnnamedAddr(true); 703221345Sdim 704207619Srdivacky // Create and set the initializer. 705207619Srdivacky llvm::Constant *Init = 706207619Srdivacky CreateVTableInitializer(Base.getBase(), 707226633Sdim VTLayout->vtable_component_begin(), 708226633Sdim VTLayout->getNumVTableComponents(), 709226633Sdim VTLayout->vtable_thunk_begin(), 710226633Sdim VTLayout->getNumVTableThunks()); 711207619Srdivacky VTable->setInitializer(Init); 712207619Srdivacky 713207619Srdivacky return VTable; 714207619Srdivacky} 715207619Srdivacky 716249423Sdim/// Compute the required linkage of the v-table for the given class. 717249423Sdim/// 718249423Sdim/// Note that we only call this at the end of the translation unit. 719249423Sdimllvm::GlobalVariable::LinkageTypes 720249423SdimCodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) { 721249423Sdim if (RD->getLinkage() != ExternalLinkage) 722249423Sdim return llvm::GlobalVariable::InternalLinkage; 723249423Sdim 724249423Sdim // We're at the end of the translation unit, so the current key 725249423Sdim // function is fully correct. 726249423Sdim if (const CXXMethodDecl *keyFunction = Context.getCurrentKeyFunction(RD)) { 727249423Sdim // If this class has a key function, use that to determine the 728249423Sdim // linkage of the vtable. 729249423Sdim const FunctionDecl *def = 0; 730249423Sdim if (keyFunction->hasBody(def)) 731249423Sdim keyFunction = cast<CXXMethodDecl>(def); 732249423Sdim 733249423Sdim switch (keyFunction->getTemplateSpecializationKind()) { 734249423Sdim case TSK_Undeclared: 735249423Sdim case TSK_ExplicitSpecialization: 736249423Sdim // When compiling with optimizations turned on, we emit all vtables, 737249423Sdim // even if the key function is not defined in the current translation 738249423Sdim // unit. If this is the case, use available_externally linkage. 739249423Sdim if (!def && CodeGenOpts.OptimizationLevel) 740249423Sdim return llvm::GlobalVariable::AvailableExternallyLinkage; 741249423Sdim 742249423Sdim if (keyFunction->isInlined()) 743249423Sdim return !Context.getLangOpts().AppleKext ? 744249423Sdim llvm::GlobalVariable::LinkOnceODRLinkage : 745249423Sdim llvm::Function::InternalLinkage; 746249423Sdim 747249423Sdim return llvm::GlobalVariable::ExternalLinkage; 748249423Sdim 749249423Sdim case TSK_ImplicitInstantiation: 750249423Sdim return !Context.getLangOpts().AppleKext ? 751249423Sdim llvm::GlobalVariable::LinkOnceODRLinkage : 752249423Sdim llvm::Function::InternalLinkage; 753249423Sdim 754249423Sdim case TSK_ExplicitInstantiationDefinition: 755249423Sdim return !Context.getLangOpts().AppleKext ? 756249423Sdim llvm::GlobalVariable::WeakODRLinkage : 757249423Sdim llvm::Function::InternalLinkage; 758249423Sdim 759249423Sdim case TSK_ExplicitInstantiationDeclaration: 760249423Sdim return !Context.getLangOpts().AppleKext ? 761249423Sdim llvm::GlobalVariable::AvailableExternallyLinkage : 762249423Sdim llvm::Function::InternalLinkage; 763249423Sdim } 764249423Sdim } 765249423Sdim 766249423Sdim // -fapple-kext mode does not support weak linkage, so we must use 767249423Sdim // internal linkage. 768249423Sdim if (Context.getLangOpts().AppleKext) 769249423Sdim return llvm::Function::InternalLinkage; 770249423Sdim 771249423Sdim switch (RD->getTemplateSpecializationKind()) { 772249423Sdim case TSK_Undeclared: 773249423Sdim case TSK_ExplicitSpecialization: 774249423Sdim case TSK_ImplicitInstantiation: 775249423Sdim return llvm::GlobalVariable::LinkOnceODRLinkage; 776249423Sdim 777249423Sdim case TSK_ExplicitInstantiationDeclaration: 778249423Sdim return llvm::GlobalVariable::AvailableExternallyLinkage; 779249423Sdim 780249423Sdim case TSK_ExplicitInstantiationDefinition: 781249423Sdim return llvm::GlobalVariable::WeakODRLinkage; 782249423Sdim } 783249423Sdim 784249423Sdim llvm_unreachable("Invalid TemplateSpecializationKind!"); 785249423Sdim} 786249423Sdim 787249423Sdim/// This is a callback from Sema to tell us that it believes that a 788249423Sdim/// particular v-table is required to be emitted in this translation 789249423Sdim/// unit. 790249423Sdim/// 791249423Sdim/// The reason we don't simply trust this callback is because Sema 792249423Sdim/// will happily report that something is used even when it's used 793249423Sdim/// only in code that we don't actually have to emit. 794249423Sdim/// 795249423Sdim/// \param isRequired - if true, the v-table is mandatory, e.g. 796249423Sdim/// because the translation unit defines the key function 797249423Sdimvoid CodeGenModule::EmitVTable(CXXRecordDecl *theClass, bool isRequired) { 798249423Sdim if (!isRequired) return; 799249423Sdim 800249423Sdim VTables.GenerateClassData(theClass); 801249423Sdim} 802249423Sdim 803207619Srdivackyvoid 804249423SdimCodeGenVTables::GenerateClassData(const CXXRecordDecl *RD) { 805249423Sdim // First off, check whether we've already emitted the v-table and 806249423Sdim // associated stuff. 807226633Sdim llvm::GlobalVariable *VTable = GetAddrOfVTable(RD); 808226633Sdim if (VTable->hasInitializer()) 809207619Srdivacky return; 810207619Srdivacky 811249423Sdim llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD); 812207619Srdivacky EmitVTableDefinition(VTable, Linkage, RD); 813207619Srdivacky 814218893Sdim if (RD->getNumVBases()) { 815249423Sdim if (!CGM.getTarget().getCXXABI().isMicrosoft()) { 816249423Sdim llvm::GlobalVariable *VTT = GetAddrOfVTT(RD); 817249423Sdim EmitVTTDefinition(VTT, Linkage, RD); 818249423Sdim } else { 819249423Sdim // FIXME: Emit vbtables here. 820249423Sdim } 821218893Sdim } 822207619Srdivacky 823207619Srdivacky // If this is the magic class __cxxabiv1::__fundamental_type_info, 824207619Srdivacky // we will emit the typeinfo for the fundamental types. This is the 825207619Srdivacky // same behaviour as GCC. 826207619Srdivacky const DeclContext *DC = RD->getDeclContext(); 827207619Srdivacky if (RD->getIdentifier() && 828207619Srdivacky RD->getIdentifier()->isStr("__fundamental_type_info") && 829207619Srdivacky isa<NamespaceDecl>(DC) && 830207619Srdivacky cast<NamespaceDecl>(DC)->getIdentifier() && 831207619Srdivacky cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") && 832207619Srdivacky DC->getParent()->isTranslationUnit()) 833207619Srdivacky CGM.EmitFundamentalRTTIDescriptors(); 834207619Srdivacky} 835249423Sdim 836249423Sdim/// At this point in the translation unit, does it appear that can we 837249423Sdim/// rely on the vtable being defined elsewhere in the program? 838249423Sdim/// 839249423Sdim/// The response is really only definitive when called at the end of 840249423Sdim/// the translation unit. 841249423Sdim/// 842249423Sdim/// The only semantic restriction here is that the object file should 843249423Sdim/// not contain a v-table definition when that v-table is defined 844249423Sdim/// strongly elsewhere. Otherwise, we'd just like to avoid emitting 845249423Sdim/// v-tables when unnecessary. 846249423Sdimbool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) { 847249423Sdim assert(RD->isDynamicClass() && "Non dynamic classes have no VTable."); 848249423Sdim 849249423Sdim // If we have an explicit instantiation declaration (and not a 850249423Sdim // definition), the v-table is defined elsewhere. 851249423Sdim TemplateSpecializationKind TSK = RD->getTemplateSpecializationKind(); 852249423Sdim if (TSK == TSK_ExplicitInstantiationDeclaration) 853249423Sdim return true; 854249423Sdim 855249423Sdim // Otherwise, if the class is an instantiated template, the 856249423Sdim // v-table must be defined here. 857249423Sdim if (TSK == TSK_ImplicitInstantiation || 858249423Sdim TSK == TSK_ExplicitInstantiationDefinition) 859249423Sdim return false; 860249423Sdim 861249423Sdim // Otherwise, if the class doesn't have a key function (possibly 862249423Sdim // anymore), the v-table must be defined here. 863249423Sdim const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD); 864249423Sdim if (!keyFunction) 865249423Sdim return false; 866249423Sdim 867249423Sdim // Otherwise, if we don't have a definition of the key function, the 868249423Sdim // v-table must be defined somewhere else. 869249423Sdim return !keyFunction->hasBody(); 870249423Sdim} 871249423Sdim 872249423Sdim/// Given that we're currently at the end of the translation unit, and 873249423Sdim/// we've emitted a reference to the v-table for this class, should 874249423Sdim/// we define that v-table? 875249423Sdimstatic bool shouldEmitVTableAtEndOfTranslationUnit(CodeGenModule &CGM, 876249423Sdim const CXXRecordDecl *RD) { 877249423Sdim // If we're building with optimization, we always emit v-tables 878249423Sdim // since that allows for virtual function calls to be devirtualized. 879249423Sdim // If the v-table is defined strongly elsewhere, this definition 880249423Sdim // will be emitted available_externally. 881249423Sdim // 882249423Sdim // However, we don't want to do this in -fapple-kext mode, because 883249423Sdim // kext mode does not permit devirtualization. 884249423Sdim if (CGM.getCodeGenOpts().OptimizationLevel && !CGM.getLangOpts().AppleKext) 885249423Sdim return true; 886249423Sdim 887249423Sdim return !CGM.getVTables().isVTableExternal(RD); 888249423Sdim} 889249423Sdim 890249423Sdim/// Given that at some point we emitted a reference to one or more 891249423Sdim/// v-tables, and that we are now at the end of the translation unit, 892249423Sdim/// decide whether we should emit them. 893249423Sdimvoid CodeGenModule::EmitDeferredVTables() { 894249423Sdim#ifndef NDEBUG 895249423Sdim // Remember the size of DeferredVTables, because we're going to assume 896249423Sdim // that this entire operation doesn't modify it. 897249423Sdim size_t savedSize = DeferredVTables.size(); 898249423Sdim#endif 899249423Sdim 900249423Sdim typedef std::vector<const CXXRecordDecl *>::const_iterator const_iterator; 901249423Sdim for (const_iterator i = DeferredVTables.begin(), 902249423Sdim e = DeferredVTables.end(); i != e; ++i) { 903249423Sdim const CXXRecordDecl *RD = *i; 904249423Sdim if (shouldEmitVTableAtEndOfTranslationUnit(*this, RD)) 905249423Sdim VTables.GenerateClassData(RD); 906249423Sdim } 907249423Sdim 908249423Sdim assert(savedSize == DeferredVTables.size() && 909249423Sdim "deferred extra v-tables during v-table emission?"); 910249423Sdim DeferredVTables.clear(); 911249423Sdim} 912