25 assert(!
Idx.isSimple() &&
"simple type indices have no slots");
63class TypeStreamMerger {
66 : IndexMap(SourceToDest) {
72 CurIndex += SourceToDest.
size();
81 std::optional<PCHMergerInfo> &PCHInfo);
93 std::optional<PCHMergerInfo> &PCHInfo);
100 std::optional<PCHMergerInfo> &PCHInfo);
117 if (!hasTypeStream())
118 return remapIndex(
Idx, TypeLookup);
120 assert(TypeLookup.empty());
121 return remapIndex(
Idx, IndexMap);
125 return remapIndex(
Idx, IndexMap);
128 bool hasTypeStream()
const {
129 return (UseGlobalHashes) ? (!!DestGlobalTypeStream) : (!!DestTypeStream);
132 bool hasIdStream()
const {
133 return (UseGlobalHashes) ? (!!DestGlobalIdStream) : (!!DestIdStream);
143 return remapIndexFallback(
Idx, Map);
164 Error errorCorruptRecord()
const {
165 return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record);
170 std::optional<Error> LastError;
172 bool UseGlobalHashes =
false;
174 bool IsSecondPass =
false;
176 unsigned NumBadIndices = 0;
200 std::optional<PCHMergerInfo> PCHInfo;
205const TypeIndex TypeStreamMerger::Untranslated(SimpleTypeKind::NotTranslated);
210 "visitKnownRecord should add one index map entry");
211 IndexMap.push_back(
Idx);
218bool TypeStreamMerger::remapIndexFallback(
TypeIndex &
Idx,
224 if (IsSecondPass && MapPos >=
Map.size()) {
228 LastError =
joinErrors(std::move(*LastError), errorCorruptRecord());
230 LastError = errorCorruptRecord();
244 DestTypeStream = &Dest;
245 UseGlobalHashes =
false;
253 DestIdStream = &Dest;
254 TypeLookup = TypeSourceToDest;
255 UseGlobalHashes =
false;
260Error TypeStreamMerger::mergeTypesAndIds(
262 const CVTypeArray &IdsAndTypes, std::optional<PCHMergerInfo> &PCHInfo) {
263 DestIdStream = &DestIds;
264 DestTypeStream = &DestTypes;
265 UseGlobalHashes =
false;
266 auto Err = doit(IdsAndTypes);
267 PCHInfo = this->PCHInfo;
272Error TypeStreamMerger::mergeTypeRecords(
275 std::optional<PCHMergerInfo> &PCHInfo) {
276 DestGlobalTypeStream = &Dest;
277 UseGlobalHashes =
true;
278 GlobalHashes = Hashes;
279 auto Err = doit(Types);
280 PCHInfo = this->PCHInfo;
288 DestGlobalIdStream = &Dest;
289 TypeLookup = TypeSourceToDest;
290 UseGlobalHashes =
true;
291 GlobalHashes = Hashes;
296Error TypeStreamMerger::mergeTypesAndIds(
299 std::optional<PCHMergerInfo> &PCHInfo) {
300 DestGlobalIdStream = &DestIds;
301 DestGlobalTypeStream = &DestTypes;
302 UseGlobalHashes =
true;
303 GlobalHashes = Hashes;
304 auto Err = doit(IdsAndTypes);
305 PCHInfo = this->PCHInfo;
310 if (
auto EC = remapAllTypes(Types))
320 while (!LastError && NumBadIndices > 0) {
321 unsigned BadIndicesRemaining = NumBadIndices;
326 if (
auto EC = remapAllTypes(Types))
329 assert(NumBadIndices <= BadIndicesRemaining &&
330 "second pass found more bad indices");
331 if (!LastError && NumBadIndices == BadIndicesRemaining) {
332 return llvm::make_error<CodeViewError>(
333 cv_error_code::corrupt_record,
"Input type graph contains cycles");
338 return std::move(*LastError);
347 return forEachCodeViewRecord<CVType>(
348 Buffer, [
this](
const CVType &
T) {
return remapType(
T); });
352 auto R = shouldRemapType(
Type);
354 return R.takeError();
360 return remapIndices(
Type, Storage);
362 unsigned AlignedSize =
alignTo(
Type.RecordData.size(), 4);
366 isIdRecord(
Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream;
373 RemapStorage.resize(AlignedSize);
383 "visitKnownRecord should add one index map entry");
388TypeStreamMerger::remapIndices(
const CVType &OriginalType,
392 "The storage buffer size is not a multiple of 4 bytes which will "
393 "cause misalignment in the output TPI stream!");
405 for (
auto &
Ref : Refs) {
407 reinterpret_cast<TypeIndex *
>(DestContent +
Ref.Offset);
409 for (
size_t I = 0;
I <
Ref.Count; ++
I) {
411 bool Success = (
Ref.Kind == TiRefKind::IndexRef) ? remapItemIndex(TI)
412 : remapTypeIndex(TI);
425 *DestContent++ = LF_PAD4 -
Align;
433 TypeStreamMerger M(SourceToDest);
434 return M.mergeTypeRecords(Dest, Types);
441 TypeStreamMerger M(SourceToDest);
442 return M.mergeIdRecords(Dest, TypeSourceToDest, Ids);
448 std::optional<PCHMergerInfo> &PCHInfo) {
449 TypeStreamMerger M(SourceToDest);
450 return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, PCHInfo);
457 std::optional<PCHMergerInfo> &PCHInfo) {
458 TypeStreamMerger M(SourceToDest);
459 return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes, PCHInfo);
466 std::optional<PCHMergerInfo> &PCHInfo) {
467 TypeStreamMerger M(SourceToDest);
468 return M.mergeTypeRecords(Dest, Types, Hashes, PCHInfo);
476 TypeStreamMerger M(SourceToDest);
477 return M.mergeIdRecords(Dest, Types, Ids, Hashes);
484 if (
Type.kind() == LF_ENDPRECOMP) {
491 return errorCorruptRecord();
#define LLVM_UNLIKELY(EXPR)
#define LLVM_LIKELY(EXPR)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
static size_t slotForIndex(TypeIndex Idx)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
uint64_t getLength() const
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
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.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
ArrayRef< uint8_t > RecordData
uint32_t getSignature() const
TypeIndex insertRecordAs(GloballyHashedType Hash, size_t RecordSize, CreateFunc Create)
TypeIndex insertRecordBytes(ArrayRef< uint8_t > &Record)
static Error deserializeAs(CVType &CVT, T &Record)
static const uint32_t FirstNonSimpleIndex
void discoverTypeIndices(ArrayRef< uint8_t > RecordData, SmallVectorImpl< TiReference > &Refs)
Error mergeIdRecords(MergingTypeTableBuilder &Dest, ArrayRef< TypeIndex > Types, SmallVectorImpl< TypeIndex > &SourceToDest, const CVTypeArray &Ids)
Merge one set of id records into another.
Error mergeTypeAndIdRecords(MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes, SmallVectorImpl< TypeIndex > &SourceToDest, const CVTypeArray &IdsAndTypes, std::optional< PCHMergerInfo > &PCHInfo)
Merge a unified set of type and id records, splitting them into separate output streams.
bool isIdRecord(TypeLeafKind K)
Return true if this record should be in the IPI stream of a PDB.
Error mergeTypeRecords(MergingTypeTableBuilder &Dest, SmallVectorImpl< TypeIndex > &SourceToDest, const CVTypeArray &Types)
Merge one set of type records into another.
This is an optimization pass for GlobalISel generic memory operations.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
@ Ref
The access may reference the value stored in memory.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
This struct is a compact representation of a valid (non-zero power of two) alignment.
A globally hashed type represents a hash value that is sufficient to uniquely identify a record acros...
Used to forward information about PCH.OBJ (precompiled) files, when applicable.