1317017Sdim//===- UDTLayout.h - UDT layout info ----------------------------*- C++ -*-===//
2317017Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6317017Sdim//
7317017Sdim//===----------------------------------------------------------------------===//
8317017Sdim
9317017Sdim#ifndef LLVM_DEBUGINFO_PDB_UDTLAYOUT_H
10317017Sdim#define LLVM_DEBUGINFO_PDB_UDTLAYOUT_H
11317017Sdim
12317017Sdim#include "llvm/ADT/ArrayRef.h"
13317017Sdim#include "llvm/ADT/BitVector.h"
14320572Sdim#include "llvm/ADT/StringRef.h"
15320572Sdim#include "llvm/DebugInfo/PDB/PDBSymbol.h"
16320572Sdim#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
17320572Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
18320572Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
19320572Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
20320572Sdim#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
21320572Sdim#include "llvm/DebugInfo/PDB/PDBTypes.h"
22320572Sdim#include <cstdint>
23317017Sdim#include <memory>
24320572Sdim#include <string>
25320572Sdim#include <vector>
26317017Sdim
27317017Sdimnamespace llvm {
28317017Sdimnamespace pdb {
29317017Sdim
30320572Sdimclass BaseClassLayout;
31317017Sdimclass ClassLayout;
32317017Sdimclass UDTLayoutBase;
33317017Sdim
34317472Sdimclass LayoutItemBase {
35317017Sdimpublic:
36317472Sdim  LayoutItemBase(const UDTLayoutBase *Parent, const PDBSymbol *Symbol,
37317472Sdim                 const std::string &Name, uint32_t OffsetInParent,
38317472Sdim                 uint32_t Size, bool IsElided);
39320572Sdim  virtual ~LayoutItemBase() = default;
40317017Sdim
41317472Sdim  uint32_t deepPaddingSize() const;
42317472Sdim  virtual uint32_t immediatePadding() const { return 0; }
43317472Sdim  virtual uint32_t tailPadding() const;
44317017Sdim
45317472Sdim  const UDTLayoutBase *getParent() const { return Parent; }
46317017Sdim  StringRef getName() const { return Name; }
47317017Sdim  uint32_t getOffsetInParent() const { return OffsetInParent; }
48317017Sdim  uint32_t getSize() const { return SizeOf; }
49317472Sdim  uint32_t getLayoutSize() const { return LayoutSize; }
50317472Sdim  const PDBSymbol *getSymbol() const { return Symbol; }
51317472Sdim  const BitVector &usedBytes() const { return UsedBytes; }
52317472Sdim  bool isElided() const { return IsElided; }
53317472Sdim  virtual bool isVBPtr() const { return false; }
54317017Sdim
55317472Sdim  uint32_t containsOffset(uint32_t Off) const {
56317472Sdim    uint32_t Begin = getOffsetInParent();
57317472Sdim    uint32_t End = Begin + getSize();
58317472Sdim    return (Off >= Begin && Off < End);
59317472Sdim  }
60317472Sdim
61317017Sdimprotected:
62317472Sdim  const PDBSymbol *Symbol = nullptr;
63317472Sdim  const UDTLayoutBase *Parent = nullptr;
64317017Sdim  BitVector UsedBytes;
65317017Sdim  std::string Name;
66317017Sdim  uint32_t OffsetInParent = 0;
67317017Sdim  uint32_t SizeOf = 0;
68317472Sdim  uint32_t LayoutSize = 0;
69317472Sdim  bool IsElided = false;
70317017Sdim};
71317017Sdim
72317472Sdimclass VBPtrLayoutItem : public LayoutItemBase {
73317017Sdimpublic:
74317472Sdim  VBPtrLayoutItem(const UDTLayoutBase &Parent,
75317472Sdim                  std::unique_ptr<PDBSymbolTypeBuiltin> Sym, uint32_t Offset,
76317472Sdim                  uint32_t Size);
77317472Sdim
78320572Sdim  bool isVBPtr() const override { return true; }
79320572Sdim
80317472Sdimprivate:
81317472Sdim  std::unique_ptr<PDBSymbolTypeBuiltin> Type;
82317472Sdim};
83317472Sdim
84317472Sdimclass DataMemberLayoutItem : public LayoutItemBase {
85317472Sdimpublic:
86317017Sdim  DataMemberLayoutItem(const UDTLayoutBase &Parent,
87317017Sdim                       std::unique_ptr<PDBSymbolData> DataMember);
88317017Sdim
89317017Sdim  const PDBSymbolData &getDataMember();
90317017Sdim  bool hasUDTLayout() const;
91317017Sdim  const ClassLayout &getUDTLayout() const;
92317017Sdim
93317017Sdimprivate:
94317017Sdim  std::unique_ptr<PDBSymbolData> DataMember;
95317017Sdim  std::unique_ptr<ClassLayout> UdtLayout;
96317017Sdim};
97317017Sdim
98317472Sdimclass VTableLayoutItem : public LayoutItemBase {
99317017Sdimpublic:
100317017Sdim  VTableLayoutItem(const UDTLayoutBase &Parent,
101317017Sdim                   std::unique_ptr<PDBSymbolTypeVTable> VTable);
102317017Sdim
103317017Sdim  uint32_t getElementSize() const { return ElementSize; }
104317017Sdim
105317017Sdimprivate:
106317017Sdim  uint32_t ElementSize = 0;
107317017Sdim  std::unique_ptr<PDBSymbolTypeVTable> VTable;
108317017Sdim};
109317017Sdim
110317472Sdimclass UDTLayoutBase : public LayoutItemBase {
111317017Sdim  template <typename T> using UniquePtrVector = std::vector<std::unique_ptr<T>>;
112317017Sdim
113317017Sdimpublic:
114317472Sdim  UDTLayoutBase(const UDTLayoutBase *Parent, const PDBSymbol &Sym,
115317472Sdim                const std::string &Name, uint32_t OffsetInParent, uint32_t Size,
116317472Sdim                bool IsElided);
117317017Sdim
118317472Sdim  uint32_t tailPadding() const override;
119317472Sdim  ArrayRef<LayoutItemBase *> layout_items() const { return LayoutItems; }
120317472Sdim  ArrayRef<BaseClassLayout *> bases() const { return AllBases; }
121317472Sdim  ArrayRef<BaseClassLayout *> regular_bases() const { return NonVirtualBases; }
122317472Sdim  ArrayRef<BaseClassLayout *> virtual_bases() const { return VirtualBases; }
123317472Sdim  uint32_t directVirtualBaseCount() const { return DirectVBaseCount; }
124317017Sdim  ArrayRef<std::unique_ptr<PDBSymbolFunc>> funcs() const { return Funcs; }
125317017Sdim  ArrayRef<std::unique_ptr<PDBSymbol>> other_items() const { return Other; }
126317017Sdim
127317017Sdimprotected:
128317472Sdim  bool hasVBPtrAtOffset(uint32_t Off) const;
129317017Sdim  void initializeChildren(const PDBSymbol &Sym);
130317017Sdim
131317472Sdim  void addChildToLayout(std::unique_ptr<LayoutItemBase> Child);
132317017Sdim
133317472Sdim  uint32_t DirectVBaseCount = 0;
134317017Sdim
135317017Sdim  UniquePtrVector<PDBSymbol> Other;
136317017Sdim  UniquePtrVector<PDBSymbolFunc> Funcs;
137317472Sdim  UniquePtrVector<LayoutItemBase> ChildStorage;
138317472Sdim  std::vector<LayoutItemBase *> LayoutItems;
139317472Sdim
140317472Sdim  std::vector<BaseClassLayout *> AllBases;
141317472Sdim  ArrayRef<BaseClassLayout *> NonVirtualBases;
142317472Sdim  ArrayRef<BaseClassLayout *> VirtualBases;
143317472Sdim
144317017Sdim  VTableLayoutItem *VTable = nullptr;
145317472Sdim  VBPtrLayoutItem *VBPtr = nullptr;
146317017Sdim};
147317017Sdim
148317472Sdimclass BaseClassLayout : public UDTLayoutBase {
149317472Sdimpublic:
150317472Sdim  BaseClassLayout(const UDTLayoutBase &Parent, uint32_t OffsetInParent,
151317472Sdim                  bool Elide, std::unique_ptr<PDBSymbolTypeBaseClass> Base);
152317472Sdim
153317472Sdim  const PDBSymbolTypeBaseClass &getBase() const { return *Base; }
154317472Sdim  bool isVirtualBase() const { return IsVirtualBase; }
155317472Sdim  bool isEmptyBase() { return SizeOf == 1 && LayoutSize == 0; }
156317472Sdim
157317472Sdimprivate:
158317472Sdim  std::unique_ptr<PDBSymbolTypeBaseClass> Base;
159317472Sdim  bool IsVirtualBase;
160317472Sdim};
161317472Sdim
162317017Sdimclass ClassLayout : public UDTLayoutBase {
163317017Sdimpublic:
164317017Sdim  explicit ClassLayout(const PDBSymbolTypeUDT &UDT);
165317017Sdim  explicit ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT);
166317017Sdim
167317017Sdim  ClassLayout(ClassLayout &&Other) = default;
168317017Sdim
169317017Sdim  const PDBSymbolTypeUDT &getClass() const { return UDT; }
170317472Sdim  uint32_t immediatePadding() const override;
171317017Sdim
172317017Sdimprivate:
173317472Sdim  BitVector ImmediateUsedBytes;
174317017Sdim  std::unique_ptr<PDBSymbolTypeUDT> OwnedStorage;
175317017Sdim  const PDBSymbolTypeUDT &UDT;
176317017Sdim};
177317017Sdim
178320572Sdim} // end namespace pdb
179320572Sdim} // end namespace llvm
180320572Sdim
181317017Sdim#endif // LLVM_DEBUGINFO_PDB_UDTLAYOUT_H
182