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