63 class TypeStreamMerger {
66 : IndexMap(SourceToDest) {
72 CurIndex += SourceToDest.
size();
110 inline bool remapTypeIndex(
TypeIndex &Idx) {
116 if (!hasTypeStream())
117 return remapIndex(Idx, TypeLookup);
119 assert(TypeLookup.empty());
120 return remapIndex(Idx, IndexMap);
122 inline bool remapItemIndex(
TypeIndex &Idx) {
124 return remapIndex(Idx, IndexMap);
127 bool hasTypeStream()
const {
128 return (UseGlobalHashes) ? (!!DestGlobalTypeStream) : (!!DestTypeStream);
131 bool hasIdStream()
const {
132 return (UseGlobalHashes) ? (!!DestGlobalIdStream) : (!!DestIdStream);
142 return remapIndexFallback(Idx, Map);
163 Error errorCorruptRecord()
const {
171 bool UseGlobalHashes =
false;
173 bool IsSecondPass =
false;
175 unsigned NumBadIndices = 0;
208 case TypeLeafKind::LF_FUNC_ID:
209 case TypeLeafKind::LF_MFUNC_ID:
210 case TypeLeafKind::LF_STRING_ID:
211 case TypeLeafKind::LF_SUBSTR_LIST:
212 case TypeLeafKind::LF_BUILDINFO:
213 case TypeLeafKind::LF_UDT_SRC_LINE:
214 case TypeLeafKind::LF_UDT_MOD_SRC_LINE:
221 void TypeStreamMerger::addMapping(
TypeIndex Idx) {
224 "visitKnownRecord should add one index map entry");
225 IndexMap.push_back(Idx);
232 bool TypeStreamMerger::remapIndexFallback(
TypeIndex &Idx,
238 if (IsSecondPass && MapPos >= Map.
size()) {
242 LastError =
joinErrors(std::move(*LastError), errorCorruptRecord());
244 LastError = errorCorruptRecord();
258 DestTypeStream = &Dest;
259 UseGlobalHashes =
false;
267 DestIdStream = &Dest;
268 TypeLookup = TypeSourceToDest;
269 UseGlobalHashes =
false;
278 DestIdStream = &DestIds;
279 DestTypeStream = &DestTypes;
280 UseGlobalHashes =
false;
281 auto Err = doit(IdsAndTypes);
291 DestGlobalTypeStream = &Dest;
292 UseGlobalHashes =
true;
293 GlobalHashes = Hashes;
294 auto Err = doit(Types);
303 DestGlobalIdStream = &Dest;
304 TypeLookup = TypeSourceToDest;
305 UseGlobalHashes =
true;
306 GlobalHashes = Hashes;
316 DestGlobalIdStream = &DestIds;
317 DestGlobalTypeStream = &DestTypes;
318 UseGlobalHashes =
true;
319 GlobalHashes = Hashes;
320 auto Err = doit(IdsAndTypes);
326 if (
auto EC = remapAllTypes(Types))
336 while (!LastError && NumBadIndices > 0) {
337 unsigned BadIndicesRemaining = NumBadIndices;
342 if (
auto EC = remapAllTypes(Types))
345 assert(NumBadIndices <= BadIndicesRemaining &&
346 "second pass found more bad indices");
347 if (!LastError && NumBadIndices == BadIndicesRemaining) {
348 return llvm::make_error<CodeViewError>(
354 return std::move(*LastError);
363 return forEachCodeViewRecord<CVType>(
364 Buffer, [
this](
const CVType &
T) {
return remapType(
T); });
368 auto R = shouldRemapType(Type);
370 return R.takeError();
376 return remapIndices(Type, Storage);
380 isIdRecord(Type.
kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream;
397 "visitKnownRecord should add one index map entry");
402 TypeStreamMerger::remapIndices(
const CVType &OriginalType,
414 for (
auto &
Ref : Refs) {
416 reinterpret_cast<TypeIndex *
>(DestContent +
Ref.Offset);
418 for (
size_t I = 0;
I <
Ref.Count; ++
I) {
421 : remapTypeIndex(TI);
432 TypeStreamMerger M(SourceToDest);
433 return M.mergeTypeRecords(Dest, Types);
440 TypeStreamMerger M(SourceToDest);
441 return M.mergeIdRecords(Dest, TypeSourceToDest, Ids);
448 TypeStreamMerger M(SourceToDest);
449 return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, PCHSignature);
456 TypeStreamMerger M(SourceToDest);
457 return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes,
466 TypeStreamMerger M(SourceToDest);
467 return M.mergeTypeRecords(Dest, Types, Hashes, PCHSignature);
475 TypeStreamMerger M(SourceToDest);
476 return M.mergeIdRecords(Dest, Types, Ids, Hashes);
483 if (Type.
kind() == LF_ENDPRECOMP) {
488 if (PCHSignature.hasValue())
489 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.
BinaryStreamRef getUnderlyingStream() const
Error mergeTypeRecords(MergingTypeTableBuilder &Dest, SmallVectorImpl< TypeIndex > &SourceToDest, const CVTypeArray &Types)
Merge one set of type records into another.
#define LLVM_UNLIKELY(EXPR)
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.
#define LLVM_LIKELY(EXPR)
uint32_t getSignature() const
bool empty() const
empty - Check if the array is empty.