xref: /minix3/external/bsd/llvm/dist/clang/lib/CodeGen/CGVTT.cpp (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
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