LLVM  8.0.1
UDTLayout.cpp
Go to the documentation of this file.
1 //===- UDTLayout.cpp ------------------------------------------------------===//
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 
11 #include "llvm/ADT/ArrayRef.h"
12 #include "llvm/ADT/BitVector.h"
13 #include "llvm/ADT/STLExtras.h"
25 #include "llvm/Support/Casting.h"
26 #include <algorithm>
27 #include <cassert>
28 #include <cstdint>
29 #include <memory>
30 
31 using namespace llvm;
32 using namespace llvm::pdb;
33 
34 static std::unique_ptr<PDBSymbol> getSymbolType(const PDBSymbol &Symbol) {
35  const IPDBSession &Session = Symbol.getSession();
36  const IPDBRawSymbol &RawSymbol = Symbol.getRawSymbol();
37  uint32_t TypeId = RawSymbol.getTypeId();
38  return Session.getSymbolById(TypeId);
39 }
40 
42  auto SymbolType = getSymbolType(Symbol);
43  const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();
44 
45  return RawType.getLength();
46 }
47 
49  const PDBSymbol *Symbol, const std::string &Name,
50  uint32_t OffsetInParent, uint32_t Size,
51  bool IsElided)
52  : Symbol(Symbol), Parent(Parent), Name(Name),
53  OffsetInParent(OffsetInParent), SizeOf(Size), LayoutSize(Size),
54  IsElided(IsElided) {
55  UsedBytes.resize(SizeOf, true);
56 }
57 
59  return UsedBytes.size() - UsedBytes.count();
60 }
61 
63  int Last = UsedBytes.find_last();
64 
65  return UsedBytes.size() - (Last + 1);
66 }
67 
69  const UDTLayoutBase &Parent, std::unique_ptr<PDBSymbolData> Member)
70  : LayoutItemBase(&Parent, Member.get(), Member->getName(),
71  Member->getOffset(), getTypeLength(*Member), false),
72  DataMember(std::move(Member)) {
73  auto Type = DataMember->getType();
74  if (auto UDT = unique_dyn_cast<PDBSymbolTypeUDT>(Type)) {
75  UdtLayout = llvm::make_unique<ClassLayout>(std::move(UDT));
76  UsedBytes = UdtLayout->usedBytes();
77  }
78 }
79 
81  std::unique_ptr<PDBSymbolTypeBuiltin> Sym,
83  : LayoutItemBase(&Parent, Sym.get(), "<vbptr>", Offset, Size, false),
84  Type(std::move(Sym)) {
85 }
86 
88  return *dyn_cast<PDBSymbolData>(Symbol);
89 }
90 
91 bool DataMemberLayoutItem::hasUDTLayout() const { return UdtLayout != nullptr; }
92 
94  return *UdtLayout;
95 }
96 
98  std::unique_ptr<PDBSymbolTypeVTable> VT)
99  : LayoutItemBase(&Parent, VT.get(), "<vtbl>", 0, getTypeLength(*VT), false),
100  VTable(std::move(VT)) {
101  auto VTableType = cast<PDBSymbolTypePointer>(VTable->getType());
102  ElementSize = VTableType->getLength();
103 }
104 
106  const std::string &Name, uint32_t OffsetInParent,
107  uint32_t Size, bool IsElided)
108  : LayoutItemBase(Parent, &Sym, Name, OffsetInParent, Size, IsElided) {
109  // UDT storage comes from a union of all the children's storage, so start out
110  // uninitialized.
111  UsedBytes.reset(0, Size);
112 
113  initializeChildren(Sym);
114  if (LayoutSize < Size)
116 }
117 
120  if (!LayoutItems.empty()) {
121  const LayoutItemBase *Back = LayoutItems.back();
122  uint32_t ChildPadding = Back->LayoutItemBase::tailPadding();
123  if (Abs < ChildPadding)
124  Abs = 0;
125  else
126  Abs -= ChildPadding;
127  }
128  return Abs;
129 }
130 
132  : UDTLayoutBase(nullptr, UDT, UDT.getName(), 0, UDT.getLength(), false),
133  UDT(UDT) {
134  ImmediateUsedBytes.resize(SizeOf, false);
135  for (auto &LI : LayoutItems) {
136  uint32_t Begin = LI->getOffsetInParent();
137  uint32_t End = Begin + LI->getLayoutSize();
138  End = std::min(SizeOf, End);
139  ImmediateUsedBytes.set(Begin, End);
140  }
141 }
142 
143 ClassLayout::ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT)
144  : ClassLayout(*UDT) {
145  OwnedStorage = std::move(UDT);
146 }
147 
149  return SizeOf - ImmediateUsedBytes.count();
150 }
151 
153  uint32_t OffsetInParent, bool Elide,
154  std::unique_ptr<PDBSymbolTypeBaseClass> B)
155  : UDTLayoutBase(&Parent, *B, B->getName(), OffsetInParent, B->getLength(),
156  Elide),
157  Base(std::move(B)) {
158  if (isEmptyBase()) {
159  // Special case an empty base so that it doesn't get treated as padding.
160  UsedBytes.resize(1);
161  UsedBytes.set(0);
162  }
163  IsVirtualBase = Base->isVirtualBaseClass();
164 }
165 
167  // Handled bases first, followed by VTables, followed by data members,
168  // followed by functions, followed by other. This ordering is necessary
169  // so that bases and vtables get initialized before any functions which
170  // may override them.
171  UniquePtrVector<PDBSymbolTypeBaseClass> Bases;
172  UniquePtrVector<PDBSymbolTypeVTable> VTables;
173  UniquePtrVector<PDBSymbolData> Members;
174  UniquePtrVector<PDBSymbolTypeBaseClass> VirtualBaseSyms;
175 
176  auto Children = Sym.findAllChildren();
177  while (auto Child = Children->getNext()) {
178  if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) {
179  if (Base->isVirtualBaseClass())
180  VirtualBaseSyms.push_back(std::move(Base));
181  else
182  Bases.push_back(std::move(Base));
183  }
184  else if (auto Data = unique_dyn_cast<PDBSymbolData>(Child)) {
185  if (Data->getDataKind() == PDB_DataKind::Member)
186  Members.push_back(std::move(Data));
187  else
188  Other.push_back(std::move(Data));
189  } else if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child))
190  VTables.push_back(std::move(VT));
191  else if (auto Func = unique_dyn_cast<PDBSymbolFunc>(Child))
192  Funcs.push_back(std::move(Func));
193  else {
194  Other.push_back(std::move(Child));
195  }
196  }
197 
198  // We don't want to have any re-allocations in the list of bases, so make
199  // sure to reserve enough space so that our ArrayRefs don't get invalidated.
200  AllBases.reserve(Bases.size() + VirtualBaseSyms.size());
201 
202  // Only add non-virtual bases to the class first. Only at the end of the
203  // class, after all non-virtual bases and data members have been added do we
204  // add virtual bases. This way the offsets are correctly aligned when we go
205  // to lay out virtual bases.
206  for (auto &Base : Bases) {
207  uint32_t Offset = Base->getOffset();
208  // Non-virtual bases never get elided.
209  auto BL = llvm::make_unique<BaseClassLayout>(*this, Offset, false,
210  std::move(Base));
211 
212  AllBases.push_back(BL.get());
213  addChildToLayout(std::move(BL));
214  }
216 
217  assert(VTables.size() <= 1);
218  if (!VTables.empty()) {
219  auto VTLayout =
220  llvm::make_unique<VTableLayoutItem>(*this, std::move(VTables[0]));
221 
222  VTable = VTLayout.get();
223 
224  addChildToLayout(std::move(VTLayout));
225  }
226 
227  for (auto &Data : Members) {
228  auto DM = llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data));
229 
230  addChildToLayout(std::move(DM));
231  }
232 
233  // Make sure add virtual bases before adding functions, since functions may be
234  // overrides of virtual functions declared in a virtual base, so the VTables
235  // and virtual intros need to be correctly initialized.
236  for (auto &VB : VirtualBaseSyms) {
237  int VBPO = VB->getVirtualBasePointerOffset();
238  if (!hasVBPtrAtOffset(VBPO)) {
239  if (auto VBP = VB->getRawSymbol().getVirtualBaseTableType()) {
240  auto VBPL = llvm::make_unique<VBPtrLayoutItem>(*this, std::move(VBP),
241  VBPO, VBP->getLength());
242  VBPtr = VBPL.get();
243  addChildToLayout(std::move(VBPL));
244  }
245  }
246 
247  // Virtual bases always go at the end. So just look for the last place we
248  // ended when writing something, and put our virtual base there.
249  // Note that virtual bases get elided unless this is a top-most derived
250  // class.
252  bool Elide = (Parent != nullptr);
253  auto BL =
254  llvm::make_unique<BaseClassLayout>(*this, Offset, Elide, std::move(VB));
255  AllBases.push_back(BL.get());
256 
257  // Only lay this virtual base out directly inside of *this* class if this
258  // is a top-most derived class. Keep track of it regardless, but only
259  // physically lay it out if it's a topmost derived class.
260  addChildToLayout(std::move(BL));
261  }
262  VirtualBases = makeArrayRef(AllBases).drop_front(NonVirtualBases.size());
263 
264  if (Parent != nullptr)
266 }
267 
269  if (VBPtr && VBPtr->getOffsetInParent() == Off)
270  return true;
271  for (BaseClassLayout *BL : AllBases) {
272  if (BL->hasVBPtrAtOffset(Off - BL->getOffsetInParent()))
273  return true;
274  }
275  return false;
276 }
277 
278 void UDTLayoutBase::addChildToLayout(std::unique_ptr<LayoutItemBase> Child) {
279  uint32_t Begin = Child->getOffsetInParent();
280 
281  if (!Child->isElided()) {
282  BitVector ChildBytes = Child->usedBytes();
283 
284  // Suppose the child occupies 4 bytes starting at offset 12 in a 32 byte
285  // class. When we call ChildBytes.resize(32), the Child's storage will
286  // still begin at offset 0, so we need to shift it left by offset bytes
287  // to get it into the right position.
288  ChildBytes.resize(UsedBytes.size());
289  ChildBytes <<= Child->getOffsetInParent();
290  UsedBytes |= ChildBytes;
291 
292  if (ChildBytes.count() > 0) {
293  auto Loc = std::upper_bound(LayoutItems.begin(), LayoutItems.end(), Begin,
294  [](uint32_t Off, const LayoutItemBase *Item) {
295  return (Off < Item->getOffsetInParent());
296  });
297 
298  LayoutItems.insert(Loc, Child.get());
299  }
300  }
301 
302  ChildStorage.push_back(std::move(Child));
303 }
uint32_t immediatePadding() const override
Definition: UDTLayout.cpp:148
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
Definition: BitVector.h:372
BitVector & set()
Definition: BitVector.h:398
IPDBSession defines an interface used to provide a context for querying debug information from a debu...
Definition: IPDBSession.h:26
virtual SymIndexId getTypeId() const =0
UniquePtrVector< PDBSymbolFunc > Funcs
Definition: UDTLayout.h:137
This class represents lattice values for constants.
Definition: AllocatorList.h:24
const UDTLayoutBase * Parent
Definition: UDTLayout.h:64
const IPDBSession & getSession() const
Definition: PDBSymbol.h:152
DataMemberLayoutItem(const UDTLayoutBase &Parent, std::unique_ptr< PDBSymbolData > DataMember)
Definition: UDTLayout.cpp:68
UniquePtrVector< PDBSymbol > Other
Definition: UDTLayout.h:136
int find_last() const
find_last - Returns the index of the last set bit, -1 if none of the bits are set.
Definition: BitVector.h:336
UniquePtrVector< LayoutItemBase > ChildStorage
Definition: UDTLayout.h:138
VTableLayoutItem(const UDTLayoutBase &Parent, std::unique_ptr< PDBSymbolTypeVTable > VTable)
Definition: UDTLayout.cpp:97
ArrayRef< BaseClassLayout * > VirtualBases
Definition: UDTLayout.h:143
std::unique_ptr< ConcreteSymbolEnumerator< T > > findAllChildren() const
Definition: PDBSymbol.h:131
UDTLayoutBase(const UDTLayoutBase *Parent, const PDBSymbol &Sym, const std::string &Name, uint32_t OffsetInParent, uint32_t Size, bool IsElided)
Definition: UDTLayout.cpp:105
uint32_t getOffsetInParent() const
Definition: UDTLayout.h:48
amdgpu Simplify well known AMD library false Value Value const Twine & Name
Definition: BitVector.h:938
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:451
virtual std::unique_ptr< PDBSymbol > getSymbolById(SymIndexId SymbolId) const =0
std::vector< LayoutItemBase * > LayoutItems
Definition: UDTLayout.h:139
uint32_t deepPaddingSize() const
Definition: UDTLayout.cpp:58
const PDBSymbolData & getDataMember()
Definition: UDTLayout.cpp:87
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
StringRef getName() const
Definition: UDTLayout.h:47
const PDBSymbol * Symbol
Definition: UDTLayout.h:63
uint32_t tailPadding() const override
Definition: UDTLayout.cpp:118
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
std::vector< BaseClassLayout * > AllBases
Definition: UDTLayout.h:141
IPDBRawSymbol defines an interface used to represent an arbitrary symbol.
Definition: IPDBRawSymbol.h:50
ArrayRef< BaseClassLayout * > NonVirtualBases
Definition: UDTLayout.h:142
BitVector & reset()
Definition: BitVector.h:439
static uint32_t getTypeLength(const PDBSymbol &Symbol)
Definition: UDTLayout.cpp:41
bool hasVBPtrAtOffset(uint32_t Off) const
Definition: UDTLayout.cpp:268
VBPtrLayoutItem * VBPtr
Definition: UDTLayout.h:146
void addChildToLayout(std::unique_ptr< LayoutItemBase > Child)
Definition: UDTLayout.cpp:278
VTableLayoutItem * VTable
Definition: UDTLayout.h:145
size_type count() const
count - Returns the number of bits which are set.
Definition: BitVector.h:173
virtual uint32_t tailPadding() const
Definition: UDTLayout.cpp:62
PDBSymbol defines the base of the inheritance hierarchy for concrete symbol types (e...
Definition: PDBSymbol.h:74
const IPDBRawSymbol & getRawSymbol() const
Definition: PDBSymbol.h:149
static std::unique_ptr< PDBSymbol > getSymbolType(const PDBSymbol &Symbol)
Definition: UDTLayout.cpp:34
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:323
ClassLayout(const PDBSymbolTypeUDT &UDT)
Definition: UDTLayout.cpp:131
size_type size() const
size - Returns the number of bits in this bitvector.
Definition: BitVector.h:170
uint32_t Size
Definition: Profile.cpp:47
auto upper_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range))
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1295
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void initializeChildren(const PDBSymbol &Sym)
Definition: UDTLayout.cpp:166
const ClassLayout & getUDTLayout() const
Definition: UDTLayout.cpp:93
VBPtrLayoutItem(const UDTLayoutBase &Parent, std::unique_ptr< PDBSymbolTypeBuiltin > Sym, uint32_t Offset, uint32_t Size)
Definition: UDTLayout.cpp:80
LayoutItemBase(const UDTLayoutBase *Parent, const PDBSymbol *Symbol, const std::string &Name, uint32_t OffsetInParent, uint32_t Size, bool IsElided)
Definition: UDTLayout.cpp:48
BaseClassLayout(const UDTLayoutBase &Parent, uint32_t OffsetInParent, bool Elide, std::unique_ptr< PDBSymbolTypeBaseClass > Base)
Definition: UDTLayout.cpp:152
virtual uint64_t getLength() const =0