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