VTTBuilder.cpp revision 239462
11541Srgrimes//===--- VTTBuilder.cpp - C++ VTT layout builder --------------------------===//
21541Srgrimes//
31541Srgrimes//                     The LLVM Compiler Infrastructure
41541Srgrimes//
517703Ssmpatel// This file is distributed under the University of Illinois Open Source
61541Srgrimes// License. See LICENSE.TXT for details.
71541Srgrimes//
811295Sswallace//===----------------------------------------------------------------------===//
91541Srgrimes//
1011295Sswallace// This contains code dealing with generation of the layout of virtual table
112257Ssos// tables (VTT).
1210907Sbde//
131541Srgrimes//===----------------------------------------------------------------------===//
141541Srgrimes
1510907Sbde#include "clang/AST/VTTBuilder.h"
161541Srgrimes#include "clang/AST/ASTContext.h"
1710907Sbde#include "clang/AST/CXXInheritance.h"
181541Srgrimes#include "clang/AST/RecordLayout.h"
191541Srgrimes#include "clang/Basic/TargetInfo.h"
2010907Sbde#include "llvm/Support/Format.h"
211541Srgrimes#include <algorithm>
2210907Sbde#include <cstdio>
2310907Sbde
2410907Sbdeusing namespace clang;
2510907Sbde
2610907Sbde#define DUMP_OVERRIDERS 0
2710907Sbde
2810907SbdeVTTBuilder::VTTBuilder(ASTContext &Ctx,
2910907Sbde                       const CXXRecordDecl *MostDerivedClass,
301541Srgrimes                       bool GenerateDefinition)
3110907Sbde  : Ctx(Ctx), MostDerivedClass(MostDerivedClass),
3210907Sbde  MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)),
3310907Sbde    GenerateDefinition(GenerateDefinition) {
3410907Sbde  // Lay out this VTT.
3510907Sbde  LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()),
3610907Sbde            /*BaseIsVirtual=*/false);
3710907Sbde}
3810907Sbde
3910907Sbdevoid VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
4010907Sbde                                  const CXXRecordDecl *VTableClass) {
411541Srgrimes  // Store the vtable pointer index if we're generating the primary VTT.
4210907Sbde  if (VTableClass == MostDerivedClass) {
4310907Sbde    assert(!SecondaryVirtualPointerIndices.count(Base) &&
4410907Sbde           "A virtual pointer index already exists for this base subobject!");
4510907Sbde    SecondaryVirtualPointerIndices[Base] = VTTComponents.size();
4610907Sbde  }
4710907Sbde
4810907Sbde  if (!GenerateDefinition) {
4910907Sbde    VTTComponents.push_back(VTTComponent());
5010907Sbde    return;
5110907Sbde  }
5210907Sbde
5311295Sswallace  VTTComponents.push_back(VTTComponent(VTableIndex, Base));
5411295Sswallace}
5510907Sbde
5610907Sbdevoid VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
5710907Sbde  const CXXRecordDecl *RD = Base.getBase();
5810907Sbde
5910907Sbde  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
601541Srgrimes       E = RD->bases_end(); I != E; ++I) {
6110907Sbde
621541Srgrimes    // Don't layout virtual bases.
6311295Sswallace    if (I->isVirtual())
6410907Sbde        continue;
6510907Sbde
6610907Sbde    const CXXRecordDecl *BaseDecl =
6710907Sbde      cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
6810907Sbde
6910907Sbde    const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
7011295Sswallace    CharUnits BaseOffset = Base.getBaseOffset() +
7110907Sbde      Layout.getBaseClassOffset(BaseDecl);
7210907Sbde
7310907Sbde    // Layout the VTT for this base.
7410907Sbde    LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
7511295Sswallace  }
7610907Sbde}
7710907Sbde
7810907Sbdevoid
7910907SbdeVTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
8010907Sbde                                           bool BaseIsMorallyVirtual,
8110907Sbde                                           uint64_t VTableIndex,
8210907Sbde                                           const CXXRecordDecl *VTableClass,
8310907Sbde                                           VisitedVirtualBasesSetTy &VBases) {
841541Srgrimes  const CXXRecordDecl *RD = Base.getBase();
851541Srgrimes
861541Srgrimes  // We're not interested in bases that don't have virtual bases, and not
8710907Sbde  // morally virtual bases.
8810907Sbde  if (!RD->getNumVBases() && !BaseIsMorallyVirtual)
8910907Sbde    return;
9010907Sbde
9110907Sbde  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
9210907Sbde       E = RD->bases_end(); I != E; ++I) {
931549Srgrimes    const CXXRecordDecl *BaseDecl =
9410907Sbde      cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
9510907Sbde
9610907Sbde    // Itanium C++ ABI 2.6.2:
9710907Sbde    //   Secondary virtual pointers are present for all bases with either
9810907Sbde    //   virtual bases or virtual function declarations overridden along a
9910907Sbde    //   virtual path.
10010907Sbde    //
10110907Sbde    // If the base class is not dynamic, we don't want to add it, nor any
10210907Sbde    // of its base classes.
10310907Sbde    if (!BaseDecl->isDynamicClass())
10410907Sbde      continue;
10510907Sbde
1061541Srgrimes    bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual;
10710907Sbde    bool BaseDeclIsNonVirtualPrimaryBase = false;
10810907Sbde    CharUnits BaseOffset;
1091541Srgrimes    if (I->isVirtual()) {
1101541Srgrimes      // Ignore virtual bases that we've already visited.
11111295Sswallace      if (!VBases.insert(BaseDecl))
11210907Sbde        continue;
11310907Sbde
11410907Sbde      BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
11510907Sbde      BaseDeclIsMorallyVirtual = true;
11610907Sbde    } else {
11710907Sbde      const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
11811295Sswallace
11910907Sbde      BaseOffset = Base.getBaseOffset() +
12010907Sbde        Layout.getBaseClassOffset(BaseDecl);
1211541Srgrimes
12211295Sswallace      if (!Layout.isPrimaryBaseVirtual() &&
1231541Srgrimes          Layout.getPrimaryBase() == BaseDecl)
1241541Srgrimes        BaseDeclIsNonVirtualPrimaryBase = true;
12510907Sbde    }
12610907Sbde
12710907Sbde    // Itanium C++ ABI 2.6.2:
12810907Sbde    //   Secondary virtual pointers: for each base class X which (a) has virtual
12910907Sbde    //   bases or is reachable along a virtual path from D, and (b) is not a
1301541Srgrimes    //   non-virtual primary base, the address of the virtual table for X-in-D
1311541Srgrimes    //   or an appropriate construction virtual table.
1321541Srgrimes    if (!BaseDeclIsNonVirtualPrimaryBase &&
13310907Sbde        (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) {
1341541Srgrimes      // Add the vtable pointer.
1351541Srgrimes      AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTableIndex,
1361541Srgrimes                       VTableClass);
13710907Sbde    }
13811295Sswallace
13910907Sbde    // And lay out the secondary virtual pointers for the base class.
14010907Sbde    LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset),
14114220Speter                                   BaseDeclIsMorallyVirtual, VTableIndex,
14210907Sbde                                   VTableClass, VBases);
14310907Sbde  }
14411295Sswallace}
14510907Sbde
14610907Sbdevoid
1471541SrgrimesVTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base,
14810907Sbde                                           uint64_t VTableIndex) {
14910907Sbde  VisitedVirtualBasesSetTy VBases;
15010907Sbde  LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false,
1511541Srgrimes                                 VTableIndex, Base.getBase(), VBases);
1521541Srgrimes}
15310907Sbde
15410907Sbdevoid VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
15510907Sbde                                   VisitedVirtualBasesSetTy &VBases) {
15610907Sbde  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
15711295Sswallace       E = RD->bases_end(); I != E; ++I) {
15810907Sbde    const CXXRecordDecl *BaseDecl =
15910907Sbde      cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
16010907Sbde
16110907Sbde    // Check if this is a virtual base.
16210907Sbde    if (I->isVirtual()) {
1631541Srgrimes      // Check if we've seen this base before.
1641541Srgrimes      if (!VBases.insert(BaseDecl))
1651541Srgrimes        continue;
1661541Srgrimes
1671541Srgrimes      CharUnits BaseOffset =
1681541Srgrimes        MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
16910907Sbde
17010907Sbde      LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true);
17111295Sswallace    }
1721541Srgrimes
17314220Speter    // We only need to layout virtual VTTs for this base if it actually has
17414220Speter    // virtual bases.
17514220Speter    if (BaseDecl->getNumVBases())
17610907Sbde      LayoutVirtualVTTs(BaseDecl, VBases);
1771541Srgrimes  }
17810907Sbde}
1791541Srgrimes
18010907Sbdevoid VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
1811541Srgrimes  const CXXRecordDecl *RD = Base.getBase();
1821541Srgrimes
18310907Sbde  // Itanium C++ ABI 2.6.2:
18410907Sbde  //   An array of virtual table addresses, called the VTT, is declared for
18510907Sbde  //   each class type that has indirect or direct virtual base classes.
18610907Sbde  if (RD->getNumVBases() == 0)
18713416Sphk    return;
18810907Sbde
1891541Srgrimes  bool IsPrimaryVTT = Base.getBase() == MostDerivedClass;
19010907Sbde
1911541Srgrimes  if (!IsPrimaryVTT) {
19211295Sswallace    // Remember the sub-VTT index.
19311295Sswallace    SubVTTIndicies[Base] = VTTComponents.size();
19410907Sbde  }
19510907Sbde
19610907Sbde  uint64_t VTableIndex = VTTVTables.size();
19710907Sbde  VTTVTables.push_back(VTTVTable(Base, BaseIsVirtual));
19810907Sbde
19910907Sbde  // Add the primary vtable pointer.
20010907Sbde  AddVTablePointer(Base, VTableIndex, RD);
20110907Sbde
20210907Sbde  // Add the secondary VTTs.
20310907Sbde  LayoutSecondaryVTTs(Base);
20410907Sbde
20510907Sbde  // Add the secondary virtual pointers.
20611295Sswallace  LayoutSecondaryVirtualPointers(Base, VTableIndex);
20714220Speter
20814220Speter  // If this is the primary VTT, we want to lay out virtual VTTs as well.
20914220Speter  if (IsPrimaryVTT) {
21010907Sbde    VisitedVirtualBasesSetTy VBases;
21110907Sbde    LayoutVirtualVTTs(Base.getBase(), VBases);
21210907Sbde  }
21310907Sbde}
2141541Srgrimes