blob: da353cb6977ce779ddda632838c12d817a5124e2 [file] [log] [blame]
Zachary Turnerc883a8c2017-04-12 23:18:21 +00001//===- UDTLayout.cpp --------------------------------------------*- C++ -*-===//
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
10#include "llvm/DebugInfo/PDB/UDTLayout.h"
11
Zachary Turner4dc4f012017-04-13 21:11:00 +000012#include "llvm/ADT/STLExtras.h"
Zachary Turnerc883a8c2017-04-12 23:18:21 +000013#include "llvm/DebugInfo/PDB/IPDBSession.h"
14#include "llvm/DebugInfo/PDB/PDBSymbol.h"
15#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
16#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
17#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
18#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
Zachary Turner16901642017-04-24 17:47:24 +000019#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
Zachary Turnerc883a8c2017-04-12 23:18:21 +000020#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
21#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
22#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
23
24#include <utility>
25
26using namespace llvm;
27using namespace llvm::pdb;
28
29static std::unique_ptr<PDBSymbol> getSymbolType(const PDBSymbol &Symbol) {
30 const IPDBSession &Session = Symbol.getSession();
31 const IPDBRawSymbol &RawSymbol = Symbol.getRawSymbol();
32 uint32_t TypeId = RawSymbol.getTypeId();
33 return Session.getSymbolById(TypeId);
34}
35
36static uint32_t getTypeLength(const PDBSymbol &Symbol) {
37 auto SymbolType = getSymbolType(Symbol);
38 const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();
39
40 return RawType.getLength();
41}
42
Zachary Turner16901642017-04-24 17:47:24 +000043LayoutItemBase::LayoutItemBase(const UDTLayoutBase *Parent,
44 const PDBSymbol *Symbol, const std::string &Name,
45 uint32_t OffsetInParent, uint32_t Size,
46 bool IsElided)
47 : Symbol(Symbol), Parent(Parent), Name(Name),
48 OffsetInParent(OffsetInParent), SizeOf(Size), LayoutSize(Size),
49 IsElided(IsElided) {
Zachary Turnerc883a8c2017-04-12 23:18:21 +000050 UsedBytes.resize(SizeOf, true);
51}
52
Zachary Turner16901642017-04-24 17:47:24 +000053uint32_t LayoutItemBase::deepPaddingSize() const {
54 return UsedBytes.size() - UsedBytes.count();
Zachary Turnerc883a8c2017-04-12 23:18:21 +000055}
56
Zachary Turner16901642017-04-24 17:47:24 +000057uint32_t LayoutItemBase::tailPadding() const {
58 int Last = UsedBytes.find_last();
59
60 return UsedBytes.size() - (Last + 1);
61}
62
Zachary Turnerc883a8c2017-04-12 23:18:21 +000063DataMemberLayoutItem::DataMemberLayoutItem(
Zachary Turner16901642017-04-24 17:47:24 +000064 const UDTLayoutBase &Parent, std::unique_ptr<PDBSymbolData> Member)
65 : LayoutItemBase(&Parent, Member.get(), Member->getName(),
66 Member->getOffset(), getTypeLength(*Member), false),
67 DataMember(std::move(Member)) {
68 auto Type = DataMember->getType();
Zachary Turnerc883a8c2017-04-12 23:18:21 +000069 if (auto UDT = unique_dyn_cast<PDBSymbolTypeUDT>(Type)) {
Zachary Turnerc883a8c2017-04-12 23:18:21 +000070 UdtLayout = llvm::make_unique<ClassLayout>(std::move(UDT));
Zachary Turner16901642017-04-24 17:47:24 +000071 UsedBytes = UdtLayout->usedBytes();
Zachary Turnerc883a8c2017-04-12 23:18:21 +000072 }
73}
74
Zachary Turner16901642017-04-24 17:47:24 +000075VBPtrLayoutItem::VBPtrLayoutItem(const UDTLayoutBase &Parent,
76 std::unique_ptr<PDBSymbolTypeBuiltin> Sym,
77 uint32_t Offset, uint32_t Size)
78 : LayoutItemBase(&Parent, Sym.get(), "<vbptr>", Offset, Size, false),
79 Type(std::move(Sym)) {
80}
81
Zachary Turnerc883a8c2017-04-12 23:18:21 +000082const PDBSymbolData &DataMemberLayoutItem::getDataMember() {
Zachary Turner16901642017-04-24 17:47:24 +000083 return *dyn_cast<PDBSymbolData>(Symbol);
Zachary Turnerc883a8c2017-04-12 23:18:21 +000084}
85
Zachary Turner4dc4f012017-04-13 21:11:00 +000086bool DataMemberLayoutItem::hasUDTLayout() const { return UdtLayout != nullptr; }
87
88const ClassLayout &DataMemberLayoutItem::getUDTLayout() const {
89 return *UdtLayout;
90}
91
Zachary Turnerc883a8c2017-04-12 23:18:21 +000092VTableLayoutItem::VTableLayoutItem(const UDTLayoutBase &Parent,
Zachary Turner16901642017-04-24 17:47:24 +000093 std::unique_ptr<PDBSymbolTypeVTable> VT)
94 : LayoutItemBase(&Parent, VT.get(), "<vtbl>", 0, getTypeLength(*VT), false),
95 VTable(std::move(VT)) {
96 auto VTableType = cast<PDBSymbolTypePointer>(VTable->getType());
Zachary Turner4dc4f012017-04-13 21:11:00 +000097 ElementSize = VTableType->getLength();
Zachary Turnerc883a8c2017-04-12 23:18:21 +000098}
99
Zachary Turner16901642017-04-24 17:47:24 +0000100UDTLayoutBase::UDTLayoutBase(const UDTLayoutBase *Parent, const PDBSymbol &Sym,
101 const std::string &Name, uint32_t OffsetInParent,
102 uint32_t Size, bool IsElided)
103 : LayoutItemBase(Parent, &Sym, Name, OffsetInParent, Size, IsElided) {
104 // UDT storage comes from a union of all the children's storage, so start out
105 // uninitialized.
106 UsedBytes.reset(0, Size);
107
108 initializeChildren(Sym);
109 if (LayoutSize < Size)
110 UsedBytes.resize(LayoutSize);
111}
112
113uint32_t UDTLayoutBase::tailPadding() const {
114 uint32_t Abs = LayoutItemBase::tailPadding();
115 if (!LayoutItems.empty()) {
116 const LayoutItemBase *Back = LayoutItems.back();
117 uint32_t ChildPadding = Back->LayoutItemBase::tailPadding();
118 if (Abs < ChildPadding)
119 Abs = 0;
120 else
121 Abs -= ChildPadding;
122 }
123 return Abs;
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000124}
125
Zachary Turner9e7dda32017-04-12 23:18:51 +0000126ClassLayout::ClassLayout(const PDBSymbolTypeUDT &UDT)
Zachary Turner16901642017-04-24 17:47:24 +0000127 : UDTLayoutBase(nullptr, UDT, UDT.getName(), 0, UDT.getLength(), false),
Zachary Turnerda307b62017-04-25 20:22:29 +0000128 UDT(UDT) {
129 ImmediateUsedBytes.resize(SizeOf, false);
130 for (auto &LI : LayoutItems) {
131 uint32_t Begin = LI->getOffsetInParent();
132 uint32_t End = Begin + LI->getLayoutSize();
133 End = std::min(SizeOf, End);
134 ImmediateUsedBytes.set(Begin, End);
135 }
136}
Zachary Turner9e7dda32017-04-12 23:18:51 +0000137
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000138ClassLayout::ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT)
Zachary Turner9e7dda32017-04-12 23:18:51 +0000139 : ClassLayout(*UDT) {
140 OwnedStorage = std::move(UDT);
141}
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000142
Zachary Turnerda307b62017-04-25 20:22:29 +0000143uint32_t ClassLayout::immediatePadding() const {
144 return SizeOf - ImmediateUsedBytes.count();
145}
146
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000147BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent,
Zachary Turner16901642017-04-24 17:47:24 +0000148 uint32_t OffsetInParent, bool Elide,
149 std::unique_ptr<PDBSymbolTypeBaseClass> B)
150 : UDTLayoutBase(&Parent, *B, B->getName(), OffsetInParent, B->getLength(),
151 Elide),
152 Base(std::move(B)) {
153 if (isEmptyBase()) {
154 // Special case an empty base so that it doesn't get treated as padding.
155 UsedBytes.resize(1);
156 UsedBytes.set(0);
157 }
158 IsVirtualBase = Base->isVirtualBaseClass();
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000159}
160
161void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) {
Zachary Turner4dc4f012017-04-13 21:11:00 +0000162 // Handled bases first, followed by VTables, followed by data members,
163 // followed by functions, followed by other. This ordering is necessary
164 // so that bases and vtables get initialized before any functions which
165 // may override them.
Zachary Turner4dc4f012017-04-13 21:11:00 +0000166 UniquePtrVector<PDBSymbolTypeBaseClass> Bases;
167 UniquePtrVector<PDBSymbolTypeVTable> VTables;
168 UniquePtrVector<PDBSymbolData> Members;
Zachary Turner16901642017-04-24 17:47:24 +0000169 UniquePtrVector<PDBSymbolTypeBaseClass> VirtualBaseSyms;
170
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000171 auto Children = Sym.findAllChildren();
172 while (auto Child = Children->getNext()) {
Zachary Turner4dc4f012017-04-13 21:11:00 +0000173 if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) {
174 if (Base->isVirtualBaseClass())
Zachary Turner16901642017-04-24 17:47:24 +0000175 VirtualBaseSyms.push_back(std::move(Base));
Zachary Turner4dc4f012017-04-13 21:11:00 +0000176 else
177 Bases.push_back(std::move(Base));
178 }
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000179
Zachary Turner4dc4f012017-04-13 21:11:00 +0000180 else if (auto Data = unique_dyn_cast<PDBSymbolData>(Child)) {
181 if (Data->getDataKind() == PDB_DataKind::Member)
182 Members.push_back(std::move(Data));
183 else
Zachary Turnerd334ceb2017-06-12 20:46:35 +0000184 Other.push_back(std::move(Data));
Zachary Turner4dc4f012017-04-13 21:11:00 +0000185 } else if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child))
186 VTables.push_back(std::move(VT));
187 else if (auto Func = unique_dyn_cast<PDBSymbolFunc>(Child))
188 Funcs.push_back(std::move(Func));
Zachary Turnerd334ceb2017-06-12 20:46:35 +0000189 else {
Zachary Turner4dc4f012017-04-13 21:11:00 +0000190 Other.push_back(std::move(Child));
Zachary Turnerd334ceb2017-06-12 20:46:35 +0000191 }
Zachary Turner4dc4f012017-04-13 21:11:00 +0000192 }
193
Zachary Turner16901642017-04-24 17:47:24 +0000194 // We don't want to have any re-allocations in the list of bases, so make
195 // sure to reserve enough space so that our ArrayRefs don't get invalidated.
196 AllBases.reserve(Bases.size() + VirtualBaseSyms.size());
Zachary Turner4dc4f012017-04-13 21:11:00 +0000197
Zachary Turner16901642017-04-24 17:47:24 +0000198 // Only add non-virtual bases to the class first. Only at the end of the
199 // class, after all non-virtual bases and data members have been added do we
200 // add virtual bases. This way the offsets are correctly aligned when we go
201 // to lay out virtual bases.
202 for (auto &Base : Bases) {
203 uint32_t Offset = Base->getOffset();
204 // Non-virtual bases never get elided.
205 auto BL = llvm::make_unique<BaseClassLayout>(*this, Offset, false,
206 std::move(Base));
207
208 AllBases.push_back(BL.get());
Zachary Turner4dc4f012017-04-13 21:11:00 +0000209 addChildToLayout(std::move(BL));
210 }
Zachary Turner16901642017-04-24 17:47:24 +0000211 NonVirtualBases = AllBases;
Zachary Turner4dc4f012017-04-13 21:11:00 +0000212
Zachary Turner16901642017-04-24 17:47:24 +0000213 assert(VTables.size() <= 1);
214 if (!VTables.empty()) {
215 auto VTLayout =
216 llvm::make_unique<VTableLayoutItem>(*this, std::move(VTables[0]));
Zachary Turner4dc4f012017-04-13 21:11:00 +0000217
218 VTable = VTLayout.get();
219
220 addChildToLayout(std::move(VTLayout));
Zachary Turner4dc4f012017-04-13 21:11:00 +0000221 }
222
223 for (auto &Data : Members) {
224 auto DM = llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data));
225
226 addChildToLayout(std::move(DM));
227 }
228
Zachary Turner16901642017-04-24 17:47:24 +0000229 // Make sure add virtual bases before adding functions, since functions may be
230 // overrides of virtual functions declared in a virtual base, so the VTables
231 // and virtual intros need to be correctly initialized.
232 for (auto &VB : VirtualBaseSyms) {
233 int VBPO = VB->getVirtualBasePointerOffset();
234 if (!hasVBPtrAtOffset(VBPO)) {
235 if (auto VBP = VB->getRawSymbol().getVirtualBaseTableType()) {
236 auto VBPL = llvm::make_unique<VBPtrLayoutItem>(*this, std::move(VBP),
237 VBPO, VBP->getLength());
238 VBPtr = VBPL.get();
239 addChildToLayout(std::move(VBPL));
Zachary Turner4dc4f012017-04-13 21:11:00 +0000240 }
241 }
Zachary Turner4dc4f012017-04-13 21:11:00 +0000242
Zachary Turner16901642017-04-24 17:47:24 +0000243 // Virtual bases always go at the end. So just look for the last place we
244 // ended when writing something, and put our virtual base there.
245 // Note that virtual bases get elided unless this is a top-most derived
246 // class.
247 uint32_t Offset = UsedBytes.find_last() + 1;
248 bool Elide = (Parent != nullptr);
249 auto BL =
250 llvm::make_unique<BaseClassLayout>(*this, Offset, Elide, std::move(VB));
251 AllBases.push_back(BL.get());
252
253 // Only lay this virtual base out directly inside of *this* class if this
254 // is a top-most derived class. Keep track of it regardless, but only
255 // physically lay it out if it's a topmost derived class.
256 addChildToLayout(std::move(BL));
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000257 }
Zachary Turner16901642017-04-24 17:47:24 +0000258 VirtualBases = makeArrayRef(AllBases).drop_front(NonVirtualBases.size());
259
260 if (Parent != nullptr)
261 LayoutSize = UsedBytes.find_last() + 1;
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000262}
263
Zachary Turner16901642017-04-24 17:47:24 +0000264bool UDTLayoutBase::hasVBPtrAtOffset(uint32_t Off) const {
265 if (VBPtr && VBPtr->getOffsetInParent() == Off)
266 return true;
267 for (BaseClassLayout *BL : AllBases) {
268 if (BL->hasVBPtrAtOffset(Off - BL->getOffsetInParent()))
269 return true;
270 }
271 return false;
272}
273
274void UDTLayoutBase::addChildToLayout(std::unique_ptr<LayoutItemBase> Child) {
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000275 uint32_t Begin = Child->getOffsetInParent();
Zachary Turner4dc4f012017-04-13 21:11:00 +0000276
Zachary Turner16901642017-04-24 17:47:24 +0000277 if (!Child->isElided()) {
278 BitVector ChildBytes = Child->usedBytes();
279
280 // Suppose the child occupies 4 bytes starting at offset 12 in a 32 byte
281 // class. When we call ChildBytes.resize(32), the Child's storage will
282 // still begin at offset 0, so we need to shift it left by offset bytes
283 // to get it into the right position.
284 ChildBytes.resize(UsedBytes.size());
285 ChildBytes <<= Child->getOffsetInParent();
286 UsedBytes |= ChildBytes;
287
288 if (ChildBytes.count() > 0) {
289 auto Loc = std::upper_bound(LayoutItems.begin(), LayoutItems.end(), Begin,
290 [](uint32_t Off, const LayoutItemBase *Item) {
291 return (Off < Item->getOffsetInParent());
292 });
293
294 LayoutItems.insert(Loc, Child.get());
295 }
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000296 }
297
Zachary Turner16901642017-04-24 17:47:24 +0000298 ChildStorage.push_back(std::move(Child));
Zachary Turnerc883a8c2017-04-12 23:18:21 +0000299}