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