CGVTT.cpp revision 226633
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
21202879Srdivacky#define D1(x)
22202879Srdivacky
23226633Sdimllvm::Constant *GetAddrOfVTTVTable(CodeGenVTables &CGVT,
24226633Sdim                                   const CXXRecordDecl *MostDerivedClass,
25226633Sdim                                   const VTTVTable &VTable,
26226633Sdim                                   llvm::GlobalVariable::LinkageTypes Linkage,
27226633Sdim                       llvm::DenseMap<BaseSubobject, uint64_t> &AddressPoints) {
28226633Sdim  if (VTable.getBase() == MostDerivedClass) {
29226633Sdim    assert(VTable.getBaseOffset().isZero() &&
30206084Srdivacky           "Most derived class vtable must have a zero offset!");
31206084Srdivacky    // This is a regular vtable.
32226633Sdim    return CGVT.GetAddrOfVTable(MostDerivedClass);
33206084Srdivacky  }
34206084Srdivacky
35226633Sdim  return CGVT.GenerateConstructionVTable(MostDerivedClass,
36226633Sdim                                         VTable.getBaseSubobject(),
37226633Sdim                                         VTable.isVirtual(),
38226633Sdim                                         Linkage,
39226633Sdim                                         AddressPoints);
40206084Srdivacky}
41202879Srdivacky
42226633Sdimvoid
43226633SdimCodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
44226633Sdim                                  llvm::GlobalVariable::LinkageTypes Linkage,
45226633Sdim                                  const CXXRecordDecl *RD) {
46226633Sdim  VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/true);
47206084Srdivacky
48226633Sdim  llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()),
49226633Sdim             *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext());
50226633Sdim  llvm::ArrayType *ArrayType =
51226633Sdim    llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size());
52206084Srdivacky
53226633Sdim  SmallVector<llvm::Constant *, 8> VTables;
54226633Sdim  SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints;
55226633Sdim  for (const VTTVTable *i = Builder.getVTTVTables().begin(),
56226633Sdim                       *e = Builder.getVTTVTables().end(); i != e; ++i) {
57226633Sdim    VTableAddressPoints.push_back(VTableAddressPointsMapTy());
58226633Sdim    VTables.push_back(GetAddrOfVTTVTable(*this, RD, *i, Linkage,
59226633Sdim                                         VTableAddressPoints.back()));
60202879Srdivacky  }
61202879Srdivacky
62226633Sdim  SmallVector<llvm::Constant *, 8> VTTComponents;
63226633Sdim  for (const VTTComponent *i = Builder.getVTTComponents().begin(),
64226633Sdim                          *e = Builder.getVTTComponents().end(); i != e; ++i) {
65226633Sdim    const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex];
66226633Sdim    llvm::Constant *VTable = VTables[i->VTableIndex];
67226633Sdim    uint64_t AddressPoint;
68226633Sdim    if (VTTVT.getBase() == RD) {
69226633Sdim      // Just get the address point for the regular vtable.
70226633Sdim      AddressPoint = VTContext.getVTableLayout(RD)
71226633Sdim                              .getAddressPoint(i->VTableBase);
72226633Sdim      assert(AddressPoint != 0 && "Did not find vtable address point!");
73206084Srdivacky    } else {
74226633Sdim      AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase);
75226633Sdim      assert(AddressPoint != 0 && "Did not find ctor vtable address point!");
76202879Srdivacky    }
77202879Srdivacky
78226633Sdim     llvm::Value *Idxs[] = {
79226633Sdim       llvm::ConstantInt::get(Int64Ty, 0),
80226633Sdim       llvm::ConstantInt::get(Int64Ty, AddressPoint)
81226633Sdim     };
82202879Srdivacky
83226633Sdim     llvm::Constant *Init =
84226633Sdim       llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Idxs);
85202879Srdivacky
86226633Sdim     Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
87202879Srdivacky
88226633Sdim     VTTComponents.push_back(Init);
89202879Srdivacky  }
90202879Srdivacky
91226633Sdim  llvm::Constant *Init = llvm::ConstantArray::get(ArrayType, VTTComponents);
92202879Srdivacky
93218893Sdim  VTT->setInitializer(Init);
94202879Srdivacky
95218893Sdim  // Set the correct linkage.
96218893Sdim  VTT->setLinkage(Linkage);
97202879Srdivacky
98218893Sdim  // Set the right visibility.
99218893Sdim  CGM.setTypeVisibility(VTT, RD, CodeGenModule::TVK_ForVTT);
100218893Sdim}
101202879Srdivacky
102218893Sdimllvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
103218893Sdim  assert(RD->getNumVBases() && "Only classes with virtual bases need a VTT");
104206084Srdivacky
105218893Sdim  llvm::SmallString<256> OutName;
106218893Sdim  llvm::raw_svector_ostream Out(OutName);
107218893Sdim  CGM.getCXXABI().getMangleContext().mangleCXXVTT(RD, Out);
108218893Sdim  Out.flush();
109226633Sdim  StringRef Name = OutName.str();
110202879Srdivacky
111226633Sdim  // This will also defer the definition of the VTT.
112226633Sdim  (void) GetAddrOfVTable(RD);
113223017Sdim
114226633Sdim  VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
115218893Sdim
116226633Sdim  llvm::Type *Int8PtrTy =
117218893Sdim    llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
118226633Sdim  llvm::ArrayType *ArrayType =
119218893Sdim    llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size());
120218893Sdim
121218893Sdim  llvm::GlobalVariable *GV =
122218893Sdim    CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,
123218893Sdim                                          llvm::GlobalValue::ExternalLinkage);
124218893Sdim  GV->setUnnamedAddr(true);
125202879Srdivacky  return GV;
126202879Srdivacky}
127202879Srdivacky
128206084Srdivackybool CodeGenVTables::needsVTTParameter(GlobalDecl GD) {
129202879Srdivacky  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
130202879Srdivacky
131202879Srdivacky  // We don't have any virtual bases, just return early.
132202879Srdivacky  if (!MD->getParent()->getNumVBases())
133202879Srdivacky    return false;
134202879Srdivacky
135202879Srdivacky  // Check if we have a base constructor.
136202879Srdivacky  if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
137202879Srdivacky    return true;
138202879Srdivacky
139202879Srdivacky  // Check if we have a base destructor.
140202879Srdivacky  if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
141202879Srdivacky    return true;
142202879Srdivacky
143202879Srdivacky  return false;
144202879Srdivacky}
145202879Srdivacky
146206084Srdivackyuint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD,
147207619Srdivacky                                        BaseSubobject Base) {
148207619Srdivacky  BaseSubobjectPairTy ClassSubobjectPair(RD, Base);
149202879Srdivacky
150207619Srdivacky  SubVTTIndiciesMapTy::iterator I = SubVTTIndicies.find(ClassSubobjectPair);
151202879Srdivacky  if (I != SubVTTIndicies.end())
152202879Srdivacky    return I->second;
153202879Srdivacky
154226633Sdim  VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
155202879Srdivacky
156207619Srdivacky  for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I =
157202879Srdivacky       Builder.getSubVTTIndicies().begin(),
158202879Srdivacky       E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
159202879Srdivacky    // Insert all indices.
160207619Srdivacky    BaseSubobjectPairTy ClassSubobjectPair(RD, I->first);
161202879Srdivacky
162207619Srdivacky    SubVTTIndicies.insert(std::make_pair(ClassSubobjectPair, I->second));
163202879Srdivacky  }
164202879Srdivacky
165207619Srdivacky  I = SubVTTIndicies.find(ClassSubobjectPair);
166202879Srdivacky  assert(I != SubVTTIndicies.end() && "Did not find index!");
167202879Srdivacky
168202879Srdivacky  return I->second;
169202879Srdivacky}
170206084Srdivacky
171206084Srdivackyuint64_t
172206084SrdivackyCodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD,
173206084Srdivacky                                                BaseSubobject Base) {
174206084Srdivacky  SecondaryVirtualPointerIndicesMapTy::iterator I =
175206084Srdivacky    SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base));
176206084Srdivacky
177206084Srdivacky  if (I != SecondaryVirtualPointerIndices.end())
178206084Srdivacky    return I->second;
179206084Srdivacky
180226633Sdim  VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
181206084Srdivacky
182206084Srdivacky  // Insert all secondary vpointer indices.
183206084Srdivacky  for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I =
184206084Srdivacky       Builder.getSecondaryVirtualPointerIndices().begin(),
185206084Srdivacky       E = Builder.getSecondaryVirtualPointerIndices().end(); I != E; ++I) {
186206084Srdivacky    std::pair<const CXXRecordDecl *, BaseSubobject> Pair =
187206084Srdivacky      std::make_pair(RD, I->first);
188206084Srdivacky
189206084Srdivacky    SecondaryVirtualPointerIndices.insert(std::make_pair(Pair, I->second));
190206084Srdivacky  }
191206084Srdivacky
192206084Srdivacky  I = SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base));
193206084Srdivacky  assert(I != SecondaryVirtualPointerIndices.end() && "Did not find index!");
194206084Srdivacky
195206084Srdivacky  return I->second;
196206084Srdivacky}
197206084Srdivacky
198