diff options
Diffstat (limited to 'clang/lib/CodeGen/CGVTT.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGVTT.cpp | 179 | 
1 files changed, 179 insertions, 0 deletions
| diff --git a/clang/lib/CodeGen/CGVTT.cpp b/clang/lib/CodeGen/CGVTT.cpp new file mode 100644 index 000000000000..e79f3f3dd8bc --- /dev/null +++ b/clang/lib/CodeGen/CGVTT.cpp @@ -0,0 +1,179 @@ +//===--- CGVTT.cpp - Emit LLVM Code for C++ VTTs --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This contains code dealing with C++ code generation of VTTs (vtable tables). +// +//===----------------------------------------------------------------------===// + +#include "CodeGenModule.h" +#include "CGCXXABI.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/VTTBuilder.h" +using namespace clang; +using namespace CodeGen; + +static llvm::GlobalVariable * +GetAddrOfVTTVTable(CodeGenVTables &CGVT, CodeGenModule &CGM, +                   const CXXRecordDecl *MostDerivedClass, +                   const VTTVTable &VTable, +                   llvm::GlobalVariable::LinkageTypes Linkage, +                   VTableLayout::AddressPointsMapTy &AddressPoints) { +  if (VTable.getBase() == MostDerivedClass) { +    assert(VTable.getBaseOffset().isZero() && +           "Most derived class vtable must have a zero offset!"); +    // This is a regular vtable. +    return CGM.getCXXABI().getAddrOfVTable(MostDerivedClass, CharUnits()); +  } + +  return CGVT.GenerateConstructionVTable(MostDerivedClass, +                                         VTable.getBaseSubobject(), +                                         VTable.isVirtual(), +                                         Linkage, +                                         AddressPoints); +} + +void +CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, +                                  llvm::GlobalVariable::LinkageTypes Linkage, +                                  const CXXRecordDecl *RD) { +  VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/true); + +  llvm::Type *Int8PtrTy = CGM.Int8PtrTy, *Int32Ty = CGM.Int32Ty; +  llvm::ArrayType *ArrayType = +    llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size()); + +  SmallVector<llvm::GlobalVariable *, 8> VTables; +  SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints; +  for (const VTTVTable *i = Builder.getVTTVTables().begin(), +                       *e = Builder.getVTTVTables().end(); i != e; ++i) { +    VTableAddressPoints.push_back(VTableAddressPointsMapTy()); +    VTables.push_back(GetAddrOfVTTVTable(*this, CGM, RD, *i, Linkage, +                                         VTableAddressPoints.back())); +  } + +  SmallVector<llvm::Constant *, 8> VTTComponents; +  for (const VTTComponent *i = Builder.getVTTComponents().begin(), +                          *e = Builder.getVTTComponents().end(); i != e; ++i) { +    const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex]; +    llvm::GlobalVariable *VTable = VTables[i->VTableIndex]; +    VTableLayout::AddressPointLocation AddressPoint; +    if (VTTVT.getBase() == RD) { +      // Just get the address point for the regular vtable. +      AddressPoint = +          getItaniumVTableContext().getVTableLayout(RD).getAddressPoint( +              i->VTableBase); +    } else { +      AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase); +      assert(AddressPoint.AddressPointIndex != 0 && +             "Did not find ctor vtable address point!"); +    } + +     llvm::Value *Idxs[] = { +       llvm::ConstantInt::get(Int32Ty, 0), +       llvm::ConstantInt::get(Int32Ty, AddressPoint.VTableIndex), +       llvm::ConstantInt::get(Int32Ty, AddressPoint.AddressPointIndex), +     }; + +     llvm::Constant *Init = llvm::ConstantExpr::getGetElementPtr( +         VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, +         /*InRangeIndex=*/1); + +     Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy); + +     VTTComponents.push_back(Init); +  } + +  llvm::Constant *Init = llvm::ConstantArray::get(ArrayType, VTTComponents); + +  VTT->setInitializer(Init); + +  // Set the correct linkage. +  VTT->setLinkage(Linkage); + +  if (CGM.supportsCOMDAT() && VTT->isWeakForLinker()) +    VTT->setComdat(CGM.getModule().getOrInsertComdat(VTT->getName())); + +  // Set the right visibility. +  CGM.setGVProperties(VTT, RD); +} + +llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) { +  assert(RD->getNumVBases() && "Only classes with virtual bases need a VTT"); + +  SmallString<256> OutName; +  llvm::raw_svector_ostream Out(OutName); +  cast<ItaniumMangleContext>(CGM.getCXXABI().getMangleContext()) +      .mangleCXXVTT(RD, Out); +  StringRef Name = OutName.str(); + +  // This will also defer the definition of the VTT. +  (void) CGM.getCXXABI().getAddrOfVTable(RD, CharUnits()); + +  VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); + +  llvm::ArrayType *ArrayType = +    llvm::ArrayType::get(CGM.Int8PtrTy, Builder.getVTTComponents().size()); +  unsigned Align = CGM.getDataLayout().getABITypeAlignment(CGM.Int8PtrTy); + +  llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable( +      Name, ArrayType, llvm::GlobalValue::ExternalLinkage, Align); +  GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); +  return GV; +} + +uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD, +                                        BaseSubobject Base) { +  BaseSubobjectPairTy ClassSubobjectPair(RD, Base); + +  SubVTTIndiciesMapTy::iterator I = SubVTTIndicies.find(ClassSubobjectPair); +  if (I != SubVTTIndicies.end()) +    return I->second; + +  VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); + +  for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = +       Builder.getSubVTTIndicies().begin(), +       E = Builder.getSubVTTIndicies().end(); I != E; ++I) { +    // Insert all indices. +    BaseSubobjectPairTy ClassSubobjectPair(RD, I->first); + +    SubVTTIndicies.insert(std::make_pair(ClassSubobjectPair, I->second)); +  } + +  I = SubVTTIndicies.find(ClassSubobjectPair); +  assert(I != SubVTTIndicies.end() && "Did not find index!"); + +  return I->second; +} + +uint64_t +CodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD, +                                                BaseSubobject Base) { +  SecondaryVirtualPointerIndicesMapTy::iterator I = +    SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base)); + +  if (I != SecondaryVirtualPointerIndices.end()) +    return I->second; + +  VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); + +  // Insert all secondary vpointer indices. +  for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = +       Builder.getSecondaryVirtualPointerIndices().begin(), +       E = Builder.getSecondaryVirtualPointerIndices().end(); I != E; ++I) { +    std::pair<const CXXRecordDecl *, BaseSubobject> Pair = +      std::make_pair(RD, I->first); + +    SecondaryVirtualPointerIndices.insert(std::make_pair(Pair, I->second)); +  } + +  I = SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base)); +  assert(I != SecondaryVirtualPointerIndices.end() && "Did not find index!"); + +  return I->second; +} | 
