CGVTT.cpp revision 226633
1202879Srdivacky//===--- CGVTT.cpp - Emit LLVM Code for C++ VTTs --------------------------===// 2202879Srdivacky// 3202879Srdivacky// The LLVM Compiler Infrastructure 4202879Srdivacky// 5202879Srdivacky// This file is distributed under the University of Illinois Open Source 6202879Srdivacky// License. See LICENSE.TXT for details. 7202879Srdivacky// 8202879Srdivacky//===----------------------------------------------------------------------===// 9202879Srdivacky// 10202879Srdivacky// This contains code dealing with C++ code generation of VTTs (vtable tables). 11202879Srdivacky// 12202879Srdivacky//===----------------------------------------------------------------------===// 13202879Srdivacky 14202879Srdivacky#include "CodeGenModule.h" 15212904Sdim#include "CGCXXABI.h" 16202879Srdivacky#include "clang/AST/RecordLayout.h" 17226633Sdim#include "clang/AST/VTTBuilder.h" 18202879Srdivackyusing namespace clang; 19202879Srdivackyusing namespace CodeGen; 20202879Srdivacky 21202879Srdivacky#define D1(x) 22202879Srdivacky 23226633Sdimllvm::Constant *GetAddrOfVTTVTable(CodeGenVTables &CGVT, 24226633Sdim const CXXRecordDecl *MostDerivedClass, 25226633Sdim const VTTVTable &VTable, 26226633Sdim llvm::GlobalVariable::LinkageTypes Linkage, 27226633Sdim llvm::DenseMap<BaseSubobject, uint64_t> &AddressPoints) { 28226633Sdim if (VTable.getBase() == MostDerivedClass) { 29226633Sdim assert(VTable.getBaseOffset().isZero() && 30206084Srdivacky "Most derived class vtable must have a zero offset!"); 31206084Srdivacky // This is a regular vtable. 32226633Sdim return CGVT.GetAddrOfVTable(MostDerivedClass); 33206084Srdivacky } 34206084Srdivacky 35226633Sdim return CGVT.GenerateConstructionVTable(MostDerivedClass, 36226633Sdim VTable.getBaseSubobject(), 37226633Sdim VTable.isVirtual(), 38226633Sdim Linkage, 39226633Sdim AddressPoints); 40206084Srdivacky} 41202879Srdivacky 42226633Sdimvoid 43226633SdimCodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, 44226633Sdim llvm::GlobalVariable::LinkageTypes Linkage, 45226633Sdim const CXXRecordDecl *RD) { 46226633Sdim VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/true); 47206084Srdivacky 48226633Sdim llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()), 49226633Sdim *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext()); 50226633Sdim llvm::ArrayType *ArrayType = 51226633Sdim llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size()); 52206084Srdivacky 53226633Sdim SmallVector<llvm::Constant *, 8> VTables; 54226633Sdim SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints; 55226633Sdim for (const VTTVTable *i = Builder.getVTTVTables().begin(), 56226633Sdim *e = Builder.getVTTVTables().end(); i != e; ++i) { 57226633Sdim VTableAddressPoints.push_back(VTableAddressPointsMapTy()); 58226633Sdim VTables.push_back(GetAddrOfVTTVTable(*this, RD, *i, Linkage, 59226633Sdim VTableAddressPoints.back())); 60202879Srdivacky } 61202879Srdivacky 62226633Sdim SmallVector<llvm::Constant *, 8> VTTComponents; 63226633Sdim for (const VTTComponent *i = Builder.getVTTComponents().begin(), 64226633Sdim *e = Builder.getVTTComponents().end(); i != e; ++i) { 65226633Sdim const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex]; 66226633Sdim llvm::Constant *VTable = VTables[i->VTableIndex]; 67226633Sdim uint64_t AddressPoint; 68226633Sdim if (VTTVT.getBase() == RD) { 69226633Sdim // Just get the address point for the regular vtable. 70226633Sdim AddressPoint = VTContext.getVTableLayout(RD) 71226633Sdim .getAddressPoint(i->VTableBase); 72226633Sdim assert(AddressPoint != 0 && "Did not find vtable address point!"); 73206084Srdivacky } else { 74226633Sdim AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase); 75226633Sdim assert(AddressPoint != 0 && "Did not find ctor vtable address point!"); 76202879Srdivacky } 77202879Srdivacky 78226633Sdim llvm::Value *Idxs[] = { 79226633Sdim llvm::ConstantInt::get(Int64Ty, 0), 80226633Sdim llvm::ConstantInt::get(Int64Ty, AddressPoint) 81226633Sdim }; 82202879Srdivacky 83226633Sdim llvm::Constant *Init = 84226633Sdim llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Idxs); 85202879Srdivacky 86226633Sdim Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy); 87202879Srdivacky 88226633Sdim VTTComponents.push_back(Init); 89202879Srdivacky } 90202879Srdivacky 91226633Sdim llvm::Constant *Init = llvm::ConstantArray::get(ArrayType, VTTComponents); 92202879Srdivacky 93218893Sdim VTT->setInitializer(Init); 94202879Srdivacky 95218893Sdim // Set the correct linkage. 96218893Sdim VTT->setLinkage(Linkage); 97202879Srdivacky 98218893Sdim // Set the right visibility. 99218893Sdim CGM.setTypeVisibility(VTT, RD, CodeGenModule::TVK_ForVTT); 100218893Sdim} 101202879Srdivacky 102218893Sdimllvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) { 103218893Sdim assert(RD->getNumVBases() && "Only classes with virtual bases need a VTT"); 104206084Srdivacky 105218893Sdim llvm::SmallString<256> OutName; 106218893Sdim llvm::raw_svector_ostream Out(OutName); 107218893Sdim CGM.getCXXABI().getMangleContext().mangleCXXVTT(RD, Out); 108218893Sdim Out.flush(); 109226633Sdim StringRef Name = OutName.str(); 110202879Srdivacky 111226633Sdim // This will also defer the definition of the VTT. 112226633Sdim (void) GetAddrOfVTable(RD); 113223017Sdim 114226633Sdim VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); 115218893Sdim 116226633Sdim llvm::Type *Int8PtrTy = 117218893Sdim llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); 118226633Sdim llvm::ArrayType *ArrayType = 119218893Sdim llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size()); 120218893Sdim 121218893Sdim llvm::GlobalVariable *GV = 122218893Sdim CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, 123218893Sdim llvm::GlobalValue::ExternalLinkage); 124218893Sdim GV->setUnnamedAddr(true); 125202879Srdivacky return GV; 126202879Srdivacky} 127202879Srdivacky 128206084Srdivackybool CodeGenVTables::needsVTTParameter(GlobalDecl GD) { 129202879Srdivacky const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 130202879Srdivacky 131202879Srdivacky // We don't have any virtual bases, just return early. 132202879Srdivacky if (!MD->getParent()->getNumVBases()) 133202879Srdivacky return false; 134202879Srdivacky 135202879Srdivacky // Check if we have a base constructor. 136202879Srdivacky if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base) 137202879Srdivacky return true; 138202879Srdivacky 139202879Srdivacky // Check if we have a base destructor. 140202879Srdivacky if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) 141202879Srdivacky return true; 142202879Srdivacky 143202879Srdivacky return false; 144202879Srdivacky} 145202879Srdivacky 146206084Srdivackyuint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD, 147207619Srdivacky BaseSubobject Base) { 148207619Srdivacky BaseSubobjectPairTy ClassSubobjectPair(RD, Base); 149202879Srdivacky 150207619Srdivacky SubVTTIndiciesMapTy::iterator I = SubVTTIndicies.find(ClassSubobjectPair); 151202879Srdivacky if (I != SubVTTIndicies.end()) 152202879Srdivacky return I->second; 153202879Srdivacky 154226633Sdim VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); 155202879Srdivacky 156207619Srdivacky for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = 157202879Srdivacky Builder.getSubVTTIndicies().begin(), 158202879Srdivacky E = Builder.getSubVTTIndicies().end(); I != E; ++I) { 159202879Srdivacky // Insert all indices. 160207619Srdivacky BaseSubobjectPairTy ClassSubobjectPair(RD, I->first); 161202879Srdivacky 162207619Srdivacky SubVTTIndicies.insert(std::make_pair(ClassSubobjectPair, I->second)); 163202879Srdivacky } 164202879Srdivacky 165207619Srdivacky I = SubVTTIndicies.find(ClassSubobjectPair); 166202879Srdivacky assert(I != SubVTTIndicies.end() && "Did not find index!"); 167202879Srdivacky 168202879Srdivacky return I->second; 169202879Srdivacky} 170206084Srdivacky 171206084Srdivackyuint64_t 172206084SrdivackyCodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD, 173206084Srdivacky BaseSubobject Base) { 174206084Srdivacky SecondaryVirtualPointerIndicesMapTy::iterator I = 175206084Srdivacky SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base)); 176206084Srdivacky 177206084Srdivacky if (I != SecondaryVirtualPointerIndices.end()) 178206084Srdivacky return I->second; 179206084Srdivacky 180226633Sdim VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); 181206084Srdivacky 182206084Srdivacky // Insert all secondary vpointer indices. 183206084Srdivacky for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = 184206084Srdivacky Builder.getSecondaryVirtualPointerIndices().begin(), 185206084Srdivacky E = Builder.getSecondaryVirtualPointerIndices().end(); I != E; ++I) { 186206084Srdivacky std::pair<const CXXRecordDecl *, BaseSubobject> Pair = 187206084Srdivacky std::make_pair(RD, I->first); 188206084Srdivacky 189206084Srdivacky SecondaryVirtualPointerIndices.insert(std::make_pair(Pair, I->second)); 190206084Srdivacky } 191206084Srdivacky 192206084Srdivacky I = SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base)); 193206084Srdivacky assert(I != SecondaryVirtualPointerIndices.end() && "Did not find index!"); 194206084Srdivacky 195206084Srdivacky return I->second; 196206084Srdivacky} 197206084Srdivacky 198