62 class TypeStreamMerger {
65 : IndexMap(SourceToDest) {
71 CurIndex += SourceToDest.
size();
109 inline bool remapTypeIndex(
TypeIndex &Idx) {
115 if (!hasTypeStream())
116 return remapIndex(Idx, TypeLookup);
118 assert(TypeLookup.empty());
119 return remapIndex(Idx, IndexMap);
121 inline bool remapItemIndex(
TypeIndex &Idx) {
123 return remapIndex(Idx, IndexMap);
126 bool hasTypeStream()
const {
127 return (UseGlobalHashes) ? (!!DestGlobalTypeStream) : (!!DestTypeStream);
130 bool hasIdStream()
const {
131 return (UseGlobalHashes) ? (!!DestGlobalIdStream) : (!!DestIdStream);
141 return remapIndexFallback(Idx, Map);
162 Error errorCorruptRecord()
const {
170 bool UseGlobalHashes =
false;
172 bool IsSecondPass =
false;
174 unsigned NumBadIndices = 0;
207 case TypeLeafKind::LF_FUNC_ID:
208 case TypeLeafKind::LF_MFUNC_ID:
209 case TypeLeafKind::LF_STRING_ID:
210 case TypeLeafKind::LF_SUBSTR_LIST:
211 case TypeLeafKind::LF_BUILDINFO:
212 case TypeLeafKind::LF_UDT_SRC_LINE:
213 case TypeLeafKind::LF_UDT_MOD_SRC_LINE:
220 void TypeStreamMerger::addMapping(
TypeIndex Idx) {
223 "visitKnownRecord should add one index map entry");
224 IndexMap.push_back(Idx);
231 bool TypeStreamMerger::remapIndexFallback(
TypeIndex &Idx,
237 if (IsSecondPass && MapPos >= Map.
size()) {
241 LastError =
joinErrors(std::move(*LastError), errorCorruptRecord());
243 LastError = errorCorruptRecord();
257 DestTypeStream = &Dest;
258 UseGlobalHashes =
false;
266 DestIdStream = &Dest;
267 TypeLookup = TypeSourceToDest;
268 UseGlobalHashes =
false;
277 DestIdStream = &DestIds;
278 DestTypeStream = &DestTypes;
279 UseGlobalHashes =
false;
280 auto Err = doit(IdsAndTypes);
290 DestGlobalTypeStream = &Dest;
291 UseGlobalHashes =
true;
292 GlobalHashes = Hashes;
293 auto Err = doit(Types);
302 DestGlobalIdStream = &Dest;
303 TypeLookup = TypeSourceToDest;
304 UseGlobalHashes =
true;
305 GlobalHashes = Hashes;
315 DestGlobalIdStream = &DestIds;
316 DestGlobalTypeStream = &DestTypes;
317 UseGlobalHashes =
true;
318 GlobalHashes = Hashes;
319 auto Err = doit(IdsAndTypes);
325 if (
auto EC = remapAllTypes(Types))
335 while (!LastError && NumBadIndices > 0) {
336 unsigned BadIndicesRemaining = NumBadIndices;
341 if (
auto EC = remapAllTypes(Types))
344 assert(NumBadIndices <= BadIndicesRemaining &&
345 "second pass found more bad indices");
346 if (!LastError && NumBadIndices == BadIndicesRemaining) {
347 return llvm::make_error<CodeViewError>(
353 return std::move(*LastError);
362 return forEachCodeViewRecord<CVType>(
363 Buffer, [
this](
const CVType &
T) {
return remapType(
T); });
367 auto R = shouldRemapType(Type);
369 return R.takeError();
375 return remapIndices(Type, Storage);
379 isIdRecord(Type.
kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream;
396 "visitKnownRecord should add one index map entry");
401 TypeStreamMerger::remapIndices(
const CVType &OriginalType,
413 for (
auto &
Ref : Refs) {
415 reinterpret_cast<TypeIndex *
>(DestContent +
Ref.Offset);
417 for (
size_t I = 0;
I <
Ref.Count; ++
I) {
420 : remapTypeIndex(TI);
431 TypeStreamMerger M(SourceToDest);
432 return M.mergeTypeRecords(Dest, Types);
439 TypeStreamMerger M(SourceToDest);
440 return M.mergeIdRecords(Dest, TypeSourceToDest, Ids);
447 TypeStreamMerger M(SourceToDest);
448 return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, PCHSignature);
455 TypeStreamMerger M(SourceToDest);
456 return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes,
465 TypeStreamMerger M(SourceToDest);
466 return M.mergeTypeRecords(Dest, Types, Hashes, PCHSignature);
474 TypeStreamMerger M(SourceToDest);
475 return M.mergeIdRecords(Dest, Types, Ids, Hashes);
482 if (Type.
kind() == LF_ENDPRECOMP) {
487 if (PCHSignature.hasValue())
488 return errorCorruptRecord();
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
void discoverTypeIndices(ArrayRef< uint8_t > RecordData, SmallVectorImpl< TiReference > &Refs)
This class represents lattice values for constants.
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
#define LLVM_UNLIKELY(EXPR)
#define LLVM_LIKELY(EXPR)
BinaryStreamRef getUnderlyingStream() const
Error mergeTypeRecords(MergingTypeTableBuilder &Dest, SmallVectorImpl< TypeIndex > &SourceToDest, const CVTypeArray &Types)
Merge one set of type records into another.
Error mergeTypeAndIdRecords(MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes, SmallVectorImpl< TypeIndex > &SourceToDest, const CVTypeArray &IdsAndTypes, Optional< uint32_t > &PCHSignature)
Merge a unified set of type and id records, splitting them into separate output streams.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
The access may reference the value stored in memory.
Tagged union holding either a T or a Error.
static const uint32_t FirstNonSimpleIndex
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
A globally hashed type represents a hash value that is sufficient to uniquely identify a record acros...
Error readBytes(uint32_t Offset, uint32_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...
The instances of the Type class are immutable: once they are created, they are never changed...
size_t size() const
size - Get the array size.
static Error deserializeAs(CVType &CVT, T &Record)
uint32_t getIndex() const
uint32_t getLength() const
static ErrorSuccess success()
Create a success value.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
static bool isIdRecord(TypeLeafKind K)
static size_t slotForIndex(TypeIndex Idx)
ArrayRef< uint8_t > RecordData
LLVM_NODISCARD bool empty() const
Error joinErrors(Error E1, Error E2)
Concatenate errors.
TypeIndex insertRecordBytes(ArrayRef< uint8_t > &Record)
Error mergeIdRecords(MergingTypeTableBuilder &Dest, ArrayRef< TypeIndex > Types, SmallVectorImpl< TypeIndex > &SourceToDest, const CVTypeArray &Ids)
Merge one set of id records into another.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
TypeIndex insertRecordAs(GloballyHashedType Hash, size_t RecordSize, CreateFunc Create)
Lightweight error class with error context and mandatory checking.
uint32_t getSignature() const
bool empty() const
empty - Check if the array is empty.