LLVM  16.0.0git
TypeStreamMerger.cpp
Go to the documentation of this file.
1 //===-- TypeStreamMerger.cpp ------------------------------------*- 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 
10 #include "llvm/ADT/Optional.h"
11 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/Support/Error.h"
20 #include <optional>
21 
22 using namespace llvm;
23 using namespace llvm::codeview;
24 
25 static inline size_t slotForIndex(TypeIndex Idx) {
26  assert(!Idx.isSimple() && "simple type indices have no slots");
28 }
29 
30 namespace {
31 
32 /// Implementation of CodeView type stream merging.
33 ///
34 /// A CodeView type stream is a series of records that reference each other
35 /// through type indices. A type index is either "simple", meaning it is less
36 /// than 0x1000 and refers to a builtin type, or it is complex, meaning it
37 /// refers to a prior type record in the current stream. The type index of a
38 /// record is equal to the number of records before it in the stream plus
39 /// 0x1000.
40 ///
41 /// Type records are only allowed to use type indices smaller than their own, so
42 /// a type stream is effectively a topologically sorted DAG. Cycles occurring in
43 /// the type graph of the source program are resolved with forward declarations
44 /// of composite types. This class implements the following type stream merging
45 /// algorithm, which relies on this DAG structure:
46 ///
47 /// - Begin with a new empty stream, and a new empty hash table that maps from
48 /// type record contents to new type index.
49 /// - For each new type stream, maintain a map from source type index to
50 /// destination type index.
51 /// - For each record, copy it and rewrite its type indices to be valid in the
52 /// destination type stream.
53 /// - If the new type record is not already present in the destination stream
54 /// hash table, append it to the destination type stream, assign it the next
55 /// type index, and update the two hash tables.
56 /// - If the type record already exists in the destination stream, discard it
57 /// and update the type index map to forward the source type index to the
58 /// existing destination type index.
59 ///
60 /// As an additional complication, type stream merging actually produces two
61 /// streams: an item (or IPI) stream and a type stream, as this is what is
62 /// actually stored in the final PDB. We choose which records go where by
63 /// looking at the record kind.
64 class TypeStreamMerger {
65 public:
66  explicit TypeStreamMerger(SmallVectorImpl<TypeIndex> &SourceToDest)
67  : IndexMap(SourceToDest) {
68  // When dealing with precompiled headers objects, all data in SourceToDest
69  // belongs to the precompiled headers object, and is assumed to be already
70  // remapped to the target PDB. Any forthcoming type that will be merged in
71  // might potentially back-reference this data. We also don't want to resolve
72  // twice the types in the precompiled object.
73  CurIndex += SourceToDest.size();
74  }
75 
76  static const TypeIndex Untranslated;
77 
78  // Local hashing entry points
79  Error mergeTypesAndIds(MergingTypeTableBuilder &DestIds,
80  MergingTypeTableBuilder &DestTypes,
81  const CVTypeArray &IdsAndTypes,
82  Optional<PCHMergerInfo> &PCHInfo);
84  ArrayRef<TypeIndex> TypeSourceToDest,
85  const CVTypeArray &Ids);
87  const CVTypeArray &Types);
88 
89  // Global hashing entry points
90  Error mergeTypesAndIds(GlobalTypeTableBuilder &DestIds,
91  GlobalTypeTableBuilder &DestTypes,
92  const CVTypeArray &IdsAndTypes,
94  Optional<PCHMergerInfo> &PCHInfo);
96  ArrayRef<TypeIndex> TypeSourceToDest,
97  const CVTypeArray &Ids,
101  Optional<PCHMergerInfo> &PCHInfo);
102 
103 private:
104  Error doit(const CVTypeArray &Types);
105 
106  Error remapAllTypes(const CVTypeArray &Types);
107 
108  Error remapType(const CVType &Type);
109 
110  void addMapping(TypeIndex Idx);
111 
112  inline bool remapTypeIndex(TypeIndex &Idx) {
113  // If we're mapping a pure index stream, then IndexMap only contains
114  // mappings from OldIdStream -> NewIdStream, in which case we will need to
115  // use the special mapping from OldTypeStream -> NewTypeStream which was
116  // computed externally. Regardless, we use this special map if and only if
117  // we are doing an id-only mapping.
118  if (!hasTypeStream())
119  return remapIndex(Idx, TypeLookup);
120 
121  assert(TypeLookup.empty());
122  return remapIndex(Idx, IndexMap);
123  }
124  inline bool remapItemIndex(TypeIndex &Idx) {
125  assert(hasIdStream());
126  return remapIndex(Idx, IndexMap);
127  }
128 
129  bool hasTypeStream() const {
130  return (UseGlobalHashes) ? (!!DestGlobalTypeStream) : (!!DestTypeStream);
131  }
132 
133  bool hasIdStream() const {
134  return (UseGlobalHashes) ? (!!DestGlobalIdStream) : (!!DestIdStream);
135  }
136 
137  ArrayRef<uint8_t> remapIndices(const CVType &OriginalType,
138  MutableArrayRef<uint8_t> Storage);
139 
140  inline bool remapIndex(TypeIndex &Idx, ArrayRef<TypeIndex> Map) {
141  if (LLVM_LIKELY(remapIndexSimple(Idx, Map)))
142  return true;
143 
144  return remapIndexFallback(Idx, Map);
145  }
146 
147  inline bool remapIndexSimple(TypeIndex &Idx, ArrayRef<TypeIndex> Map) const {
148  // Simple types are unchanged.
149  if (Idx.isSimple())
150  return true;
151 
152  // Check if this type index refers to a record we've already translated
153  // successfully. If it refers to a type later in the stream or a record we
154  // had to defer, defer it until later pass.
155  unsigned MapPos = slotForIndex(Idx);
156  if (LLVM_UNLIKELY(MapPos >= Map.size() || Map[MapPos] == Untranslated))
157  return false;
158 
159  Idx = Map[MapPos];
160  return true;
161  }
162 
163  bool remapIndexFallback(TypeIndex &Idx, ArrayRef<TypeIndex> Map);
164 
165  Error errorCorruptRecord() const {
166  return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record);
167  }
168 
169  Expected<bool> shouldRemapType(const CVType &Type);
170 
171  std::optional<Error> LastError;
172 
173  bool UseGlobalHashes = false;
174 
175  bool IsSecondPass = false;
176 
177  unsigned NumBadIndices = 0;
178 
180 
181  MergingTypeTableBuilder *DestIdStream = nullptr;
182  MergingTypeTableBuilder *DestTypeStream = nullptr;
183 
184  GlobalTypeTableBuilder *DestGlobalIdStream = nullptr;
185  GlobalTypeTableBuilder *DestGlobalTypeStream = nullptr;
186 
187  ArrayRef<GloballyHashedType> GlobalHashes;
188 
189  // If we're only mapping id records, this array contains the mapping for
190  // type records.
191  ArrayRef<TypeIndex> TypeLookup;
192 
193  /// Map from source type index to destination type index. Indexed by source
194  /// type index minus 0x1000.
195  SmallVectorImpl<TypeIndex> &IndexMap;
196 
197  /// Temporary storage that we use to copy a record's data while re-writing
198  /// its type indices.
199  SmallVector<uint8_t, 256> RemapStorage;
200 
201  Optional<PCHMergerInfo> PCHInfo;
202 };
203 
204 } // end anonymous namespace
205 
206 const TypeIndex TypeStreamMerger::Untranslated(SimpleTypeKind::NotTranslated);
207 
208 void TypeStreamMerger::addMapping(TypeIndex Idx) {
209  if (!IsSecondPass) {
210  assert(IndexMap.size() == slotForIndex(CurIndex) &&
211  "visitKnownRecord should add one index map entry");
212  IndexMap.push_back(Idx);
213  } else {
214  assert(slotForIndex(CurIndex) < IndexMap.size());
215  IndexMap[slotForIndex(CurIndex)] = Idx;
216  }
217 }
218 
219 bool TypeStreamMerger::remapIndexFallback(TypeIndex &Idx,
220  ArrayRef<TypeIndex> Map) {
221  size_t MapPos = slotForIndex(Idx);
222 
223  // If this is the second pass and this index isn't in the map, then it points
224  // outside the current type stream, and this is a corrupt record.
225  if (IsSecondPass && MapPos >= Map.size()) {
226  // FIXME: Print a more useful error. We can give the current record and the
227  // index that we think its pointing to.
228  if (LastError)
229  LastError = joinErrors(std::move(*LastError), errorCorruptRecord());
230  else
231  LastError = errorCorruptRecord();
232  }
233 
234  ++NumBadIndices;
235 
236  // This type index is invalid. Remap this to "not translated by cvpack",
237  // and return failure.
238  Idx = Untranslated;
239  return false;
240 }
241 
242 // Local hashing entry points
244  const CVTypeArray &Types) {
245  DestTypeStream = &Dest;
246  UseGlobalHashes = false;
247 
248  return doit(Types);
249 }
250 
252  ArrayRef<TypeIndex> TypeSourceToDest,
253  const CVTypeArray &Ids) {
254  DestIdStream = &Dest;
255  TypeLookup = TypeSourceToDest;
256  UseGlobalHashes = false;
257 
258  return doit(Ids);
259 }
260 
261 Error TypeStreamMerger::mergeTypesAndIds(MergingTypeTableBuilder &DestIds,
262  MergingTypeTableBuilder &DestTypes,
263  const CVTypeArray &IdsAndTypes,
264  Optional<PCHMergerInfo> &PCHInfo) {
265  DestIdStream = &DestIds;
266  DestTypeStream = &DestTypes;
267  UseGlobalHashes = false;
268  auto Err = doit(IdsAndTypes);
269  PCHInfo = this->PCHInfo;
270  return Err;
271 }
272 
273 // Global hashing entry points
275  const CVTypeArray &Types,
277  Optional<PCHMergerInfo> &PCHInfo) {
278  DestGlobalTypeStream = &Dest;
279  UseGlobalHashes = true;
280  GlobalHashes = Hashes;
281  auto Err = doit(Types);
282  PCHInfo = this->PCHInfo;
283  return Err;
284 }
285 
287  ArrayRef<TypeIndex> TypeSourceToDest,
288  const CVTypeArray &Ids,
290  DestGlobalIdStream = &Dest;
291  TypeLookup = TypeSourceToDest;
292  UseGlobalHashes = true;
293  GlobalHashes = Hashes;
294 
295  return doit(Ids);
296 }
297 
298 Error TypeStreamMerger::mergeTypesAndIds(GlobalTypeTableBuilder &DestIds,
299  GlobalTypeTableBuilder &DestTypes,
300  const CVTypeArray &IdsAndTypes,
302  Optional<PCHMergerInfo> &PCHInfo) {
303  DestGlobalIdStream = &DestIds;
304  DestGlobalTypeStream = &DestTypes;
305  UseGlobalHashes = true;
306  GlobalHashes = Hashes;
307  auto Err = doit(IdsAndTypes);
308  PCHInfo = this->PCHInfo;
309  return Err;
310 }
311 
312 Error TypeStreamMerger::doit(const CVTypeArray &Types) {
313  if (auto EC = remapAllTypes(Types))
314  return EC;
315 
316  // If we found bad indices but no other errors, try doing another pass and see
317  // if we can resolve the indices that weren't in the map on the first pass.
318  // This may require multiple passes, but we should always make progress. MASM
319  // is the only known CodeView producer that makes type streams that aren't
320  // topologically sorted. The standard library contains MASM-produced objects,
321  // so this is important to handle correctly, but we don't have to be too
322  // efficient. MASM type streams are usually very small.
323  while (!LastError && NumBadIndices > 0) {
324  unsigned BadIndicesRemaining = NumBadIndices;
325  IsSecondPass = true;
326  NumBadIndices = 0;
328 
329  if (auto EC = remapAllTypes(Types))
330  return EC;
331 
332  assert(NumBadIndices <= BadIndicesRemaining &&
333  "second pass found more bad indices");
334  if (!LastError && NumBadIndices == BadIndicesRemaining) {
335  return llvm::make_error<CodeViewError>(
336  cv_error_code::corrupt_record, "Input type graph contains cycles");
337  }
338  }
339 
340  if (LastError)
341  return std::move(*LastError);
342  return Error::success();
343 }
344 
345 Error TypeStreamMerger::remapAllTypes(const CVTypeArray &Types) {
346  BinaryStreamRef Stream = Types.getUnderlyingStream();
347  ArrayRef<uint8_t> Buffer;
348  cantFail(Stream.readBytes(0, Stream.getLength(), Buffer));
349 
350  return forEachCodeViewRecord<CVType>(
351  Buffer, [this](const CVType &T) { return remapType(T); });
352 }
353 
354 Error TypeStreamMerger::remapType(const CVType &Type) {
355  auto R = shouldRemapType(Type);
356  if (!R)
357  return R.takeError();
358 
359  TypeIndex DestIdx = Untranslated;
360  if (*R) {
361  auto DoSerialize =
362  [this, Type](MutableArrayRef<uint8_t> Storage) -> ArrayRef<uint8_t> {
363  return remapIndices(Type, Storage);
364  };
365  unsigned AlignedSize = alignTo(Type.RecordData.size(), 4);
366 
367  if (LLVM_LIKELY(UseGlobalHashes)) {
368  GlobalTypeTableBuilder &Dest =
369  isIdRecord(Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream;
370  GloballyHashedType H = GlobalHashes[CurIndex.toArrayIndex()];
371  DestIdx = Dest.insertRecordAs(H, AlignedSize, DoSerialize);
372  } else {
374  isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream;
375 
376  RemapStorage.resize(AlignedSize);
377  ArrayRef<uint8_t> Result = DoSerialize(RemapStorage);
378  if (!Result.empty())
379  DestIdx = Dest.insertRecordBytes(Result);
380  }
381  }
382  addMapping(DestIdx);
383 
384  ++CurIndex;
385  assert((IsSecondPass || IndexMap.size() == slotForIndex(CurIndex)) &&
386  "visitKnownRecord should add one index map entry");
387  return Error::success();
388 }
389 
391 TypeStreamMerger::remapIndices(const CVType &OriginalType,
392  MutableArrayRef<uint8_t> Storage) {
393  unsigned Align = OriginalType.RecordData.size() & 3;
394  assert(Storage.size() == alignTo(OriginalType.RecordData.size(), 4) &&
395  "The storage buffer size is not a multiple of 4 bytes which will "
396  "cause misalignment in the output TPI stream!");
397 
399  discoverTypeIndices(OriginalType.RecordData, Refs);
400  if (Refs.empty() && Align == 0)
401  return OriginalType.RecordData;
402 
403  ::memcpy(Storage.data(), OriginalType.RecordData.data(),
404  OriginalType.RecordData.size());
405 
406  uint8_t *DestContent = Storage.data() + sizeof(RecordPrefix);
407 
408  for (auto &Ref : Refs) {
409  TypeIndex *DestTIs =
410  reinterpret_cast<TypeIndex *>(DestContent + Ref.Offset);
411 
412  for (size_t I = 0; I < Ref.Count; ++I) {
413  TypeIndex &TI = DestTIs[I];
414  bool Success = (Ref.Kind == TiRefKind::IndexRef) ? remapItemIndex(TI)
415  : remapTypeIndex(TI);
416  if (LLVM_UNLIKELY(!Success))
417  return {};
418  }
419  }
420 
421  if (Align > 0) {
422  RecordPrefix *StorageHeader =
423  reinterpret_cast<RecordPrefix *>(Storage.data());
424  StorageHeader->RecordLen += 4 - Align;
425 
426  DestContent = Storage.data() + OriginalType.RecordData.size();
427  for (; Align < 4; ++Align)
428  *DestContent++ = LF_PAD4 - Align;
429  }
430  return Storage;
431 }
432 
434  SmallVectorImpl<TypeIndex> &SourceToDest,
435  const CVTypeArray &Types) {
436  TypeStreamMerger M(SourceToDest);
437  return M.mergeTypeRecords(Dest, Types);
438 }
439 
441  ArrayRef<TypeIndex> TypeSourceToDest,
442  SmallVectorImpl<TypeIndex> &SourceToDest,
443  const CVTypeArray &Ids) {
444  TypeStreamMerger M(SourceToDest);
445  return M.mergeIdRecords(Dest, TypeSourceToDest, Ids);
446 }
447 
450  SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes,
451  Optional<PCHMergerInfo> &PCHInfo) {
452  TypeStreamMerger M(SourceToDest);
453  return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, PCHInfo);
454 }
455 
457  GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes,
458  SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes,
460  TypeStreamMerger M(SourceToDest);
461  return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes, PCHInfo);
462 }
463 
465  SmallVectorImpl<TypeIndex> &SourceToDest,
466  const CVTypeArray &Types,
468  Optional<PCHMergerInfo> &PCHInfo) {
469  TypeStreamMerger M(SourceToDest);
470  return M.mergeTypeRecords(Dest, Types, Hashes, PCHInfo);
471 }
472 
474  ArrayRef<TypeIndex> Types,
475  SmallVectorImpl<TypeIndex> &SourceToDest,
476  const CVTypeArray &Ids,
478  TypeStreamMerger M(SourceToDest);
479  return M.mergeIdRecords(Dest, Types, Ids, Hashes);
480 }
481 
482 Expected<bool> TypeStreamMerger::shouldRemapType(const CVType &Type) {
483  // For object files containing precompiled types, we need to extract the
484  // signature, through EndPrecompRecord. This is done here for performance
485  // reasons, to avoid re-parsing the Types stream.
486  if (Type.kind() == LF_ENDPRECOMP) {
487  EndPrecompRecord EP;
488  if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type),
489  EP))
490  return joinErrors(std::move(EC), errorCorruptRecord());
491  // Only one record of this kind can appear in a OBJ.
492  if (PCHInfo)
493  return errorCorruptRecord();
494  PCHInfo.emplace(PCHMergerInfo{EP.getSignature(), CurIndex.toArrayIndex()});
495  return false;
496  }
497  return true;
498 }
GlobalTypeTableBuilder.h
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
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
TypeStreamMerger.h
Optional.h
llvm::codeview::TypeIndex::FirstNonSimpleIndex
static const uint32_t FirstNonSimpleIndex
Definition: TypeIndex.h:98
llvm::codeview::MergingTypeTableBuilder
Definition: MergingTypeTableBuilder.h:28
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
Error.h
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::Optional
Definition: APInt.h:33
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::codeview::RecordPrefix
Definition: RecordSerialization.h:32
llvm::codeview::CVRecord::RecordData
ArrayRef< uint8_t > RecordData
Definition: CVRecord.h:60
llvm::ArrayRef::data
const T * data() const
Definition: ArrayRef.h:161
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:265
llvm::codeview::mergeTypeRecords
Error mergeTypeRecords(MergingTypeTableBuilder &Dest, SmallVectorImpl< TypeIndex > &SourceToDest, const CVTypeArray &Types)
Merge one set of type records into another.
Definition: TypeStreamMerger.cpp:433
slotForIndex
static size_t slotForIndex(TypeIndex Idx)
Definition: TypeStreamMerger.cpp:25
llvm::MutableArrayRef< uint8_t >
llvm::ModRefInfo::Ref
@ Ref
The access may reference the value stored in memory.
llvm::msgpack::Type::Map
@ Map
llvm::VarStreamArray< CVType >
llvm::BinaryStreamRefBase::getLength
uint64_t getLength() const
Definition: BinaryStreamRef.h:50
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
MergingTypeTableBuilder.h
Align
uint64_t Align
Definition: ELFObjHandler.cpp:82
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
llvm::codeview::MergingTypeTableBuilder::insertRecordBytes
TypeIndex insertRecordBytes(ArrayRef< uint8_t > &Record)
Definition: MergingTypeTableBuilder.cpp:108
llvm::codeview::GloballyHashedType
A globally hashed type represents a hash value that is sufficient to uniquely identify a record acros...
Definition: TypeHashing.h:80
llvm::codeview::GlobalTypeTableBuilder
Definition: GlobalTypeTableBuilder.h:29
TypeRecord.h
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
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::codeview::GlobalTypeTableBuilder::insertRecordAs
TypeIndex insertRecordAs(GloballyHashedType Hash, size_t RecordSize, CreateFunc Create)
Definition: GlobalTypeTableBuilder.h:71
llvm::joinErrors
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:426
llvm::codeview::mergeIdRecords
Error mergeIdRecords(MergingTypeTableBuilder &Dest, ArrayRef< TypeIndex > Types, SmallVectorImpl< TypeIndex > &SourceToDest, const CVTypeArray &Ids)
Merge one set of id records into another.
Definition: TypeStreamMerger.cpp:440
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(<
TypeRecordHelpers.h
llvm::codeview::CompileSym2Flags::EC
@ EC
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::logicalview::LVCompareKind::Types
@ Types
llvm::codeview::CVRecord< TypeLeafKind >
llvm::cantFail
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:744
llvm::codeview::TiRefKind::IndexRef
@ IndexRef
llvm::MutableArrayRef::data
T * data() const
Definition: ArrayRef.h:353
llvm::codeview::EndPrecompRecord::getSignature
uint32_t getSignature() const
Definition: TypeRecord.h:951
H
#define H(x, y, z)
Definition: MD5.cpp:57
TypeDeserializer.h
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
Success
#define Success
Definition: AArch64Disassembler.cpp:295
llvm::codeview::discoverTypeIndices
void discoverTypeIndices(ArrayRef< uint8_t > RecordData, SmallVectorImpl< TiReference > &Refs)
Definition: TypeIndexDiscovery.cpp:493
llvm::codeview::cv_error_code::corrupt_record
@ corrupt_record
llvm::codeview::PCHMergerInfo
Used to forward information about PCH.OBJ (precompiled) files, when applicable.
Definition: TypeStreamMerger.h:28
llvm::codeview::TypeIndex::getIndex
uint32_t getIndex() const
Definition: TypeIndex.h:111
TypeIndex.h
llvm::BinaryStreamRef::readBytes
Error readBytes(uint64_t Offset, uint64_t Size, ArrayRef< uint8_t > &Buffer) const
Given an Offset into this StreamRef and a Size, return a reference to a buffer owned by the stream.
Definition: BinaryStreamRef.cpp:79
llvm::codeview
Definition: AppendingTypeTableBuilder.h:22
llvm::codeview::TypeIndex::isSimple
bool isSimple() const
Definition: TypeIndex.h:113
llvm::codeview::TypeDeserializer::deserializeAs
static Error deserializeAs(CVType &CVT, T &Record)
Definition: TypeDeserializer.h:42
SmallVector.h
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:164
LLVM_LIKELY
#define LLVM_LIKELY(EXPR)
Definition: Compiler.h:209
llvm::codeview::RecordPrefix::RecordLen
ulittle16_t RecordLen
Definition: RecordSerialization.h:36
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
llvm::codeview::TypeIndex
A 32-bit type reference.
Definition: TypeIndex.h:96
TypeIndexDiscovery.h
llvm::codeview::SimpleTypeKind::NotTranslated
@ NotTranslated
llvm::codeview::isIdRecord
bool isIdRecord(TypeLeafKind K)
Return true if this record should be in the IPI stream of a PDB.
Definition: TypeRecordHelpers.h:29
LLVM_UNLIKELY
#define LLVM_UNLIKELY(EXPR)
Definition: Compiler.h:210
llvm::codeview::EndPrecompRecord
Definition: TypeRecord.h:946
llvm::codeview::mergeTypeAndIdRecords
Error mergeTypeAndIdRecords(MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes, SmallVectorImpl< TypeIndex > &SourceToDest, const CVTypeArray &IdsAndTypes, Optional< PCHMergerInfo > &PCHInfo)
Merge a unified set of type and id records, splitting them into separate output streams.
Definition: TypeStreamMerger.cpp:448
llvm::BinaryStreamRef
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
Definition: BinaryStreamRef.h:155