17330f729Sjoerg //===--- CGVTT.cpp - Emit LLVM Code for C++ VTTs --------------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This contains code dealing with C++ code generation of VTTs (vtable tables).
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg
137330f729Sjoerg #include "CodeGenModule.h"
147330f729Sjoerg #include "CGCXXABI.h"
157330f729Sjoerg #include "clang/AST/RecordLayout.h"
167330f729Sjoerg #include "clang/AST/VTTBuilder.h"
177330f729Sjoerg using namespace clang;
187330f729Sjoerg using namespace CodeGen;
197330f729Sjoerg
207330f729Sjoerg static llvm::GlobalVariable *
GetAddrOfVTTVTable(CodeGenVTables & CGVT,CodeGenModule & CGM,const CXXRecordDecl * MostDerivedClass,const VTTVTable & VTable,llvm::GlobalVariable::LinkageTypes Linkage,VTableLayout::AddressPointsMapTy & AddressPoints)217330f729Sjoerg GetAddrOfVTTVTable(CodeGenVTables &CGVT, CodeGenModule &CGM,
227330f729Sjoerg const CXXRecordDecl *MostDerivedClass,
237330f729Sjoerg const VTTVTable &VTable,
247330f729Sjoerg llvm::GlobalVariable::LinkageTypes Linkage,
257330f729Sjoerg VTableLayout::AddressPointsMapTy &AddressPoints) {
267330f729Sjoerg if (VTable.getBase() == MostDerivedClass) {
277330f729Sjoerg assert(VTable.getBaseOffset().isZero() &&
287330f729Sjoerg "Most derived class vtable must have a zero offset!");
297330f729Sjoerg // This is a regular vtable.
307330f729Sjoerg return CGM.getCXXABI().getAddrOfVTable(MostDerivedClass, CharUnits());
317330f729Sjoerg }
327330f729Sjoerg
337330f729Sjoerg return CGVT.GenerateConstructionVTable(MostDerivedClass,
347330f729Sjoerg VTable.getBaseSubobject(),
357330f729Sjoerg VTable.isVirtual(),
367330f729Sjoerg Linkage,
377330f729Sjoerg AddressPoints);
387330f729Sjoerg }
397330f729Sjoerg
407330f729Sjoerg void
EmitVTTDefinition(llvm::GlobalVariable * VTT,llvm::GlobalVariable::LinkageTypes Linkage,const CXXRecordDecl * RD)417330f729Sjoerg CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
427330f729Sjoerg llvm::GlobalVariable::LinkageTypes Linkage,
437330f729Sjoerg const CXXRecordDecl *RD) {
447330f729Sjoerg VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/true);
457330f729Sjoerg llvm::ArrayType *ArrayType =
46*e038c9c4Sjoerg llvm::ArrayType::get(CGM.Int8PtrTy, Builder.getVTTComponents().size());
477330f729Sjoerg
487330f729Sjoerg SmallVector<llvm::GlobalVariable *, 8> VTables;
497330f729Sjoerg SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints;
507330f729Sjoerg for (const VTTVTable *i = Builder.getVTTVTables().begin(),
517330f729Sjoerg *e = Builder.getVTTVTables().end(); i != e; ++i) {
527330f729Sjoerg VTableAddressPoints.push_back(VTableAddressPointsMapTy());
537330f729Sjoerg VTables.push_back(GetAddrOfVTTVTable(*this, CGM, RD, *i, Linkage,
547330f729Sjoerg VTableAddressPoints.back()));
557330f729Sjoerg }
567330f729Sjoerg
577330f729Sjoerg SmallVector<llvm::Constant *, 8> VTTComponents;
587330f729Sjoerg for (const VTTComponent *i = Builder.getVTTComponents().begin(),
597330f729Sjoerg *e = Builder.getVTTComponents().end(); i != e; ++i) {
607330f729Sjoerg const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex];
617330f729Sjoerg llvm::GlobalVariable *VTable = VTables[i->VTableIndex];
627330f729Sjoerg VTableLayout::AddressPointLocation AddressPoint;
637330f729Sjoerg if (VTTVT.getBase() == RD) {
647330f729Sjoerg // Just get the address point for the regular vtable.
657330f729Sjoerg AddressPoint =
667330f729Sjoerg getItaniumVTableContext().getVTableLayout(RD).getAddressPoint(
677330f729Sjoerg i->VTableBase);
687330f729Sjoerg } else {
697330f729Sjoerg AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase);
707330f729Sjoerg assert(AddressPoint.AddressPointIndex != 0 &&
717330f729Sjoerg "Did not find ctor vtable address point!");
727330f729Sjoerg }
737330f729Sjoerg
747330f729Sjoerg llvm::Value *Idxs[] = {
75*e038c9c4Sjoerg llvm::ConstantInt::get(CGM.Int32Ty, 0),
76*e038c9c4Sjoerg llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex),
77*e038c9c4Sjoerg llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex),
787330f729Sjoerg };
797330f729Sjoerg
807330f729Sjoerg llvm::Constant *Init = llvm::ConstantExpr::getGetElementPtr(
817330f729Sjoerg VTable->getValueType(), VTable, Idxs, /*InBounds=*/true,
827330f729Sjoerg /*InRangeIndex=*/1);
837330f729Sjoerg
84*e038c9c4Sjoerg Init = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(Init,
85*e038c9c4Sjoerg CGM.Int8PtrTy);
867330f729Sjoerg
877330f729Sjoerg VTTComponents.push_back(Init);
887330f729Sjoerg }
897330f729Sjoerg
907330f729Sjoerg llvm::Constant *Init = llvm::ConstantArray::get(ArrayType, VTTComponents);
917330f729Sjoerg
927330f729Sjoerg VTT->setInitializer(Init);
937330f729Sjoerg
947330f729Sjoerg // Set the correct linkage.
957330f729Sjoerg VTT->setLinkage(Linkage);
967330f729Sjoerg
977330f729Sjoerg if (CGM.supportsCOMDAT() && VTT->isWeakForLinker())
987330f729Sjoerg VTT->setComdat(CGM.getModule().getOrInsertComdat(VTT->getName()));
997330f729Sjoerg
1007330f729Sjoerg // Set the right visibility.
1017330f729Sjoerg CGM.setGVProperties(VTT, RD);
1027330f729Sjoerg }
1037330f729Sjoerg
GetAddrOfVTT(const CXXRecordDecl * RD)1047330f729Sjoerg llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) {
1057330f729Sjoerg assert(RD->getNumVBases() && "Only classes with virtual bases need a VTT");
1067330f729Sjoerg
1077330f729Sjoerg SmallString<256> OutName;
1087330f729Sjoerg llvm::raw_svector_ostream Out(OutName);
1097330f729Sjoerg cast<ItaniumMangleContext>(CGM.getCXXABI().getMangleContext())
1107330f729Sjoerg .mangleCXXVTT(RD, Out);
1117330f729Sjoerg StringRef Name = OutName.str();
1127330f729Sjoerg
1137330f729Sjoerg // This will also defer the definition of the VTT.
1147330f729Sjoerg (void) CGM.getCXXABI().getAddrOfVTable(RD, CharUnits());
1157330f729Sjoerg
1167330f729Sjoerg VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
1177330f729Sjoerg
1187330f729Sjoerg llvm::ArrayType *ArrayType =
1197330f729Sjoerg llvm::ArrayType::get(CGM.Int8PtrTy, Builder.getVTTComponents().size());
1207330f729Sjoerg unsigned Align = CGM.getDataLayout().getABITypeAlignment(CGM.Int8PtrTy);
1217330f729Sjoerg
1227330f729Sjoerg llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable(
1237330f729Sjoerg Name, ArrayType, llvm::GlobalValue::ExternalLinkage, Align);
1247330f729Sjoerg GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1257330f729Sjoerg return GV;
1267330f729Sjoerg }
1277330f729Sjoerg
getSubVTTIndex(const CXXRecordDecl * RD,BaseSubobject Base)1287330f729Sjoerg uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD,
1297330f729Sjoerg BaseSubobject Base) {
1307330f729Sjoerg BaseSubobjectPairTy ClassSubobjectPair(RD, Base);
1317330f729Sjoerg
1327330f729Sjoerg SubVTTIndiciesMapTy::iterator I = SubVTTIndicies.find(ClassSubobjectPair);
1337330f729Sjoerg if (I != SubVTTIndicies.end())
1347330f729Sjoerg return I->second;
1357330f729Sjoerg
1367330f729Sjoerg VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
1377330f729Sjoerg
1387330f729Sjoerg for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I =
1397330f729Sjoerg Builder.getSubVTTIndicies().begin(),
1407330f729Sjoerg E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
1417330f729Sjoerg // Insert all indices.
1427330f729Sjoerg BaseSubobjectPairTy ClassSubobjectPair(RD, I->first);
1437330f729Sjoerg
1447330f729Sjoerg SubVTTIndicies.insert(std::make_pair(ClassSubobjectPair, I->second));
1457330f729Sjoerg }
1467330f729Sjoerg
1477330f729Sjoerg I = SubVTTIndicies.find(ClassSubobjectPair);
1487330f729Sjoerg assert(I != SubVTTIndicies.end() && "Did not find index!");
1497330f729Sjoerg
1507330f729Sjoerg return I->second;
1517330f729Sjoerg }
1527330f729Sjoerg
1537330f729Sjoerg uint64_t
getSecondaryVirtualPointerIndex(const CXXRecordDecl * RD,BaseSubobject Base)1547330f729Sjoerg CodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD,
1557330f729Sjoerg BaseSubobject Base) {
1567330f729Sjoerg SecondaryVirtualPointerIndicesMapTy::iterator I =
1577330f729Sjoerg SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base));
1587330f729Sjoerg
1597330f729Sjoerg if (I != SecondaryVirtualPointerIndices.end())
1607330f729Sjoerg return I->second;
1617330f729Sjoerg
1627330f729Sjoerg VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false);
1637330f729Sjoerg
1647330f729Sjoerg // Insert all secondary vpointer indices.
1657330f729Sjoerg for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I =
1667330f729Sjoerg Builder.getSecondaryVirtualPointerIndices().begin(),
1677330f729Sjoerg E = Builder.getSecondaryVirtualPointerIndices().end(); I != E; ++I) {
1687330f729Sjoerg std::pair<const CXXRecordDecl *, BaseSubobject> Pair =
1697330f729Sjoerg std::make_pair(RD, I->first);
1707330f729Sjoerg
1717330f729Sjoerg SecondaryVirtualPointerIndices.insert(std::make_pair(Pair, I->second));
1727330f729Sjoerg }
1737330f729Sjoerg
1747330f729Sjoerg I = SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base));
1757330f729Sjoerg assert(I != SecondaryVirtualPointerIndices.end() && "Did not find index!");
1767330f729Sjoerg
1777330f729Sjoerg return I->second;
1787330f729Sjoerg }
179