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