1*f4a2713aSLionel Sambuc //===--- CGVTT.cpp - Emit LLVM Code for C++ VTTs --------------------------===// 2*f4a2713aSLionel Sambuc // 3*f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4*f4a2713aSLionel Sambuc // 5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7*f4a2713aSLionel Sambuc // 8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9*f4a2713aSLionel Sambuc // 10*f4a2713aSLionel Sambuc // This contains code dealing with C++ code generation of VTTs (vtable tables). 11*f4a2713aSLionel Sambuc // 12*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 13*f4a2713aSLionel Sambuc 14*f4a2713aSLionel Sambuc #include "CodeGenModule.h" 15*f4a2713aSLionel Sambuc #include "CGCXXABI.h" 16*f4a2713aSLionel Sambuc #include "clang/AST/RecordLayout.h" 17*f4a2713aSLionel Sambuc #include "clang/AST/VTTBuilder.h" 18*f4a2713aSLionel Sambuc using namespace clang; 19*f4a2713aSLionel Sambuc using namespace CodeGen; 20*f4a2713aSLionel Sambuc 21*f4a2713aSLionel Sambuc static llvm::Constant * 22*f4a2713aSLionel Sambuc GetAddrOfVTTVTable(CodeGenVTables &CGVT, CodeGenModule &CGM, 23*f4a2713aSLionel Sambuc const CXXRecordDecl *MostDerivedClass, 24*f4a2713aSLionel Sambuc const VTTVTable &VTable, 25*f4a2713aSLionel Sambuc llvm::GlobalVariable::LinkageTypes Linkage, 26*f4a2713aSLionel Sambuc llvm::DenseMap<BaseSubobject, uint64_t> &AddressPoints) { 27*f4a2713aSLionel Sambuc if (VTable.getBase() == MostDerivedClass) { 28*f4a2713aSLionel Sambuc assert(VTable.getBaseOffset().isZero() && 29*f4a2713aSLionel Sambuc "Most derived class vtable must have a zero offset!"); 30*f4a2713aSLionel Sambuc // This is a regular vtable. 31*f4a2713aSLionel Sambuc return CGM.getCXXABI().getAddrOfVTable(MostDerivedClass, CharUnits()); 32*f4a2713aSLionel Sambuc } 33*f4a2713aSLionel Sambuc 34*f4a2713aSLionel Sambuc return CGVT.GenerateConstructionVTable(MostDerivedClass, 35*f4a2713aSLionel Sambuc VTable.getBaseSubobject(), 36*f4a2713aSLionel Sambuc VTable.isVirtual(), 37*f4a2713aSLionel Sambuc Linkage, 38*f4a2713aSLionel Sambuc AddressPoints); 39*f4a2713aSLionel Sambuc } 40*f4a2713aSLionel Sambuc 41*f4a2713aSLionel Sambuc void 42*f4a2713aSLionel Sambuc CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, 43*f4a2713aSLionel Sambuc llvm::GlobalVariable::LinkageTypes Linkage, 44*f4a2713aSLionel Sambuc const CXXRecordDecl *RD) { 45*f4a2713aSLionel Sambuc VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/true); 46*f4a2713aSLionel Sambuc 47*f4a2713aSLionel Sambuc llvm::Type *Int8PtrTy = CGM.Int8PtrTy, *Int64Ty = CGM.Int64Ty; 48*f4a2713aSLionel Sambuc llvm::ArrayType *ArrayType = 49*f4a2713aSLionel Sambuc llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size()); 50*f4a2713aSLionel Sambuc 51*f4a2713aSLionel Sambuc SmallVector<llvm::Constant *, 8> VTables; 52*f4a2713aSLionel Sambuc SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints; 53*f4a2713aSLionel Sambuc for (const VTTVTable *i = Builder.getVTTVTables().begin(), 54*f4a2713aSLionel Sambuc *e = Builder.getVTTVTables().end(); i != e; ++i) { 55*f4a2713aSLionel Sambuc VTableAddressPoints.push_back(VTableAddressPointsMapTy()); 56*f4a2713aSLionel Sambuc VTables.push_back(GetAddrOfVTTVTable(*this, CGM, RD, *i, Linkage, 57*f4a2713aSLionel Sambuc VTableAddressPoints.back())); 58*f4a2713aSLionel Sambuc } 59*f4a2713aSLionel Sambuc 60*f4a2713aSLionel Sambuc SmallVector<llvm::Constant *, 8> VTTComponents; 61*f4a2713aSLionel Sambuc for (const VTTComponent *i = Builder.getVTTComponents().begin(), 62*f4a2713aSLionel Sambuc *e = Builder.getVTTComponents().end(); i != e; ++i) { 63*f4a2713aSLionel Sambuc const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex]; 64*f4a2713aSLionel Sambuc llvm::Constant *VTable = VTables[i->VTableIndex]; 65*f4a2713aSLionel Sambuc uint64_t AddressPoint; 66*f4a2713aSLionel Sambuc if (VTTVT.getBase() == RD) { 67*f4a2713aSLionel Sambuc // Just get the address point for the regular vtable. 68*f4a2713aSLionel Sambuc AddressPoint = 69*f4a2713aSLionel Sambuc ItaniumVTContext.getVTableLayout(RD).getAddressPoint(i->VTableBase); 70*f4a2713aSLionel Sambuc assert(AddressPoint != 0 && "Did not find vtable address point!"); 71*f4a2713aSLionel Sambuc } else { 72*f4a2713aSLionel Sambuc AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase); 73*f4a2713aSLionel Sambuc assert(AddressPoint != 0 && "Did not find ctor vtable address point!"); 74*f4a2713aSLionel Sambuc } 75*f4a2713aSLionel Sambuc 76*f4a2713aSLionel Sambuc llvm::Value *Idxs[] = { 77*f4a2713aSLionel Sambuc llvm::ConstantInt::get(Int64Ty, 0), 78*f4a2713aSLionel Sambuc llvm::ConstantInt::get(Int64Ty, AddressPoint) 79*f4a2713aSLionel Sambuc }; 80*f4a2713aSLionel Sambuc 81*f4a2713aSLionel Sambuc llvm::Constant *Init = 82*f4a2713aSLionel Sambuc llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Idxs); 83*f4a2713aSLionel Sambuc 84*f4a2713aSLionel Sambuc Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy); 85*f4a2713aSLionel Sambuc 86*f4a2713aSLionel Sambuc VTTComponents.push_back(Init); 87*f4a2713aSLionel Sambuc } 88*f4a2713aSLionel Sambuc 89*f4a2713aSLionel Sambuc llvm::Constant *Init = llvm::ConstantArray::get(ArrayType, VTTComponents); 90*f4a2713aSLionel Sambuc 91*f4a2713aSLionel Sambuc VTT->setInitializer(Init); 92*f4a2713aSLionel Sambuc 93*f4a2713aSLionel Sambuc // Set the correct linkage. 94*f4a2713aSLionel Sambuc VTT->setLinkage(Linkage); 95*f4a2713aSLionel Sambuc 96*f4a2713aSLionel Sambuc // Set the right visibility. 97*f4a2713aSLionel Sambuc CGM.setTypeVisibility(VTT, RD, CodeGenModule::TVK_ForVTT); 98*f4a2713aSLionel Sambuc } 99*f4a2713aSLionel Sambuc 100*f4a2713aSLionel Sambuc llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) { 101*f4a2713aSLionel Sambuc assert(RD->getNumVBases() && "Only classes with virtual bases need a VTT"); 102*f4a2713aSLionel Sambuc 103*f4a2713aSLionel Sambuc SmallString<256> OutName; 104*f4a2713aSLionel Sambuc llvm::raw_svector_ostream Out(OutName); 105*f4a2713aSLionel Sambuc cast<ItaniumMangleContext>(CGM.getCXXABI().getMangleContext()) 106*f4a2713aSLionel Sambuc .mangleCXXVTT(RD, Out); 107*f4a2713aSLionel Sambuc Out.flush(); 108*f4a2713aSLionel Sambuc StringRef Name = OutName.str(); 109*f4a2713aSLionel Sambuc 110*f4a2713aSLionel Sambuc // This will also defer the definition of the VTT. 111*f4a2713aSLionel Sambuc (void) CGM.getCXXABI().getAddrOfVTable(RD, CharUnits()); 112*f4a2713aSLionel Sambuc 113*f4a2713aSLionel Sambuc VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); 114*f4a2713aSLionel Sambuc 115*f4a2713aSLionel Sambuc llvm::ArrayType *ArrayType = 116*f4a2713aSLionel Sambuc llvm::ArrayType::get(CGM.Int8PtrTy, Builder.getVTTComponents().size()); 117*f4a2713aSLionel Sambuc 118*f4a2713aSLionel Sambuc llvm::GlobalVariable *GV = 119*f4a2713aSLionel Sambuc CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, 120*f4a2713aSLionel Sambuc llvm::GlobalValue::ExternalLinkage); 121*f4a2713aSLionel Sambuc GV->setUnnamedAddr(true); 122*f4a2713aSLionel Sambuc return GV; 123*f4a2713aSLionel Sambuc } 124*f4a2713aSLionel Sambuc 125*f4a2713aSLionel Sambuc uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD, 126*f4a2713aSLionel Sambuc BaseSubobject Base) { 127*f4a2713aSLionel Sambuc BaseSubobjectPairTy ClassSubobjectPair(RD, Base); 128*f4a2713aSLionel Sambuc 129*f4a2713aSLionel Sambuc SubVTTIndiciesMapTy::iterator I = SubVTTIndicies.find(ClassSubobjectPair); 130*f4a2713aSLionel Sambuc if (I != SubVTTIndicies.end()) 131*f4a2713aSLionel Sambuc return I->second; 132*f4a2713aSLionel Sambuc 133*f4a2713aSLionel Sambuc VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); 134*f4a2713aSLionel Sambuc 135*f4a2713aSLionel Sambuc for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = 136*f4a2713aSLionel Sambuc Builder.getSubVTTIndicies().begin(), 137*f4a2713aSLionel Sambuc E = Builder.getSubVTTIndicies().end(); I != E; ++I) { 138*f4a2713aSLionel Sambuc // Insert all indices. 139*f4a2713aSLionel Sambuc BaseSubobjectPairTy ClassSubobjectPair(RD, I->first); 140*f4a2713aSLionel Sambuc 141*f4a2713aSLionel Sambuc SubVTTIndicies.insert(std::make_pair(ClassSubobjectPair, I->second)); 142*f4a2713aSLionel Sambuc } 143*f4a2713aSLionel Sambuc 144*f4a2713aSLionel Sambuc I = SubVTTIndicies.find(ClassSubobjectPair); 145*f4a2713aSLionel Sambuc assert(I != SubVTTIndicies.end() && "Did not find index!"); 146*f4a2713aSLionel Sambuc 147*f4a2713aSLionel Sambuc return I->second; 148*f4a2713aSLionel Sambuc } 149*f4a2713aSLionel Sambuc 150*f4a2713aSLionel Sambuc uint64_t 151*f4a2713aSLionel Sambuc CodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD, 152*f4a2713aSLionel Sambuc BaseSubobject Base) { 153*f4a2713aSLionel Sambuc SecondaryVirtualPointerIndicesMapTy::iterator I = 154*f4a2713aSLionel Sambuc SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base)); 155*f4a2713aSLionel Sambuc 156*f4a2713aSLionel Sambuc if (I != SecondaryVirtualPointerIndices.end()) 157*f4a2713aSLionel Sambuc return I->second; 158*f4a2713aSLionel Sambuc 159*f4a2713aSLionel Sambuc VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); 160*f4a2713aSLionel Sambuc 161*f4a2713aSLionel Sambuc // Insert all secondary vpointer indices. 162*f4a2713aSLionel Sambuc for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = 163*f4a2713aSLionel Sambuc Builder.getSecondaryVirtualPointerIndices().begin(), 164*f4a2713aSLionel Sambuc E = Builder.getSecondaryVirtualPointerIndices().end(); I != E; ++I) { 165*f4a2713aSLionel Sambuc std::pair<const CXXRecordDecl *, BaseSubobject> Pair = 166*f4a2713aSLionel Sambuc std::make_pair(RD, I->first); 167*f4a2713aSLionel Sambuc 168*f4a2713aSLionel Sambuc SecondaryVirtualPointerIndices.insert(std::make_pair(Pair, I->second)); 169*f4a2713aSLionel Sambuc } 170*f4a2713aSLionel Sambuc 171*f4a2713aSLionel Sambuc I = SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base)); 172*f4a2713aSLionel Sambuc assert(I != SecondaryVirtualPointerIndices.end() && "Did not find index!"); 173*f4a2713aSLionel Sambuc 174*f4a2713aSLionel Sambuc return I->second; 175*f4a2713aSLionel Sambuc } 176*f4a2713aSLionel Sambuc 177