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 21234353Sdimstatic llvm::Constant * 22263508SdimGetAddrOfVTTVTable(CodeGenVTables &CGVT, CodeGenModule &CGM, 23263508Sdim const CXXRecordDecl *MostDerivedClass, 24234353Sdim const VTTVTable &VTable, 25234353Sdim llvm::GlobalVariable::LinkageTypes Linkage, 26234353Sdim llvm::DenseMap<BaseSubobject, uint64_t> &AddressPoints) { 27226633Sdim if (VTable.getBase() == MostDerivedClass) { 28226633Sdim assert(VTable.getBaseOffset().isZero() && 29206084Srdivacky "Most derived class vtable must have a zero offset!"); 30206084Srdivacky // This is a regular vtable. 31263508Sdim return CGM.getCXXABI().getAddrOfVTable(MostDerivedClass, CharUnits()); 32206084Srdivacky } 33206084Srdivacky 34226633Sdim return CGVT.GenerateConstructionVTable(MostDerivedClass, 35226633Sdim VTable.getBaseSubobject(), 36226633Sdim VTable.isVirtual(), 37226633Sdim Linkage, 38226633Sdim AddressPoints); 39206084Srdivacky} 40202879Srdivacky 41226633Sdimvoid 42226633SdimCodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, 43226633Sdim llvm::GlobalVariable::LinkageTypes Linkage, 44226633Sdim const CXXRecordDecl *RD) { 45226633Sdim VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/true); 46206084Srdivacky 47234353Sdim llvm::Type *Int8PtrTy = CGM.Int8PtrTy, *Int64Ty = CGM.Int64Ty; 48226633Sdim llvm::ArrayType *ArrayType = 49226633Sdim llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size()); 50206084Srdivacky 51226633Sdim SmallVector<llvm::Constant *, 8> VTables; 52226633Sdim SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints; 53226633Sdim for (const VTTVTable *i = Builder.getVTTVTables().begin(), 54226633Sdim *e = Builder.getVTTVTables().end(); i != e; ++i) { 55226633Sdim VTableAddressPoints.push_back(VTableAddressPointsMapTy()); 56263508Sdim VTables.push_back(GetAddrOfVTTVTable(*this, CGM, RD, *i, Linkage, 57226633Sdim VTableAddressPoints.back())); 58202879Srdivacky } 59202879Srdivacky 60226633Sdim SmallVector<llvm::Constant *, 8> VTTComponents; 61226633Sdim for (const VTTComponent *i = Builder.getVTTComponents().begin(), 62226633Sdim *e = Builder.getVTTComponents().end(); i != e; ++i) { 63226633Sdim const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex]; 64226633Sdim llvm::Constant *VTable = VTables[i->VTableIndex]; 65226633Sdim uint64_t AddressPoint; 66226633Sdim if (VTTVT.getBase() == RD) { 67226633Sdim // Just get the address point for the regular vtable. 68263508Sdim AddressPoint = 69263508Sdim ItaniumVTContext.getVTableLayout(RD).getAddressPoint(i->VTableBase); 70226633Sdim assert(AddressPoint != 0 && "Did not find vtable address point!"); 71206084Srdivacky } else { 72226633Sdim AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase); 73226633Sdim assert(AddressPoint != 0 && "Did not find ctor vtable address point!"); 74202879Srdivacky } 75202879Srdivacky 76226633Sdim llvm::Value *Idxs[] = { 77226633Sdim llvm::ConstantInt::get(Int64Ty, 0), 78226633Sdim llvm::ConstantInt::get(Int64Ty, AddressPoint) 79226633Sdim }; 80202879Srdivacky 81226633Sdim llvm::Constant *Init = 82226633Sdim llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Idxs); 83202879Srdivacky 84226633Sdim Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy); 85202879Srdivacky 86226633Sdim VTTComponents.push_back(Init); 87202879Srdivacky } 88202879Srdivacky 89226633Sdim llvm::Constant *Init = llvm::ConstantArray::get(ArrayType, VTTComponents); 90202879Srdivacky 91218893Sdim VTT->setInitializer(Init); 92202879Srdivacky 93218893Sdim // Set the correct linkage. 94218893Sdim VTT->setLinkage(Linkage); 95202879Srdivacky 96218893Sdim // Set the right visibility. 97218893Sdim CGM.setTypeVisibility(VTT, RD, CodeGenModule::TVK_ForVTT); 98218893Sdim} 99202879Srdivacky 100218893Sdimllvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) { 101218893Sdim assert(RD->getNumVBases() && "Only classes with virtual bases need a VTT"); 102206084Srdivacky 103234353Sdim SmallString<256> OutName; 104218893Sdim llvm::raw_svector_ostream Out(OutName); 105263508Sdim cast<ItaniumMangleContext>(CGM.getCXXABI().getMangleContext()) 106263508Sdim .mangleCXXVTT(RD, Out); 107218893Sdim Out.flush(); 108226633Sdim StringRef Name = OutName.str(); 109202879Srdivacky 110226633Sdim // This will also defer the definition of the VTT. 111263508Sdim (void) CGM.getCXXABI().getAddrOfVTable(RD, CharUnits()); 112223017Sdim 113226633Sdim VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); 114218893Sdim 115226633Sdim llvm::ArrayType *ArrayType = 116234353Sdim llvm::ArrayType::get(CGM.Int8PtrTy, Builder.getVTTComponents().size()); 117218893Sdim 118218893Sdim llvm::GlobalVariable *GV = 119218893Sdim CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, 120218893Sdim llvm::GlobalValue::ExternalLinkage); 121218893Sdim GV->setUnnamedAddr(true); 122202879Srdivacky return GV; 123202879Srdivacky} 124202879Srdivacky 125206084Srdivackyuint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD, 126207619Srdivacky BaseSubobject Base) { 127207619Srdivacky BaseSubobjectPairTy ClassSubobjectPair(RD, Base); 128202879Srdivacky 129207619Srdivacky SubVTTIndiciesMapTy::iterator I = SubVTTIndicies.find(ClassSubobjectPair); 130202879Srdivacky if (I != SubVTTIndicies.end()) 131202879Srdivacky return I->second; 132202879Srdivacky 133226633Sdim VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); 134202879Srdivacky 135207619Srdivacky for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = 136202879Srdivacky Builder.getSubVTTIndicies().begin(), 137202879Srdivacky E = Builder.getSubVTTIndicies().end(); I != E; ++I) { 138202879Srdivacky // Insert all indices. 139207619Srdivacky BaseSubobjectPairTy ClassSubobjectPair(RD, I->first); 140202879Srdivacky 141207619Srdivacky SubVTTIndicies.insert(std::make_pair(ClassSubobjectPair, I->second)); 142202879Srdivacky } 143202879Srdivacky 144207619Srdivacky I = SubVTTIndicies.find(ClassSubobjectPair); 145202879Srdivacky assert(I != SubVTTIndicies.end() && "Did not find index!"); 146202879Srdivacky 147202879Srdivacky return I->second; 148202879Srdivacky} 149206084Srdivacky 150206084Srdivackyuint64_t 151206084SrdivackyCodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD, 152206084Srdivacky BaseSubobject Base) { 153206084Srdivacky SecondaryVirtualPointerIndicesMapTy::iterator I = 154206084Srdivacky SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base)); 155206084Srdivacky 156206084Srdivacky if (I != SecondaryVirtualPointerIndices.end()) 157206084Srdivacky return I->second; 158206084Srdivacky 159226633Sdim VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); 160206084Srdivacky 161206084Srdivacky // Insert all secondary vpointer indices. 162206084Srdivacky for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = 163206084Srdivacky Builder.getSecondaryVirtualPointerIndices().begin(), 164206084Srdivacky E = Builder.getSecondaryVirtualPointerIndices().end(); I != E; ++I) { 165206084Srdivacky std::pair<const CXXRecordDecl *, BaseSubobject> Pair = 166206084Srdivacky std::make_pair(RD, I->first); 167206084Srdivacky 168206084Srdivacky SecondaryVirtualPointerIndices.insert(std::make_pair(Pair, I->second)); 169206084Srdivacky } 170206084Srdivacky 171206084Srdivacky I = SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base)); 172206084Srdivacky assert(I != SecondaryVirtualPointerIndices.end() && "Did not find index!"); 173206084Srdivacky 174206084Srdivacky return I->second; 175206084Srdivacky} 176206084Srdivacky 177