clang API Documentation

VTTBuilder.cpp
Go to the documentation of this file.
00001 //===--- VTTBuilder.cpp - C++ VTT layout builder --------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This contains code dealing with generation of the layout of virtual table
00011 // tables (VTT).
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "clang/AST/VTTBuilder.h"
00016 #include "clang/AST/ASTContext.h"
00017 #include "clang/AST/CXXInheritance.h"
00018 #include "clang/AST/RecordLayout.h"
00019 #include "clang/Basic/TargetInfo.h"
00020 #include "llvm/Support/Format.h"
00021 #include <algorithm>
00022 #include <cstdio>
00023 
00024 using namespace clang;
00025 
00026 #define DUMP_OVERRIDERS 0
00027 
00028 VTTBuilder::VTTBuilder(ASTContext &Ctx,
00029                        const CXXRecordDecl *MostDerivedClass,
00030                        bool GenerateDefinition)
00031   : Ctx(Ctx), MostDerivedClass(MostDerivedClass), 
00032   MostDerivedClassLayout(Ctx.getASTRecordLayout(MostDerivedClass)),
00033     GenerateDefinition(GenerateDefinition) {
00034   // Lay out this VTT.
00035   LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()), 
00036             /*BaseIsVirtual=*/false);
00037 }
00038 
00039 void VTTBuilder::AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
00040                                   const CXXRecordDecl *VTableClass) {
00041   // Store the vtable pointer index if we're generating the primary VTT.
00042   if (VTableClass == MostDerivedClass) {
00043     assert(!SecondaryVirtualPointerIndices.count(Base) &&
00044            "A virtual pointer index already exists for this base subobject!");
00045     SecondaryVirtualPointerIndices[Base] = VTTComponents.size();
00046   }
00047 
00048   if (!GenerateDefinition) {
00049     VTTComponents.push_back(VTTComponent());
00050     return;
00051   }
00052 
00053   VTTComponents.push_back(VTTComponent(VTableIndex, Base));
00054 }
00055 
00056 void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) {
00057   const CXXRecordDecl *RD = Base.getBase();
00058 
00059   for (const auto &I : RD->bases()) {    
00060     // Don't layout virtual bases.
00061     if (I.isVirtual())
00062         continue;
00063 
00064     const CXXRecordDecl *BaseDecl =
00065       cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
00066 
00067     const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
00068     CharUnits BaseOffset = Base.getBaseOffset() + 
00069       Layout.getBaseClassOffset(BaseDecl);
00070    
00071     // Layout the VTT for this base.
00072     LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false);
00073   }
00074 }
00075 
00076 void
00077 VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, 
00078                                            bool BaseIsMorallyVirtual,
00079                                            uint64_t VTableIndex,
00080                                            const CXXRecordDecl *VTableClass,
00081                                            VisitedVirtualBasesSetTy &VBases) {
00082   const CXXRecordDecl *RD = Base.getBase();
00083   
00084   // We're not interested in bases that don't have virtual bases, and not
00085   // morally virtual bases.
00086   if (!RD->getNumVBases() && !BaseIsMorallyVirtual)
00087     return;
00088 
00089   for (const auto &I : RD->bases()) {
00090     const CXXRecordDecl *BaseDecl =
00091       cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
00092 
00093     // Itanium C++ ABI 2.6.2:
00094     //   Secondary virtual pointers are present for all bases with either
00095     //   virtual bases or virtual function declarations overridden along a 
00096     //   virtual path.
00097     //
00098     // If the base class is not dynamic, we don't want to add it, nor any
00099     // of its base classes.
00100     if (!BaseDecl->isDynamicClass())
00101       continue;
00102     
00103     bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual;
00104     bool BaseDeclIsNonVirtualPrimaryBase = false;
00105     CharUnits BaseOffset;
00106     if (I.isVirtual()) {
00107       // Ignore virtual bases that we've already visited.
00108       if (!VBases.insert(BaseDecl))
00109         continue;
00110       
00111       BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
00112       BaseDeclIsMorallyVirtual = true;
00113     } else {
00114       const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
00115       
00116       BaseOffset = Base.getBaseOffset() + 
00117         Layout.getBaseClassOffset(BaseDecl);
00118       
00119       if (!Layout.isPrimaryBaseVirtual() &&
00120           Layout.getPrimaryBase() == BaseDecl)
00121         BaseDeclIsNonVirtualPrimaryBase = true;
00122     }
00123 
00124     // Itanium C++ ABI 2.6.2:
00125     //   Secondary virtual pointers: for each base class X which (a) has virtual
00126     //   bases or is reachable along a virtual path from D, and (b) is not a
00127     //   non-virtual primary base, the address of the virtual table for X-in-D
00128     //   or an appropriate construction virtual table.
00129     if (!BaseDeclIsNonVirtualPrimaryBase &&
00130         (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) {
00131       // Add the vtable pointer.
00132       AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTableIndex, 
00133                        VTableClass);
00134     }
00135 
00136     // And lay out the secondary virtual pointers for the base class.
00137     LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset),
00138                                    BaseDeclIsMorallyVirtual, VTableIndex, 
00139                                    VTableClass, VBases);
00140   }
00141 }
00142 
00143 void 
00144 VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, 
00145                                            uint64_t VTableIndex) {
00146   VisitedVirtualBasesSetTy VBases;
00147   LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false,
00148                                  VTableIndex, Base.getBase(), VBases);
00149 }
00150 
00151 void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD,
00152                                    VisitedVirtualBasesSetTy &VBases) {
00153   for (const auto &I : RD->bases()) {
00154     const CXXRecordDecl *BaseDecl = 
00155       cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
00156     
00157     // Check if this is a virtual base.
00158     if (I.isVirtual()) {
00159       // Check if we've seen this base before.
00160       if (!VBases.insert(BaseDecl))
00161         continue;
00162     
00163       CharUnits BaseOffset = 
00164         MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
00165       
00166       LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true);
00167     }
00168     
00169     // We only need to layout virtual VTTs for this base if it actually has
00170     // virtual bases.
00171     if (BaseDecl->getNumVBases())
00172       LayoutVirtualVTTs(BaseDecl, VBases);
00173   }
00174 }
00175 
00176 void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) {
00177   const CXXRecordDecl *RD = Base.getBase();
00178 
00179   // Itanium C++ ABI 2.6.2:
00180   //   An array of virtual table addresses, called the VTT, is declared for 
00181   //   each class type that has indirect or direct virtual base classes.
00182   if (RD->getNumVBases() == 0)
00183     return;
00184 
00185   bool IsPrimaryVTT = Base.getBase() == MostDerivedClass;
00186 
00187   if (!IsPrimaryVTT) {
00188     // Remember the sub-VTT index.
00189     SubVTTIndicies[Base] = VTTComponents.size();
00190   }
00191 
00192   uint64_t VTableIndex = VTTVTables.size();
00193   VTTVTables.push_back(VTTVTable(Base, BaseIsVirtual));
00194 
00195   // Add the primary vtable pointer.
00196   AddVTablePointer(Base, VTableIndex, RD);
00197 
00198   // Add the secondary VTTs.
00199   LayoutSecondaryVTTs(Base);
00200   
00201   // Add the secondary virtual pointers.
00202   LayoutSecondaryVirtualPointers(Base, VTableIndex);
00203   
00204   // If this is the primary VTT, we want to lay out virtual VTTs as well.
00205   if (IsPrimaryVTT) {
00206     VisitedVirtualBasesSetTy VBases;
00207     LayoutVirtualVTTs(Base.getBase(), VBases);
00208   }
00209 }