63class TypeStreamMerger {
65 explicit TypeStreamMerger(SmallVectorImpl<TypeIndex> &SourceToDest)
66 : IndexMap(SourceToDest) {
72 CurIndex += SourceToDest.
size();
75 static const TypeIndex Untranslated;
78 Error mergeTypesAndIds(MergingTypeTableBuilder &DestIds,
79 MergingTypeTableBuilder &DestTypes,
81 std::optional<PCHMergerInfo> &PCHInfo);
89 Error mergeTypesAndIds(GlobalTypeTableBuilder &DestIds,
90 GlobalTypeTableBuilder &DestTypes,
93 std::optional<PCHMergerInfo> &PCHInfo);
100 std::optional<PCHMergerInfo> &PCHInfo);
109 void addMapping(TypeIndex Idx);
111 inline bool remapTypeIndex(TypeIndex &Idx) {
117 if (!hasTypeStream())
118 return remapIndex(Idx, TypeLookup);
120 assert(TypeLookup.empty());
121 return remapIndex(Idx, IndexMap);
123 inline bool remapItemIndex(TypeIndex &Idx) {
125 return remapIndex(Idx, IndexMap);
128 bool hasTypeStream()
const {
129 return (UseGlobalHashes) ? (!!DestGlobalTypeStream) : (!!DestTypeStream);
132 bool hasIdStream()
const {
133 return (UseGlobalHashes) ? (!!DestGlobalIdStream) : (!!DestIdStream);
137 MutableArrayRef<uint8_t> Storage);
143 return remapIndexFallback(Idx, Map);
164 Error errorCorruptRecord()
const {
168 Expected<bool> shouldRemapType(
const CVType &
Type);
170 std::optional<Error> LastError;
172 bool UseGlobalHashes =
false;
174 bool IsSecondPass =
false;
176 unsigned NumBadIndices = 0;
180 MergingTypeTableBuilder *DestIdStream =
nullptr;
181 MergingTypeTableBuilder *DestTypeStream =
nullptr;
183 GlobalTypeTableBuilder *DestGlobalIdStream =
nullptr;
184 GlobalTypeTableBuilder *DestGlobalTypeStream =
nullptr;
194 SmallVectorImpl<TypeIndex> &IndexMap;
200 std::optional<PCHMergerInfo> PCHInfo;
207void TypeStreamMerger::addMapping(
TypeIndex Idx) {
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();
242Error TypeStreamMerger::mergeTypeRecords(MergingTypeTableBuilder &Dest,
244 DestTypeStream = &Dest;
245 UseGlobalHashes =
false;
250Error TypeStreamMerger::mergeIdRecords(MergingTypeTableBuilder &Dest,
253 DestIdStream = &Dest;
254 TypeLookup = TypeSourceToDest;
255 UseGlobalHashes =
false;
260Error TypeStreamMerger::mergeTypesAndIds(
261 MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes,
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(
273 GlobalTypeTableBuilder &Dest,
const CVTypeArray &Types,
275 std::optional<PCHMergerInfo> &PCHInfo) {
276 DestGlobalTypeStream = &Dest;
277 UseGlobalHashes =
true;
278 GlobalHashes = Hashes;
279 auto Err = doit(Types);
280 PCHInfo = this->PCHInfo;
284Error TypeStreamMerger::mergeIdRecords(GlobalTypeTableBuilder &Dest,
288 DestGlobalIdStream = &Dest;
289 TypeLookup = TypeSourceToDest;
290 UseGlobalHashes =
true;
291 GlobalHashes = Hashes;
296Error TypeStreamMerger::mergeTypesAndIds(
297 GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes,
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) {
333 cv_error_code::corrupt_record,
"Input type graph contains cycles");
338 return std::move(*LastError);
343 BinaryStreamRef Stream =
Types.getUnderlyingStream();
344 ArrayRef<uint8_t> Buffer;
348 Buffer, [
this](
const CVType &
T) {
return remapType(
T); });
352 auto R = shouldRemapType(
Type);
354 return R.takeError();
356 TypeIndex DestIdx = Untranslated;
359 [
this,
Type](MutableArrayRef<uint8_t> Storage) -> ArrayRef<uint8_t> {
362 unsigned AlignedSize =
alignTo(
Type.RecordData.size(), 4);
365 GlobalTypeTableBuilder &Dest =
366 isIdRecord(
Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream;
367 GloballyHashedType
H = GlobalHashes[CurIndex.
toArrayIndex()];
370 MergingTypeTableBuilder &Dest =
373 RemapStorage.resize(AlignedSize);
374 ArrayRef<uint8_t>
Result = DoSerialize(RemapStorage);
383 "visitKnownRecord should add one index map entry");
388TypeStreamMerger::remapIndices(
const CVType &OriginalType,
389 MutableArrayRef<uint8_t> Storage) {
392 "The storage buffer size is not a multiple of 4 bytes which will "
393 "cause misalignment in the output TPI stream!");
397 if (Refs.
empty() && Align == 0)
403 uint8_t *DestContent = Storage.
data() +
sizeof(RecordPrefix);
405 for (
auto &
Ref : Refs) {
407 reinterpret_cast<TypeIndex *
>(DestContent +
Ref.Offset);
409 for (
size_t I = 0;
I <
Ref.Count; ++
I) {
410 TypeIndex &TI = DestTIs[
I];
411 bool Success = (
Ref.Kind == TiRefKind::IndexRef) ? remapItemIndex(TI)
412 : remapTypeIndex(TI);
419 RecordPrefix *StorageHeader =
420 reinterpret_cast<RecordPrefix *
>(Storage.
data());
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();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_UNLIKELY(EXPR)
#define LLVM_LIKELY(EXPR)
static std::pair< std::vector< int64_t >, std::vector< int64_t > > remapIndices(Function &Caller, BasicBlock *StartBB, PGOContextualProfile &CtxProf, uint32_t CalleeCounters, uint32_t CalleeCallsites)
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
LLVM_ABI 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.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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)
uint32_t toArrayIndex() const
static const uint32_t FirstNonSimpleIndex
uint32_t getIndex() const
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
CVRecord< TypeLeafKind > CVType
Error forEachCodeViewRecord(ArrayRef< uint8_t > StreamBuffer, Func F)
VarStreamArray< CVType > CVTypeArray
LLVM_ABI void discoverTypeIndices(ArrayRef< uint8_t > RecordData, SmallVectorImpl< TiReference > &Refs)
LLVM_ABI Error mergeIdRecords(MergingTypeTableBuilder &Dest, ArrayRef< TypeIndex > Types, SmallVectorImpl< TypeIndex > &SourceToDest, const CVTypeArray &Ids)
Merge one set of id records into another.
LLVM_ABI 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.
LLVM_ABI 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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
@ 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.
ArrayRef(const T &OneElt) -> ArrayRef< T >
Used to forward information about PCH.OBJ (precompiled) files, when applicable.