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