xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/CodeGen/CGVTT.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
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