Home | History | Annotate | Download | only in AST
      1 //===--- VTTBuilder.cpp - C++ VTT layout builder --------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This contains code dealing with generation of the layout of virtual table
     11 // tables (VTT).
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "clang/AST/VTTBuilder.h"
     16 #include "clang/AST/CXXInheritance.h"
     17 #include "clang/AST/RecordLayout.h"
     18 #include "clang/Basic/TargetInfo.h"
     19 #include "llvm/Support/Format.h"
     20 #include <algorithm>
     21 #include <cstdio>
     22 
     23 using namespace clang;
     24 
     25 #define DUMP_OVERRIDERS 0
     26 
     27 VTTBuilder::VTTBuilder(ASTContext &Ctx,
     28                        const CXXRecordDecl *MostDerivedClass,
     29                        bool GenerateDefinition)
     30   : Ctx(Ctx), MostDerivedClass(MostDerivedClass),
     31   MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)),
     32     GenerateDefinition(GenerateDefinition) {
     33   // Lay out this VTT.
     34   LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
     35             /*BaseIsVirtual=*/false);
     36 }
     37 
     38 void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
     39                                   const CXXRecordDecl *VTableClass) {
     40   // Store the vtable pointer index if we're generating the primary VTT.
     41   if (VTableClass == MostDerivedClass) {
     42     assert(!SecondaryVirtualPointerIndices.count(Base) &&
     43            "A virtual pointer index already exists for this base subobject!");
     44     SecondaryVirtualPointerIndices[Base] = VTTComponents.size();
     45   }
     46 
     47   if (!GenerateDefinition) {
     48     VTTComponents.push_back(VTTComponent());
     49     return;
     50   }
     51 
     52   VTTComponents.push_back(VTTComponent(VTableIndex, Base));
     53 }
     54 
     55 void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
     56   const CXXRecordDecl *RD = Base.getBase();
     57 
     58   for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
     59        E = RD->bases_end(); I != E; ++I) {
     60 
     61     // Don't layout virtual bases.
     62     if (I->isVirtual())
     63         continue;
     64 
     65     const CXXRecordDecl *BaseDecl =
     66       cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
     67 
     68     const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
     69     CharUnits BaseOffset = Base.getBaseOffset() +
     70       Layout.getBaseClassOffset(BaseDecl);
     71 
     72     // Layout the VTT for this base.
     73     LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
     74   }
     75 }
     76 
     77 void
     78 VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
     79                                            bool BaseIsMorallyVirtual,
     80                                            uint64_t VTableIndex,
     81                                            const CXXRecordDecl *VTableClass,
     82                                            VisitedVirtualBasesSetTy &VBases) {
     83   const CXXRecordDecl *RD = Base.getBase();
     84 
     85   // We're not interested in bases that don't have virtual bases, and not
     86   // morally virtual bases.
     87   if (!RD->getNumVBases() && !BaseIsMorallyVirtual)
     88     return;
     89 
     90   for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
     91        E = RD->bases_end(); I != E; ++I) {
     92     const CXXRecordDecl *BaseDecl =
     93       cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
     94 
     95     // Itanium C++ ABI 2.6.2:
     96     //   Secondary virtual pointers are present for all bases with either
     97     //   virtual bases or virtual function declarations overridden along a
     98     //   virtual path.
     99     //
    100     // If the base class is not dynamic, we don't want to add it, nor any
    101     // of its base classes.
    102     if (!BaseDecl->isDynamicClass())
    103       continue;
    104 
    105     bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual;
    106     bool BaseDeclIsNonVirtualPrimaryBase = false;
    107     CharUnits BaseOffset;
    108     if (I->isVirtual()) {
    109       // Ignore virtual bases that we've already visited.
    110       if (!VBases.insert(BaseDecl))
    111         continue;
    112 
    113       BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
    114       BaseDeclIsMorallyVirtual = true;
    115     } else {
    116       const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
    117 
    118       BaseOffset = Base.getBaseOffset() +
    119         Layout.getBaseClassOffset(BaseDecl);
    120 
    121       if (!Layout.isPrimaryBaseVirtual() &&
    122           Layout.getPrimaryBase() == BaseDecl)
    123         BaseDeclIsNonVirtualPrimaryBase = true;
    124     }
    125 
    126     // Itanium C++ ABI 2.6.2:
    127     //   Secondary virtual pointers: for each base class X which (a) has virtual
    128     //   bases or is reachable along a virtual path from D, and (b) is not a
    129     //   non-virtual primary base, the address of the virtual table for X-in-D
    130     //   or an appropriate construction virtual table.
    131     if (!BaseDeclIsNonVirtualPrimaryBase &&
    132         (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) {
    133       // Add the vtable pointer.
    134       AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTableIndex,
    135                        VTableClass);
    136     }
    137 
    138     // And lay out the secondary virtual pointers for the base class.
    139     LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset),
    140                                    BaseDeclIsMorallyVirtual, VTableIndex,
    141                                    VTableClass, VBases);
    142   }
    143 }
    144 
    145 void
    146 VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
    147                                            uint64_t VTableIndex) {
    148   VisitedVirtualBasesSetTy VBases;
    149   LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false,
    150                                  VTableIndex, Base.getBase(), VBases);
    151 }
    152 
    153 void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
    154                                    VisitedVirtualBasesSetTy &VBases) {
    155   for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
    156        E = RD->bases_end(); I != E; ++I) {
    157     const CXXRecordDecl *BaseDecl =
    158       cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
    159 
    160     // Check if this is a virtual base.
    161     if (I->isVirtual()) {
    162       // Check if we've seen this base before.
    163       if (!VBases.insert(BaseDecl))
    164         continue;
    165 
    166       CharUnits BaseOffset =
    167         MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
    168 
    169       LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true);
    170     }
    171 
    172     // We only need to layout virtual VTTs for this base if it actually has
    173     // virtual bases.
    174     if (BaseDecl->getNumVBases())
    175       LayoutVirtualVTTs(BaseDecl, VBases);
    176   }
    177 }
    178 
    179 void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
    180   const CXXRecordDecl *RD = Base.getBase();
    181 
    182   // Itanium C++ ABI 2.6.2:
    183   //   An array of virtual table addresses, called the VTT, is declared for
    184   //   each class type that has indirect or direct virtual base classes.
    185   if (RD->getNumVBases() == 0)
    186     return;
    187 
    188   bool IsPrimaryVTT = Base.getBase() == MostDerivedClass;
    189 
    190   if (!IsPrimaryVTT) {
    191     // Remember the sub-VTT index.
    192     SubVTTIndicies[Base] = VTTComponents.size();
    193   }
    194 
    195   uint64_t VTableIndex = VTTVTables.size();
    196   VTTVTables.push_back(VTTVTable(Base, BaseIsVirtual));
    197 
    198   // Add the primary vtable pointer.
    199   AddVTablePointer(Base, VTableIndex, RD);
    200 
    201   // Add the secondary VTTs.
    202   LayoutSecondaryVTTs(Base);
    203 
    204   // Add the secondary virtual pointers.
    205   LayoutSecondaryVirtualPointers(Base, VTableIndex);
    206 
    207   // If this is the primary VTT, we want to lay out virtual VTTs as well.
    208   if (IsPrimaryVTT) {
    209     VisitedVirtualBasesSetTy VBases;
    210     LayoutVirtualVTTs(Base.getBase(), VBases);
    211   }
    212 }
    213