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