//===- VTTBuilder.h - C++ VTT layout builder --------------------*- C++ -*-===//
 
//
 
// 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 generation of the layout of virtual table
 
// tables (VTT).
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_CLANG_AST_VTTBUILDER_H
 
#define LLVM_CLANG_AST_VTTBUILDER_H
 
 
 
#include "clang/AST/BaseSubobject.h"
 
#include "clang/AST/CharUnits.h"
 
#include "clang/Basic/LLVM.h"
 
#include "llvm/ADT/DenseMap.h"
 
#include "llvm/ADT/PointerIntPair.h"
 
#include "llvm/ADT/SmallPtrSet.h"
 
#include "llvm/ADT/SmallVector.h"
 
#include <cstdint>
 
 
 
namespace clang {
 
 
 
class ASTContext;
 
class ASTRecordLayout;
 
class CXXRecordDecl;
 
 
 
class VTTVTable {
 
  llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> BaseAndIsVirtual;
 
  CharUnits BaseOffset;
 
 
 
public:
 
  VTTVTable() = default;
 
  VTTVTable(const CXXRecordDecl *Base, CharUnits BaseOffset, bool BaseIsVirtual)
 
      : BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {}
 
  VTTVTable(BaseSubobject Base, bool BaseIsVirtual)
 
      : BaseAndIsVirtual(Base.getBase(), BaseIsVirtual),
 
        BaseOffset(Base.getBaseOffset()) {}
 
 
 
  const CXXRecordDecl *getBase() const {
 
    return BaseAndIsVirtual.getPointer();
 
  }
 
 
 
  CharUnits getBaseOffset() const {
 
    return BaseOffset;
 
  }
 
 
 
  bool isVirtual() const {
 
    return BaseAndIsVirtual.getInt();
 
  }
 
 
 
  BaseSubobject getBaseSubobject() const {
 
    return BaseSubobject(getBase(), getBaseOffset());
 
  }
 
};
 
 
 
struct VTTComponent {
 
  uint64_t VTableIndex;
 
  BaseSubobject VTableBase;
 
 
 
  VTTComponent() = default;
 
  VTTComponent(uint64_t VTableIndex, BaseSubobject VTableBase)
 
     : VTableIndex(VTableIndex), VTableBase(VTableBase) {}
 
};
 
 
 
/// Class for building VTT layout information.
 
class VTTBuilder {
 
  ASTContext &Ctx;
 
 
 
  /// The most derived class for which we're building this vtable.
 
  const CXXRecordDecl *MostDerivedClass;
 
 
 
  using VTTVTablesVectorTy = SmallVector<VTTVTable, 64>;
 
 
 
  /// The VTT vtables.
 
  VTTVTablesVectorTy VTTVTables;
 
 
 
  using VTTComponentsVectorTy = SmallVector<VTTComponent, 64>;
 
 
 
  /// The VTT components.
 
  VTTComponentsVectorTy VTTComponents;
 
 
 
  /// The AST record layout of the most derived class.
 
  const ASTRecordLayout &MostDerivedClassLayout;
 
 
 
  using VisitedVirtualBasesSetTy = llvm::SmallPtrSet<const CXXRecordDecl *, 4>;
 
 
 
  using AddressPointsMapTy = llvm::DenseMap<BaseSubobject, uint64_t>;
 
 
 
  /// The sub-VTT indices for the bases of the most derived class.
 
  llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies;
 
 
 
  /// The secondary virtual pointer indices of all subobjects of
 
  /// the most derived class.
 
  llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices;
 
 
 
  /// Whether the VTT builder should generate LLVM IR for the VTT.
 
  bool GenerateDefinition;
 
 
 
  /// Add a vtable pointer to the VTT currently being built.
 
  void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
 
                        const CXXRecordDecl *VTableClass);
 
 
 
  /// Lay out the secondary VTTs of the given base subobject.
 
  void LayoutSecondaryVTTs(BaseSubobject Base);
 
 
 
  /// Lay out the secondary virtual pointers for the given base
 
  /// subobject.
 
  ///
 
  /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
 
  /// or a direct or indirect base of a virtual base.
 
  void LayoutSecondaryVirtualPointers(BaseSubobject Base,
 
                                      bool BaseIsMorallyVirtual,
 
                                      uint64_t VTableIndex,
 
                                      const CXXRecordDecl *VTableClass,
 
                                      VisitedVirtualBasesSetTy &VBases);
 
 
 
  /// Lay out the secondary virtual pointers for the given base
 
  /// subobject.
 
  void LayoutSecondaryVirtualPointers(BaseSubobject Base,
 
                                      uint64_t VTableIndex);
 
 
 
  /// Lay out the VTTs for the virtual base classes of the given
 
  /// record declaration.
 
  void LayoutVirtualVTTs(const CXXRecordDecl *RD,
 
                         VisitedVirtualBasesSetTy &VBases);
 
 
 
  /// Lay out the VTT for the given subobject, including any
 
  /// secondary VTTs, secondary virtual pointers and virtual VTTs.
 
  void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual);
 
 
 
public:
 
  VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass,
 
             bool GenerateDefinition);
 
 
 
  // Returns a reference to the VTT components.
 
  const VTTComponentsVectorTy &getVTTComponents() const {
 
    return VTTComponents;
 
  }
 
 
 
  // Returns a reference to the VTT vtables.
 
  const VTTVTablesVectorTy &getVTTVTables() const {
 
    return VTTVTables;
 
  }
 
 
 
  /// Returns a reference to the sub-VTT indices.
 
  const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndicies() const {
 
    return SubVTTIndicies;
 
  }
 
 
 
  /// Returns a reference to the secondary virtual pointer indices.
 
  const llvm::DenseMap<BaseSubobject, uint64_t> &
 
  getSecondaryVirtualPointerIndices() const {
 
    return SecondaryVirtualPointerIndices;
 
  }
 
};
 
 
 
} // namespace clang
 
 
 
#endif // LLVM_CLANG_AST_VTTBUILDER_H