LLVM  15.0.0git
GSIStreamBuilder.cpp
Go to the documentation of this file.
1 //===- DbiStreamBuilder.cpp - PDB Dbi Stream Creation -----------*- C++ -*-===//
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 //
9 // The data structures defined in this file are based on the reference
10 // implementation which is available at
11 // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.cpp
12 //
13 //===----------------------------------------------------------------------===//
14 
28 #include "llvm/Support/Parallel.h"
29 #include "llvm/Support/xxhash.h"
30 #include <algorithm>
31 #include <vector>
32 
33 using namespace llvm;
34 using namespace llvm::msf;
35 using namespace llvm::pdb;
36 using namespace llvm::codeview;
37 
38 // Helper class for building the public and global PDB hash table buckets.
40  // Sum of the size of all public or global records.
41  uint32_t RecordByteSize = 0;
42 
43  std::vector<PSHashRecord> HashRecords;
44 
45  // The hash bitmap has `ceil((IPHR_HASH + 1) / 32)` words in it. The
46  // reference implementation builds a hash table with IPHR_HASH buckets in it.
47  // The last bucket is used to link together free hash table cells in a linked
48  // list, but it is always empty in the compressed, on-disk format. However,
49  // the bitmap must have a bit for it.
50  std::array<support::ulittle32_t, (IPHR_HASH + 32) / 32> HashBitmap;
51 
52  std::vector<support::ulittle32_t> HashBuckets;
53 
54  uint32_t calculateSerializedLength() const;
55  Error commit(BinaryStreamWriter &Writer);
56 
57  void finalizePublicBuckets();
58  void finalizeGlobalBuckets(uint32_t RecordZeroOffset);
59 
60  // Assign public and global symbol records into hash table buckets.
61  // Modifies the list of records to store the bucket index, but does not
62  // change the order.
63  void finalizeBuckets(uint32_t RecordZeroOffset,
65 };
66 
67 // DenseMapInfo implementation for deduplicating symbol records.
69  static inline CVSymbol getEmptyKey() {
70  static CVSymbol Empty;
71  return Empty;
72  }
73  static inline CVSymbol getTombstoneKey() {
74  static CVSymbol Tombstone(
75  DenseMapInfo<ArrayRef<uint8_t>>::getTombstoneKey());
76  return Tombstone;
77  }
78  static unsigned getHashValue(const CVSymbol &Val) {
79  return xxHash64(Val.RecordData);
80  }
81  static bool isEqual(const CVSymbol &LHS, const CVSymbol &RHS) {
82  return LHS.RecordData == RHS.RecordData;
83  }
84 };
85 
86 namespace {
88 struct PublicSym32Layout {
91  // char Name[];
92 };
94 } // namespace
95 
96 // Calculate how much memory this public needs when serialized.
97 static uint32_t sizeOfPublic(const BulkPublic &Pub) {
98  uint32_t NameLen = Pub.NameLen;
99  NameLen = std::min(NameLen,
100  uint32_t(MaxRecordLength - sizeof(PublicSym32Layout) - 1));
101  return alignTo(sizeof(PublicSym32Layout) + NameLen + 1, 4);
102 }
103 
104 static CVSymbol serializePublic(uint8_t *Mem, const BulkPublic &Pub) {
105  // Assume the caller has allocated sizeOfPublic bytes.
106  uint32_t NameLen = std::min(
107  Pub.NameLen, uint32_t(MaxRecordLength - sizeof(PublicSym32Layout) - 1));
108  size_t Size = alignTo(sizeof(PublicSym32Layout) + NameLen + 1, 4);
109  assert(Size == sizeOfPublic(Pub));
110  auto *FixedMem = reinterpret_cast<PublicSym32Layout *>(Mem);
111  FixedMem->Prefix.RecordKind = static_cast<uint16_t>(codeview::S_PUB32);
112  FixedMem->Prefix.RecordLen = static_cast<uint16_t>(Size - 2);
113  FixedMem->Pub.Flags = Pub.Flags;
114  FixedMem->Pub.Offset = Pub.Offset;
115  FixedMem->Pub.Segment = Pub.Segment;
116  char *NameMem = reinterpret_cast<char *>(FixedMem + 1);
117  memcpy(NameMem, Pub.Name, NameLen);
118  // Zero the null terminator and remaining bytes.
119  memset(&NameMem[NameLen], 0, Size - sizeof(PublicSym32Layout) - NameLen);
120  return CVSymbol(makeArrayRef(reinterpret_cast<uint8_t *>(Mem), Size));
121 }
122 
123 uint32_t GSIHashStreamBuilder::calculateSerializedLength() const {
124  uint32_t Size = sizeof(GSIHashHeader);
125  Size += HashRecords.size() * sizeof(PSHashRecord);
126  Size += HashBitmap.size() * sizeof(uint32_t);
127  Size += HashBuckets.size() * sizeof(uint32_t);
128  return Size;
129 }
130 
131 Error GSIHashStreamBuilder::commit(BinaryStreamWriter &Writer) {
132  GSIHashHeader Header;
133  Header.VerSignature = GSIHashHeader::HdrSignature;
134  Header.VerHdr = GSIHashHeader::HdrVersion;
135  Header.HrSize = HashRecords.size() * sizeof(PSHashRecord);
136  Header.NumBuckets = HashBitmap.size() * 4 + HashBuckets.size() * 4;
137 
138  if (auto EC = Writer.writeObject(Header))
139  return EC;
140 
141  if (auto EC = Writer.writeArray(makeArrayRef(HashRecords)))
142  return EC;
143  if (auto EC = Writer.writeArray(makeArrayRef(HashBitmap)))
144  return EC;
145  if (auto EC = Writer.writeArray(makeArrayRef(HashBuckets)))
146  return EC;
147  return Error::success();
148 }
149 
150 static bool isAsciiString(StringRef S) {
151  return llvm::all_of(S, [](char C) { return unsigned(C) < 0x80; });
152 }
153 
154 // See `caseInsensitiveComparePchPchCchCch` in gsi.cpp
155 static int gsiRecordCmp(StringRef S1, StringRef S2) {
156  size_t LS = S1.size();
157  size_t RS = S2.size();
158  // Shorter strings always compare less than longer strings.
159  if (LS != RS)
160  return (LS > RS) - (LS < RS);
161 
162  // If either string contains non ascii characters, memcmp them.
163  if (LLVM_UNLIKELY(!isAsciiString(S1) || !isAsciiString(S2)))
164  return memcmp(S1.data(), S2.data(), LS);
165 
166  // Both strings are ascii, perform a case-insensitive comparison.
167  return S1.compare_insensitive(S2.data());
168 }
169 
170 void GSIStreamBuilder::finalizePublicBuckets() {
171  PSH->finalizeBuckets(0, Publics);
172 }
173 
174 void GSIStreamBuilder::finalizeGlobalBuckets(uint32_t RecordZeroOffset) {
175  // Build up a list of globals to be bucketed. Use the BulkPublic data
176  // structure for this purpose, even though these are global records, not
177  // public records. Most of the same fields are required:
178  // - Name
179  // - NameLen
180  // - SymOffset
181  // - BucketIdx
182  // The dead fields are Offset, Segment, and Flags.
183  std::vector<BulkPublic> Records;
184  Records.resize(Globals.size());
185  uint32_t SymOffset = RecordZeroOffset;
186  for (size_t I = 0, E = Globals.size(); I < E; ++I) {
187  StringRef Name = getSymbolName(Globals[I]);
188  Records[I].Name = Name.data();
189  Records[I].NameLen = Name.size();
190  Records[I].SymOffset = SymOffset;
191  SymOffset += Globals[I].length();
192  }
193 
194  GSH->finalizeBuckets(RecordZeroOffset, Records);
195 }
196 
197 void GSIHashStreamBuilder::finalizeBuckets(
198  uint32_t RecordZeroOffset, MutableArrayRef<BulkPublic> Records) {
199  // Hash every name in parallel.
200  parallelFor(0, Records.size(), [&](size_t I) {
201  Records[I].setBucketIdx(hashStringV1(Records[I].Name) % IPHR_HASH);
202  });
203 
204  // Count up the size of each bucket. Then, use an exclusive prefix sum to
205  // calculate the bucket start offsets. This is C++17 std::exclusive_scan, but
206  // we can't use it yet.
207  uint32_t BucketStarts[IPHR_HASH] = {0};
208  for (const BulkPublic &P : Records)
209  ++BucketStarts[P.BucketIdx];
210  uint32_t Sum = 0;
211  for (uint32_t &B : BucketStarts) {
212  uint32_t Size = B;
213  B = Sum;
214  Sum += Size;
215  }
216 
217  // Place globals into the hash table in bucket order. When placing a global,
218  // update the bucket start. Every hash table slot should be filled. Always use
219  // a refcount of one for now.
220  HashRecords.resize(Records.size());
221  uint32_t BucketCursors[IPHR_HASH];
222  memcpy(BucketCursors, BucketStarts, sizeof(BucketCursors));
223  for (int I = 0, E = Records.size(); I < E; ++I) {
224  uint32_t HashIdx = BucketCursors[Records[I].BucketIdx]++;
225  HashRecords[HashIdx].Off = I;
226  HashRecords[HashIdx].CRef = 1;
227  }
228 
229  // Within the buckets, sort each bucket by memcmp of the symbol's name. It's
230  // important that we use the same sorting algorithm as is used by the
231  // reference implementation to ensure that the search for a record within a
232  // bucket can properly early-out when it detects the record won't be found.
233  // The algorithm used here corresponds to the function
234  // caseInsensitiveComparePchPchCchCch in the reference implementation.
235  parallelFor(0, IPHR_HASH, [&](size_t I) {
236  auto B = HashRecords.begin() + BucketStarts[I];
237  auto E = HashRecords.begin() + BucketCursors[I];
238  if (B == E)
239  return;
240  auto BucketCmp = [Records](const PSHashRecord &LHash,
241  const PSHashRecord &RHash) {
242  const BulkPublic &L = Records[uint32_t(LHash.Off)];
243  const BulkPublic &R = Records[uint32_t(RHash.Off)];
244  assert(L.BucketIdx == R.BucketIdx);
245  int Cmp = gsiRecordCmp(L.getName(), R.getName());
246  if (Cmp != 0)
247  return Cmp < 0;
248  // This comparison is necessary to make the sorting stable in the presence
249  // of two static globals with the same name. The easiest way to observe
250  // this is with S_LDATA32 records.
251  return L.SymOffset < R.SymOffset;
252  };
253  llvm::sort(B, E, BucketCmp);
254 
255  // After we are done sorting, replace the global indices with the stream
256  // offsets of each global. Add one when writing symbol offsets to disk.
257  // See GSI1::fixSymRecs.
258  for (PSHashRecord &HRec : make_range(B, E))
259  HRec.Off = Records[uint32_t(HRec.Off)].SymOffset + 1;
260  });
261 
262  // For each non-empty bucket, push the bucket start offset into HashBuckets
263  // and set a bit in the hash bitmap.
264  for (uint32_t I = 0; I < HashBitmap.size(); ++I) {
265  uint32_t Word = 0;
266  for (uint32_t J = 0; J < 32; ++J) {
267  // Skip empty buckets.
268  uint32_t BucketIdx = I * 32 + J;
269  if (BucketIdx >= IPHR_HASH ||
270  BucketStarts[BucketIdx] == BucketCursors[BucketIdx])
271  continue;
272  Word |= (1U << J);
273 
274  // Calculate what the offset of the first hash record in the chain would
275  // be if it were inflated to contain 32-bit pointers. On a 32-bit system,
276  // each record would be 12 bytes. See HROffsetCalc in gsi.h.
277  const int SizeOfHROffsetCalc = 12;
278  ulittle32_t ChainStartOff =
279  ulittle32_t(BucketStarts[BucketIdx] * SizeOfHROffsetCalc);
280  HashBuckets.push_back(ChainStartOff);
281  }
282  HashBitmap[I] = Word;
283  }
284 }
285 
286 GSIStreamBuilder::GSIStreamBuilder(msf::MSFBuilder &Msf)
287  : Msf(Msf), PSH(std::make_unique<GSIHashStreamBuilder>()),
288  GSH(std::make_unique<GSIHashStreamBuilder>()) {}
289 
291 
292 uint32_t GSIStreamBuilder::calculatePublicsHashStreamSize() const {
293  uint32_t Size = 0;
294  Size += sizeof(PublicsStreamHeader);
295  Size += PSH->calculateSerializedLength();
296  Size += Publics.size() * sizeof(uint32_t); // AddrMap
297  // FIXME: Add thunk map and section offsets for incremental linking.
298 
299  return Size;
300 }
301 
302 uint32_t GSIStreamBuilder::calculateGlobalsHashStreamSize() const {
303  return GSH->calculateSerializedLength();
304 }
305 
307  // First we write public symbol records, then we write global symbol records.
308  finalizePublicBuckets();
309  finalizeGlobalBuckets(PSH->RecordByteSize);
310 
311  Expected<uint32_t> Idx = Msf.addStream(calculateGlobalsHashStreamSize());
312  if (!Idx)
313  return Idx.takeError();
314  GlobalsStreamIndex = *Idx;
315 
316  Idx = Msf.addStream(calculatePublicsHashStreamSize());
317  if (!Idx)
318  return Idx.takeError();
319  PublicsStreamIndex = *Idx;
320 
321  uint32_t RecordBytes = PSH->RecordByteSize + GSH->RecordByteSize;
322 
323  Idx = Msf.addStream(RecordBytes);
324  if (!Idx)
325  return Idx.takeError();
326  RecordStreamIndex = *Idx;
327  return Error::success();
328 }
329 
330 void GSIStreamBuilder::addPublicSymbols(std::vector<BulkPublic> &&PublicsIn) {
331  assert(Publics.empty() && PSH->RecordByteSize == 0 &&
332  "publics can only be added once");
333  Publics = std::move(PublicsIn);
334 
335  // Sort the symbols by name. PDBs contain lots of symbols, so use parallelism.
336  parallelSort(Publics, [](const BulkPublic &L, const BulkPublic &R) {
337  return L.getName() < R.getName();
338  });
339 
340  // Assign offsets and calculate the length of the public symbol records.
341  uint32_t SymOffset = 0;
342  for (BulkPublic &Pub : Publics) {
343  Pub.SymOffset = SymOffset;
344  SymOffset += sizeOfPublic(Pub);
345  }
346 
347  // Remember the length of the public stream records.
348  PSH->RecordByteSize = SymOffset;
349 }
350 
352  serializeAndAddGlobal(Sym);
353 }
354 
356  serializeAndAddGlobal(Sym);
357 }
358 
360  serializeAndAddGlobal(Sym);
361 }
362 
363 template <typename T>
364 void GSIStreamBuilder::serializeAndAddGlobal(const T &Symbol) {
365  T Copy(Symbol);
366  addGlobalSymbol(SymbolSerializer::writeOneSymbol(Copy, Msf.getAllocator(),
367  CodeViewContainer::Pdb));
368 }
369 
371  // Ignore duplicate typedefs and constants.
372  if (Symbol.kind() == S_UDT || Symbol.kind() == S_CONSTANT) {
373  auto Iter = GlobalsSeen.insert(Symbol);
374  if (!Iter.second)
375  return;
376  }
377  GSH->RecordByteSize += Symbol.length();
378  Globals.push_back(Symbol);
379 }
380 
381 // Serialize each public and write it.
383  ArrayRef<BulkPublic> Publics) {
384  std::vector<uint8_t> Storage;
385  for (const BulkPublic &Pub : Publics) {
386  Storage.resize(sizeOfPublic(Pub));
387  serializePublic(Storage.data(), Pub);
388  if (Error E = Writer.writeBytes(Storage))
389  return E;
390  }
391  return Error::success();
392 }
393 
395  ArrayRef<CVSymbol> Records) {
397  ItemStream.setItems(Records);
398  BinaryStreamRef RecordsRef(ItemStream);
399  return Writer.writeStreamRef(RecordsRef);
400 }
401 
402 Error GSIStreamBuilder::commitSymbolRecordStream(
403  WritableBinaryStreamRef Stream) {
404  BinaryStreamWriter Writer(Stream);
405 
406  // Write public symbol records first, followed by global symbol records. This
407  // must match the order that we assume in finalizeMsfLayout when computing
408  // PSHZero and GSHZero.
409  if (auto EC = writePublics(Writer, Publics))
410  return EC;
411  if (auto EC = writeRecords(Writer, Globals))
412  return EC;
413 
414  return Error::success();
415 }
416 
417 static std::vector<support::ulittle32_t>
419  // Build a parallel vector of indices into the Publics vector, and sort it by
420  // address.
421  std::vector<ulittle32_t> PubAddrMap;
422  PubAddrMap.reserve(Publics.size());
423  for (int I = 0, E = Publics.size(); I < E; ++I)
424  PubAddrMap.push_back(ulittle32_t(I));
425 
426  auto AddrCmp = [Publics](const ulittle32_t &LIdx, const ulittle32_t &RIdx) {
427  const BulkPublic &L = Publics[LIdx];
428  const BulkPublic &R = Publics[RIdx];
429  if (L.Segment != R.Segment)
430  return L.Segment < R.Segment;
431  if (L.Offset != R.Offset)
432  return L.Offset < R.Offset;
433  // parallelSort is unstable, so we have to do name comparison to ensure
434  // that two names for the same location come out in a deterministic order.
435  return L.getName() < R.getName();
436  };
437  parallelSort(PubAddrMap, AddrCmp);
438 
439  // Rewrite the public symbol indices into symbol offsets.
440  for (ulittle32_t &Entry : PubAddrMap)
441  Entry = Publics[Entry].SymOffset;
442  return PubAddrMap;
443 }
444 
445 Error GSIStreamBuilder::commitPublicsHashStream(
446  WritableBinaryStreamRef Stream) {
447  BinaryStreamWriter Writer(Stream);
448  PublicsStreamHeader Header;
449 
450  // FIXME: Fill these in. They are for incremental linking.
451  Header.SymHash = PSH->calculateSerializedLength();
452  Header.AddrMap = Publics.size() * 4;
453  Header.NumThunks = 0;
454  Header.SizeOfThunk = 0;
455  Header.ISectThunkTable = 0;
456  memset(Header.Padding, 0, sizeof(Header.Padding));
457  Header.OffThunkTable = 0;
458  Header.NumSections = 0;
459  if (auto EC = Writer.writeObject(Header))
460  return EC;
461 
462  if (auto EC = PSH->commit(Writer))
463  return EC;
464 
465  std::vector<support::ulittle32_t> PubAddrMap = computeAddrMap(Publics);
466  assert(PubAddrMap.size() == Publics.size());
467  if (auto EC = Writer.writeArray(makeArrayRef(PubAddrMap)))
468  return EC;
469 
470  return Error::success();
471 }
472 
473 Error GSIStreamBuilder::commitGlobalsHashStream(
474  WritableBinaryStreamRef Stream) {
475  BinaryStreamWriter Writer(Stream);
476  return GSH->commit(Writer);
477 }
478 
480  WritableBinaryStreamRef Buffer) {
481  auto GS = WritableMappedBlockStream::createIndexedStream(
482  Layout, Buffer, getGlobalsStreamIndex(), Msf.getAllocator());
483  auto PS = WritableMappedBlockStream::createIndexedStream(
484  Layout, Buffer, getPublicsStreamIndex(), Msf.getAllocator());
485  auto PRS = WritableMappedBlockStream::createIndexedStream(
486  Layout, Buffer, getRecordStreamIndex(), Msf.getAllocator());
487 
488  if (auto EC = commitSymbolRecordStream(*PRS))
489  return EC;
490  if (auto EC = commitGlobalsHashStream(*GS))
491  return EC;
492  if (auto EC = commitPublicsHashStream(*PS))
493  return EC;
494  return Error::success();
495 }
llvm::alignTo
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:156
LLVM_PACKED_END
#define LLVM_PACKED_END
Definition: Compiler.h:396
llvm::pdb::BulkPublic::Offset
uint32_t Offset
Definition: GSIStreamBuilder.h:118
llvm::pdb::SymbolDenseMapInfo::getEmptyKey
static CVSymbol getEmptyKey()
Definition: GSIStreamBuilder.cpp:69
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::make_range
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Definition: iterator_range.h:53
LLVM_PACKED_START
#define LLVM_PACKED_START
Definition: Compiler.h:395
llvm::pdb::GSIHashStreamBuilder::HashRecords
std::vector< PSHashRecord > HashRecords
Definition: GSIStreamBuilder.cpp:43
llvm::pdb::PublicsStreamHeader::SizeOfThunk
support::ulittle32_t SizeOfThunk
Definition: RawTypes.h:268
RecordSerialization.h
llvm::pdb::PublicsStreamHeader::AddrMap
support::ulittle32_t AddrMap
Definition: RawTypes.h:266
llvm::cl::Prefix
@ Prefix
Definition: CommandLine.h:160
RawTypes.h
T
llvm::pdb::GSIStreamBuilder::getGlobalsStreamIndex
uint32_t getGlobalsStreamIndex() const
Definition: GSIStreamBuilder.h:60
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
llvm::pdb::GSIHashHeader::HrSize
support::ulittle32_t HrSize
Definition: RawTypes.h:35
llvm::pdb::PublicsStreamHeader::ISectThunkTable
support::ulittle16_t ISectThunkTable
Definition: RawTypes.h:269
llvm::pdb::GSIStreamBuilder::getPublicsStreamIndex
uint32_t getPublicsStreamIndex() const
Definition: GSIStreamBuilder.h:59
SymbolRecord.h
llvm::BinaryStreamWriter
Provides write only access to a subclass of WritableBinaryStream.
Definition: BinaryStreamWriter.h:30
llvm::pdb::SymbolDenseMapInfo
Definition: GSIStreamBuilder.cpp:68
llvm::codeview::DataSym
Definition: SymbolRecord.h:936
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::pdb::GSIHashStreamBuilder
Definition: GSIStreamBuilder.cpp:39
llvm::BinaryStreamWriter::writeStreamRef
Error writeStreamRef(BinaryStreamRef Ref)
Efficiently reads all data from Ref, and writes it to this stream.
Definition: BinaryStreamWriter.cpp:60
memcmp
Merge contiguous icmps into a memcmp
Definition: MergeICmps.cpp:899
writeRecords
static Error writeRecords(BinaryStreamWriter &Writer, ArrayRef< CVSymbol > Records)
Definition: GSIStreamBuilder.cpp:394
llvm::pdb::GSIHashHeader::VerSignature
support::ulittle32_t VerSignature
Definition: RawTypes.h:33
RecordName.h
GSIStreamBuilder.h
llvm::pdb::GSIStreamBuilder::~GSIStreamBuilder
~GSIStreamBuilder()
llvm::msf::MSFBuilder::addStream
Expected< uint32_t > addStream(uint32_t Size, ArrayRef< uint32_t > Blocks)
Add a stream to the MSF file with the given size, occupying the given list of blocks.
Definition: MSFBuilder.cpp:155
llvm::BinaryStreamWriter::writeArray
Error writeArray(ArrayRef< T > Array)
Writes an array of objects of type T to the underlying stream, as if by using memcpy.
Definition: BinaryStreamWriter.h:145
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
RHS
Value * RHS
Definition: X86PartialReduction.cpp:76
llvm::codeview::RecordPrefix
Definition: RecordSerialization.h:32
llvm::codeview::CVRecord::RecordData
ArrayRef< uint8_t > RecordData
Definition: CVRecord.h:60
llvm::msf
Definition: IMSFFile.h:18
llvm::msf::MSFBuilder
Definition: MSFBuilder.h:27
llvm::pdb::GSIHashHeader
Header of the hash tables found in the globals and publics sections.
Definition: RawTypes.h:28
llvm::pdb::BulkPublic::SymOffset
uint32_t SymOffset
Definition: GSIStreamBuilder.h:115
llvm::pdb::BulkPublic::getName
StringRef getName() const
Definition: GSIStreamBuilder.h:140
LHS
Value * LHS
Definition: X86PartialReduction.cpp:75
llvm::DenseMapInfo
An information struct used to provide DenseMap with the various necessary components for a given valu...
Definition: APInt.h:34
llvm::DwarfLinkerAccelTableKind::Pub
@ Pub
.debug_pubnames, .debug_pubtypes
llvm::all_of
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1617
llvm::pdb::GSIStreamBuilder::getRecordStreamIndex
uint32_t getRecordStreamIndex() const
Definition: GSIStreamBuilder.h:61
llvm::codeview::ConstantSym
Definition: SymbolRecord.h:921
GlobalsStream.h
llvm::MutableArrayRef
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:306
writePublics
static Error writePublics(BinaryStreamWriter &Writer, ArrayRef< BulkPublic > Publics)
Definition: GSIStreamBuilder.cpp:382
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::support::little
@ little
Definition: Endian.h:27
llvm::msf::MSFLayout
Definition: MSFCommon.h:51
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
Parallel.h
serializePublic
static CVSymbol serializePublic(uint8_t *Mem, const BulkPublic &Pub)
Definition: GSIStreamBuilder.cpp:104
llvm::codeview::CVSymbol
CVRecord< SymbolKind > CVSymbol
Definition: CVRecord.h:65
llvm::codeview::MaxRecordLength
@ MaxRecordLength
Definition: RecordSerialization.h:30
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::pdb::GSIStreamBuilder::addGlobalSymbol
void addGlobalSymbol(const codeview::ProcRefSym &Sym)
Definition: GSIStreamBuilder.cpp:351
llvm::pdb::GSIHashStreamBuilder::HashBuckets
std::vector< support::ulittle32_t > HashBuckets
Definition: GSIStreamBuilder.cpp:52
MSFBuilder.h
llvm::pdb::GSIHashHeader::NumBuckets
support::ulittle32_t NumBuckets
Definition: RawTypes.h:36
llvm::pdb
Definition: ConcreteSymbolEnumerator.h:20
llvm::pdb::SymbolDenseMapInfo::isEqual
static bool isEqual(const CVSymbol &LHS, const CVSymbol &RHS)
Definition: GSIStreamBuilder.cpp:81
llvm::pdb::GSIHashHeader::VerHdr
support::ulittle32_t VerHdr
Definition: RawTypes.h:34
llvm::pdb::PSHashRecord
Definition: RawTypes.h:40
llvm::support::ulittle32_t
detail::packed_endian_specific_integral< uint32_t, little, unaligned > ulittle32_t
Definition: Endian.h:272
llvm::pdb::IPHR_HASH
@ IPHR_HASH
Definition: GlobalsStream.h:45
BinaryItemStream.h
llvm::pdb::PublicsStreamHeader::OffThunkTable
support::ulittle32_t OffThunkTable
Definition: RawTypes.h:271
llvm::pdb::BulkPublic
This struct is equivalent to codeview::PublicSym32, but it has been optimized for size to speed up bu...
Definition: GSIStreamBuilder.h:108
llvm::pdb::PublicsStreamHeader::SymHash
support::ulittle32_t SymHash
Definition: RawTypes.h:265
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::BulkPublic::Segment
uint16_t Segment
Definition: GSIStreamBuilder.h:121
llvm::codeview::FrameCookieKind::Copy
@ Copy
llvm::pdb::Empty
@ Empty
Definition: PDBTypes.h:395
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::pdb::GSIStreamBuilder::finalizeMsfLayout
Error finalizeMsfLayout()
Definition: GSIStreamBuilder.cpp:306
MappedBlockStream.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
llvm::codeview::CompileSym2Flags::EC
@ EC
llvm::pdb::GSIStreamBuilder::commit
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer)
Definition: GSIStreamBuilder.cpp:479
SymbolSerializer.h
llvm::BinaryItemStream::setItems
void setItems(ArrayRef< T > ItemArray)
Definition: BinaryItemStream.h:64
llvm::pdb::GSIStreamBuilder::addPublicSymbols
void addPublicSymbols(std::vector< BulkPublic > &&PublicsIn)
Definition: GSIStreamBuilder.cpp:330
llvm::pdb::BulkPublic::BucketIdx
uint16_t BucketIdx
Definition: GSIStreamBuilder.h:127
llvm::irsymtab::storage::Word
support::ulittle32_t Word
Definition: IRSymtab.h:52
xxhash.h
llvm::pdb::PSHashRecord::Off
support::ulittle32_t Off
Definition: RawTypes.h:41
llvm::ArrayRef< uint8_t >
llvm::BinaryStreamWriter::writeObject
Error writeObject(const T &Obj)
Writes the object Obj to the underlying stream, as if by using memcpy.
Definition: BinaryStreamWriter.h:129
llvm::min
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
Definition: FileCheck.cpp:357
computeAddrMap
static std::vector< support::ulittle32_t > computeAddrMap(ArrayRef< BulkPublic > Publics)
Definition: GSIStreamBuilder.cpp:418
llvm::BinaryStreamWriter::writeBytes
Error writeBytes(ArrayRef< uint8_t > Buffer)
Write the bytes specified in Buffer to the underlying stream.
Definition: BinaryStreamWriter.cpp:27
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::codeview::CVRecord
CVRecord is a fat pointer (base + size pair) to a symbol or type record.
Definition: CVRecord.h:29
llvm::parallelSort
void parallelSort(RandomAccessIterator Start, RandomAccessIterator End, const Comparator &Comp=Comparator())
Definition: Parallel.h:185
uint32_t
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
MSFCommon.h
sizeOfPublic
static uint32_t sizeOfPublic(const BulkPublic &Pub)
Definition: GSIStreamBuilder.cpp:97
llvm::pdb::SymbolDenseMapInfo::getHashValue
static unsigned getHashValue(const CVSymbol &Val)
Definition: GSIStreamBuilder.cpp:78
llvm::msf::MSFBuilder::getAllocator
BumpPtrAllocator & getAllocator()
Definition: MSFBuilder.h:119
llvm::StringRef::size
constexpr LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:157
llvm::pdb::PublicsStreamHeader::Padding
char Padding[2]
Definition: RawTypes.h:270
llvm::parallelFor
void parallelFor(size_t Begin, size_t End, function_ref< void(size_t)> Fn)
Definition: Parallel.cpp:178
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
std
Definition: BitVector.h:851
uint16_t
llvm::X86AS::GS
@ GS
Definition: X86.h:191
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::AArch64CC::LS
@ LS
Definition: AArch64BaseInfo.h:264
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1562
llvm::pdb::SymbolDenseMapInfo::getTombstoneKey
static CVSymbol getTombstoneKey()
Definition: GSIStreamBuilder.cpp:73
llvm::codeview::PublicSym32Header
Definition: SymbolRecord.h:353
llvm::BinaryItemStream
BinaryItemStream represents a sequence of objects stored in some kind of external container but for w...
Definition: BinaryItemStream.h:34
llvm::codeview
Definition: AppendingTypeTableBuilder.h:22
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::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:597
llvm::pdb::PublicsStreamHeader::NumSections
support::ulittle32_t NumSections
Definition: RawTypes.h:272
llvm::StringRef::compare_insensitive
LLVM_NODISCARD int compare_insensitive(StringRef RHS) const
Compare two strings, ignoring case.
Definition: StringRef.cpp:37
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:164
llvm::StringRef::data
const LLVM_NODISCARD char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:149
isAsciiString
static bool isAsciiString(StringRef S)
Definition: GSIStreamBuilder.cpp:150
Hash.h
BinaryStreamWriter.h
llvm::pdb::PublicsStreamHeader::NumThunks
support::ulittle32_t NumThunks
Definition: RawTypes.h:267
LLVM_UNLIKELY
#define LLVM_UNLIKELY(EXPR)
Definition: Compiler.h:220
llvm::codeview::ProcRefSym
Definition: SymbolRecord.h:393
getSymbolName
static StringRef getSymbolName(SymbolKind SymKind)
Definition: CodeViewDebug.cpp:3104
llvm::pdb::PublicsStreamHeader
Definition: RawTypes.h:264
gsiRecordCmp
static int gsiRecordCmp(StringRef S1, StringRef S2)
Definition: GSIStreamBuilder.cpp:155
llvm::WritableBinaryStreamRef
Definition: BinaryStreamRef.h:220
llvm::xxHash64
uint64_t xxHash64(llvm::StringRef Data)
Definition: xxhash.cpp:70
llvm::BinaryStreamRef
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
Definition: BinaryStreamRef.h:155