diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp | 20 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp | 90 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp | 277 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp | 8 |
4 files changed, 250 insertions, 145 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp index f95c3e79388..705b548141b 100644 --- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -45,24 +45,9 @@ static Error visitKnownMember(CVMemberRecord &Record, } static Expected<TypeServer2Record> deserializeTypeServerRecord(CVType &Record) { - class StealTypeServerVisitor : public TypeVisitorCallbacks { - public: - explicit StealTypeServerVisitor(TypeServer2Record &TR) : TR(TR) {} - - Error visitKnownRecord(CVType &CVR, TypeServer2Record &Record) override { - TR = Record; - return Error::success(); - } - - private: - TypeServer2Record &TR; - }; - TypeServer2Record R(TypeRecordKind::TypeServer2); - StealTypeServerVisitor Thief(R); - if (auto EC = visitTypeRecord(Record, Thief)) + if (auto EC = TypeDeserializer::deserializeAs(Record, R)) return std::move(EC); - return R; } @@ -308,8 +293,9 @@ Error llvm::codeview::visitTypeRecord(CVType &Record, Error llvm::codeview::visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks, + VisitorDataSource Source, TypeServerHandler *TS) { - VisitHelper V(Callbacks, VDS_BytesPresent); + VisitHelper V(Callbacks, Source); if (TS) V.Visitor.addTypeServerHandler(*TS); return V.Visitor.visitTypeStream(Types); diff --git a/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp b/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp index c667a73d086..4894277947b 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp @@ -75,29 +75,23 @@ private: /// entries are small and easy to rehash. DenseSet<HashedTypePtr> HashedRecords; - SmallVector<ArrayRef<uint8_t>, 2> SeenRecords; - - TypeIndex NextTypeIndex = TypeIndex(TypeIndex::FirstNonSimpleIndex); - public: TypeHasher(BumpPtrAllocator &RecordStorage) : RecordStorage(RecordStorage) {} - ArrayRef<ArrayRef<uint8_t>> records() const { return SeenRecords; } - /// Takes the bytes of type record, inserts them into the hash table, saves /// them, and returns a pointer to an identical stable type record along with /// its type index in the destination stream. - TypeIndex getOrCreateRecord(ArrayRef<uint8_t> &Record); + TypeIndex getOrCreateRecord(ArrayRef<uint8_t> &Record, TypeIndex TI); }; -TypeIndex TypeHasher::getOrCreateRecord(ArrayRef<uint8_t> &Record) { +TypeIndex TypeHasher::getOrCreateRecord(ArrayRef<uint8_t> &Record, + TypeIndex TI) { assert(Record.size() < UINT32_MAX && "Record too big"); assert(Record.size() % 4 == 0 && "Record is not aligned to 4 bytes!"); // Compute the hash up front so we can store it in the key. HashedType TempHashedType = {hash_value(Record), Record.data(), - unsigned(Record.size()), NextTypeIndex}; - + unsigned(Record.size()), TI}; auto Result = HashedRecords.insert(HashedTypePtr(&TempHashedType)); HashedType *&Hashed = Result.first->Ptr; @@ -111,20 +105,15 @@ TypeIndex TypeHasher::getOrCreateRecord(ArrayRef<uint8_t> &Record) { memcpy(Stable, Record.data(), Record.size()); Hashed->Data = Stable; assert(Hashed->Size == Record.size()); - - // This was a new record, so increment our next type index. - ++NextTypeIndex; } // Update the caller's copy of Record to point a stable copy. Record = ArrayRef<uint8_t>(Hashed->Data, Hashed->Size); + return Hashed->Index; +} - if (Result.second) { - // FIXME: Can we record these in a more efficient way? - SeenRecords.push_back(Record); - } - - return TypeIndex(Hashed->Index); +TypeIndex TypeSerializer::nextTypeIndex() const { + return TypeIndex::fromArrayIndex(SeenRecords.size()); } bool TypeSerializer::isInFieldList() const { @@ -166,26 +155,68 @@ TypeSerializer::addPadding(MutableArrayRef<uint8_t> Record) { return MutableArrayRef<uint8_t>(Record.data(), Record.size() + N); } -TypeSerializer::TypeSerializer(BumpPtrAllocator &Storage) +TypeSerializer::TypeSerializer(BumpPtrAllocator &Storage, bool Hash) : RecordStorage(Storage), RecordBuffer(MaxRecordLength * 2), Stream(RecordBuffer, llvm::support::little), Writer(Stream), - Mapping(Writer), Hasher(make_unique<TypeHasher>(Storage)) { + Mapping(Writer) { // RecordBuffer needs to be able to hold enough data so that if we are 1 // byte short of MaxRecordLen, and then we try to write MaxRecordLen bytes, // we won't overflow. + if (Hash) + Hasher = make_unique<TypeHasher>(Storage); } TypeSerializer::~TypeSerializer() = default; ArrayRef<ArrayRef<uint8_t>> TypeSerializer::records() const { - return Hasher->records(); + return SeenRecords; } -TypeIndex TypeSerializer::insertRecordBytes(ArrayRef<uint8_t> Record) { +TypeIndex TypeSerializer::insertRecordBytes(ArrayRef<uint8_t> &Record) { assert(!TypeKind.hasValue() && "Already in a type mapping!"); assert(Writer.getOffset() == 0 && "Stream has data already!"); - return Hasher->getOrCreateRecord(Record); + if (Hasher) { + TypeIndex ActualTI = Hasher->getOrCreateRecord(Record, nextTypeIndex()); + if (nextTypeIndex() == ActualTI) + SeenRecords.push_back(Record); + return ActualTI; + } + + TypeIndex NewTI = nextTypeIndex(); + uint8_t *Stable = RecordStorage.Allocate<uint8_t>(Record.size()); + memcpy(Stable, Record.data(), Record.size()); + Record = ArrayRef<uint8_t>(Stable, Record.size()); + SeenRecords.push_back(Record); + return NewTI; +} + +TypeIndex TypeSerializer::insertRecord(const RemappedType &Record) { + assert(!TypeKind.hasValue() && "Already in a type mapping!"); + assert(Writer.getOffset() == 0 && "Stream has data already!"); + + TypeIndex TI; + ArrayRef<uint8_t> OriginalData = Record.OriginalRecord.RecordData; + if (Record.Mappings.empty()) { + // This record did not remap any type indices. Just write it. + return insertRecordBytes(OriginalData); + } + + // At least one type index was remapped. Before we can hash it we have to + // copy the full record bytes, re-write each type index, then hash the copy. + // We do this in temporary storage since only the DenseMap can decide whether + // this record already exists, and if it does we don't want the memory to + // stick around. + RemapStorage.resize(OriginalData.size()); + ::memcpy(&RemapStorage[0], OriginalData.data(), OriginalData.size()); + uint8_t *ContentBegin = RemapStorage.data() + sizeof(RecordPrefix); + for (const auto &M : Record.Mappings) { + // First 4 bytes of every record are the record prefix, but the mapping + // offset is relative to the content which starts after. + *(TypeIndex *)(ContentBegin + M.first) = M.second; + } + auto RemapRef = makeArrayRef(RemapStorage); + return insertRecordBytes(RemapRef); } Error TypeSerializer::visitTypeBegin(CVType &Record) { @@ -221,7 +252,12 @@ Expected<TypeIndex> TypeSerializer::visitTypeEndGetIndex(CVType &Record) { Record.Type = *TypeKind; Record.RecordData = ThisRecordData; - TypeIndex InsertedTypeIndex = Hasher->getOrCreateRecord(Record.RecordData); + + // insertRecordBytes assumes we're not in a mapping, so do this first. + TypeKind.reset(); + Writer.setOffset(0); + + TypeIndex InsertedTypeIndex = insertRecordBytes(Record.RecordData); // Write out each additional segment in reverse order, and update each // record's continuation index to point to the previous one. @@ -231,11 +267,9 @@ Expected<TypeIndex> TypeSerializer::visitTypeEndGetIndex(CVType &Record) { reinterpret_cast<support::ulittle32_t *>(CIBytes.data()); assert(*CI == 0xB0C0B0C0 && "Invalid TypeIndex placeholder"); *CI = InsertedTypeIndex.getIndex(); - InsertedTypeIndex = Hasher->getOrCreateRecord(X); + InsertedTypeIndex = insertRecordBytes(X); } - TypeKind.reset(); - Writer.setOffset(0); FieldListSegments.clear(); CurrentSegment.SubRecords.clear(); diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp index 383799bca7e..0f8357ca80f 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" @@ -95,6 +96,33 @@ private: bool remapTypeIndex(TypeIndex &Idx); bool remapItemIndex(TypeIndex &Idx); + bool remapIndices(RemappedType &Record, ArrayRef<uint32_t> TidOffs, + ArrayRef<uint32_t> IidOffs) { + auto OriginalData = Record.OriginalRecord.content(); + bool Success = true; + for (auto Off : TidOffs) { + ArrayRef<uint8_t> Bytes = OriginalData.slice(Off, sizeof(TypeIndex)); + TypeIndex OldTI( + *reinterpret_cast<const support::ulittle32_t *>(Bytes.data())); + TypeIndex NewTI = OldTI; + bool ThisSuccess = remapTypeIndex(NewTI); + if (ThisSuccess && NewTI != OldTI) + Record.Mappings.emplace_back(Off, NewTI); + Success &= ThisSuccess; + } + for (auto Off : IidOffs) { + ArrayRef<uint8_t> Bytes = OriginalData.slice(Off, sizeof(TypeIndex)); + TypeIndex OldTI( + *reinterpret_cast<const support::ulittle32_t *>(Bytes.data())); + TypeIndex NewTI = OldTI; + bool ThisSuccess = remapItemIndex(NewTI); + if (ThisSuccess && NewTI != OldTI) + Record.Mappings.emplace_back(Off, NewTI); + Success &= ThisSuccess; + } + return Success; + } + bool remapIndex(TypeIndex &Idx, ArrayRef<TypeIndex> Map); size_t slotForIndex(TypeIndex Idx) const { @@ -107,23 +135,49 @@ private: } template <typename RecordType> - Error writeRecord(RecordType &R, bool RemapSuccess) { + Error writeKnownRecord(TypeTableBuilder &Dest, RecordType &R, + bool RemapSuccess) { TypeIndex DestIdx = Untranslated; if (RemapSuccess) - DestIdx = DestTypeStream->writeKnownType(R); + DestIdx = Dest.writeKnownType(R); addMapping(DestIdx); return Error::success(); } template <typename RecordType> - Error writeIdRecord(RecordType &R, bool RemapSuccess) { + Error writeKnownTypeRecord(RecordType &R, bool RemapSuccess) { + return writeKnownRecord(*DestTypeStream, R, RemapSuccess); + } + + template <typename RecordType> + Error writeKnownIdRecord(RecordType &R, bool RemapSuccess) { + return writeKnownRecord(*DestIdStream, R, RemapSuccess); + } + + Error writeRecord(TypeTableBuilder &Dest, const RemappedType &Record, + bool RemapSuccess) { TypeIndex DestIdx = Untranslated; if (RemapSuccess) - DestIdx = DestIdStream->writeKnownType(R); + DestIdx = Dest.writeSerializedRecord(Record); addMapping(DestIdx); return Error::success(); } + Error writeTypeRecord(const CVType &Record) { + TypeIndex DestIdx = + DestTypeStream->writeSerializedRecord(Record.RecordData); + addMapping(DestIdx); + return Error::success(); + } + + Error writeTypeRecord(const RemappedType &Record, bool RemapSuccess) { + return writeRecord(*DestTypeStream, Record, RemapSuccess); + } + + Error writeIdRecord(const RemappedType &Record, bool RemapSuccess) { + return writeRecord(*DestIdStream, Record, RemapSuccess); + } + template <typename RecordType> Error writeMember(RecordType &R, bool RemapSuccess) { if (RemapSuccess) @@ -163,12 +217,10 @@ private: const TypeIndex TypeStreamMerger::Untranslated(SimpleTypeKind::NotTranslated); -Error TypeStreamMerger::visitTypeBegin(CVRecord<TypeLeafKind> &Rec) { - return Error::success(); -} +Error TypeStreamMerger::visitTypeBegin(CVType &Rec) { return Error::success(); } -Error TypeStreamMerger::visitTypeEnd(CVRecord<TypeLeafKind> &Rec) { - CurIndex = TypeIndex(CurIndex.getIndex() + 1); +Error TypeStreamMerger::visitTypeEnd(CVType &Rec) { + ++CurIndex; if (!IsSecondPass) assert(IndexMap.size() == slotForIndex(CurIndex) && "visitKnownRecord should add one index map entry"); @@ -242,184 +294,206 @@ bool TypeStreamMerger::remapItemIndex(TypeIndex &Idx) { // Item records //----------------------------------------------------------------------------// -Error TypeStreamMerger::visitKnownRecord(CVType &, FuncIdRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, FuncIdRecord &R) { assert(DestIdStream); - bool Success = true; - Success &= remapItemIndex(R.ParentScope); - Success &= remapTypeIndex(R.FunctionType); - return writeIdRecord(R, Success); + + RemappedType RR(CVR); + return writeIdRecord(RR, remapIndices(RR, {4}, {0})); } -Error TypeStreamMerger::visitKnownRecord(CVType &, MemberFuncIdRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &R) { assert(DestIdStream); - bool Success = true; - Success &= remapTypeIndex(R.ClassType); - Success &= remapTypeIndex(R.FunctionType); - return writeIdRecord(R, Success); + + RemappedType RR(CVR); + return writeIdRecord(RR, remapIndices(RR, {0, 4}, {})); } -Error TypeStreamMerger::visitKnownRecord(CVType &, StringIdRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, StringIdRecord &R) { assert(DestIdStream); - return writeIdRecord(R, remapItemIndex(R.Id)); + + RemappedType RR(CVR); + return writeIdRecord(RR, remapIndices(RR, {}, {0})); } -Error TypeStreamMerger::visitKnownRecord(CVType &, StringListRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, StringListRecord &R) { assert(DestIdStream); + + if (auto EC = TypeDeserializer::deserializeAs<StringListRecord>(CVR, R)) + return EC; bool Success = true; - for (TypeIndex &Str : R.StringIndices) - Success &= remapItemIndex(Str); - return writeIdRecord(R, Success); + + for (TypeIndex &Id : R.StringIndices) + Success &= remapItemIndex(Id); + return writeKnownIdRecord(R, Success); } -Error TypeStreamMerger::visitKnownRecord(CVType &, BuildInfoRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, BuildInfoRecord &R) { assert(DestIdStream); + + if (auto EC = TypeDeserializer::deserializeAs(CVR, R)) + return EC; + bool Success = true; - for (TypeIndex &Arg : R.ArgIndices) - Success &= remapItemIndex(Arg); - return writeIdRecord(R, Success); + for (TypeIndex &Str : R.ArgIndices) + Success &= remapItemIndex(Str); + return writeKnownIdRecord(R, Success); } -Error TypeStreamMerger::visitKnownRecord(CVType &, UdtSourceLineRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, UdtSourceLineRecord &R) { assert(DestIdStream); - bool Success = true; - Success &= remapTypeIndex(R.UDT); - Success &= remapItemIndex(R.SourceFile); + + RemappedType RR(CVR); + // FIXME: Translate UdtSourceLineRecord into UdtModSourceLineRecords in the // IPI stream. - return writeIdRecord(R, Success); + return writeIdRecord(RR, remapIndices(RR, {0}, {4})); } -Error TypeStreamMerger::visitKnownRecord(CVType &, UdtModSourceLineRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, + UdtModSourceLineRecord &R) { assert(DestIdStream); - bool Success = true; - Success &= remapTypeIndex(R.UDT); - // UdtModSourceLine Source File Ids are offsets into the global string table. + + RemappedType RR(CVR); + + // UdtModSourceLine Source File Ids are offsets into the global string table, + // not type indices. // FIXME: We need to merge string table records for this to be valid. - // Success &= remapItemIndex(R.SourceFile); - return writeIdRecord(R, Success); + return writeIdRecord(RR, remapIndices(RR, {0}, {})); } //----------------------------------------------------------------------------// // Type records //----------------------------------------------------------------------------// -Error TypeStreamMerger::visitKnownRecord(CVType &, ModifierRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, ModifierRecord &R) { assert(DestTypeStream); - return writeRecord(R, remapTypeIndex(R.ModifiedType)); + + RemappedType RR(CVR); + return writeTypeRecord(RR, remapIndices(RR, {0}, {})); } -Error TypeStreamMerger::visitKnownRecord(CVType &, ProcedureRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, ProcedureRecord &R) { assert(DestTypeStream); - bool Success = true; - Success &= remapTypeIndex(R.ReturnType); - Success &= remapTypeIndex(R.ArgumentList); - return writeRecord(R, Success); + + RemappedType RR(CVR); + return writeTypeRecord(RR, remapIndices(RR, {0, 8}, {})); } -Error TypeStreamMerger::visitKnownRecord(CVType &, MemberFunctionRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, MemberFunctionRecord &R) { assert(DestTypeStream); - bool Success = true; - Success &= remapTypeIndex(R.ReturnType); - Success &= remapTypeIndex(R.ClassType); - Success &= remapTypeIndex(R.ThisType); - Success &= remapTypeIndex(R.ArgumentList); - return writeRecord(R, Success); + + RemappedType RR(CVR); + return writeTypeRecord(RR, remapIndices(RR, {0, 4, 8, 16}, {})); } -Error TypeStreamMerger::visitKnownRecord(CVType &Type, ArgListRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, ArgListRecord &R) { assert(DestTypeStream); + + if (auto EC = TypeDeserializer::deserializeAs(CVR, R)) + return EC; + bool Success = true; for (TypeIndex &Arg : R.ArgIndices) Success &= remapTypeIndex(Arg); - if (auto EC = writeRecord(R, Success)) - return EC; - return Error::success(); + + return writeKnownTypeRecord(R, Success); } -Error TypeStreamMerger::visitKnownRecord(CVType &, PointerRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, PointerRecord &R) { assert(DestTypeStream); - bool Success = true; - Success &= remapTypeIndex(R.ReferentType); + + // Pointer records have a different number of TypeIndex mappings depending + // on whether or not it is a pointer to member. + if (auto EC = TypeDeserializer::deserializeAs(CVR, R)) + return EC; + + bool Success = remapTypeIndex(R.ReferentType); if (R.isPointerToMember()) Success &= remapTypeIndex(R.MemberInfo->ContainingType); - return writeRecord(R, Success); + return writeKnownTypeRecord(R, Success); } -Error TypeStreamMerger::visitKnownRecord(CVType &, ArrayRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, ArrayRecord &R) { assert(DestTypeStream); - bool Success = true; - Success &= remapTypeIndex(R.ElementType); - Success &= remapTypeIndex(R.IndexType); - return writeRecord(R, Success); + + RemappedType RR(CVR); + return writeTypeRecord(RR, remapIndices(RR, {0, 4}, {})); } -Error TypeStreamMerger::visitKnownRecord(CVType &, ClassRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, ClassRecord &R) { assert(DestTypeStream); - bool Success = true; - Success &= remapTypeIndex(R.FieldList); - Success &= remapTypeIndex(R.DerivationList); - Success &= remapTypeIndex(R.VTableShape); - return writeRecord(R, Success); + + RemappedType RR(CVR); + return writeTypeRecord(RR, remapIndices(RR, {4, 8, 12}, {})); } -Error TypeStreamMerger::visitKnownRecord(CVType &, UnionRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, UnionRecord &R) { assert(DestTypeStream); - return writeRecord(R, remapTypeIndex(R.FieldList)); + + RemappedType RR(CVR); + return writeTypeRecord(RR, remapIndices(RR, {4}, {})); } -Error TypeStreamMerger::visitKnownRecord(CVType &, EnumRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, EnumRecord &R) { assert(DestTypeStream); - bool Success = true; - Success &= remapTypeIndex(R.FieldList); - Success &= remapTypeIndex(R.UnderlyingType); - return writeRecord(R, Success); + + RemappedType RR(CVR); + return writeTypeRecord(RR, remapIndices(RR, {4, 8}, {})); } -Error TypeStreamMerger::visitKnownRecord(CVType &, BitFieldRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, BitFieldRecord &R) { assert(DestTypeStream); - return writeRecord(R, remapTypeIndex(R.Type)); + + RemappedType RR(CVR); + return writeTypeRecord(RR, remapIndices(RR, {0}, {})); } -Error TypeStreamMerger::visitKnownRecord(CVType &, VFTableShapeRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, VFTableShapeRecord &R) { assert(DestTypeStream); - return writeRecord(R, true); + + return writeTypeRecord(CVR); } -Error TypeStreamMerger::visitKnownRecord(CVType &, TypeServer2Record &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, TypeServer2Record &R) { assert(DestTypeStream); - return writeRecord(R, true); + + return writeTypeRecord(CVR); } -Error TypeStreamMerger::visitKnownRecord(CVType &, LabelRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, LabelRecord &R) { assert(DestTypeStream); - return writeRecord(R, true); + + return writeTypeRecord(CVR); } -Error TypeStreamMerger::visitKnownRecord(CVType &, VFTableRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, VFTableRecord &R) { assert(DestTypeStream); - bool Success = true; - Success &= remapTypeIndex(R.CompleteClass); - Success &= remapTypeIndex(R.OverriddenVFTable); - return writeRecord(R, Success); + + RemappedType RR(CVR); + return writeTypeRecord(RR, remapIndices(RR, {0, 4}, {})); } -Error TypeStreamMerger::visitKnownRecord(CVType &, +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, MethodOverloadListRecord &R) { assert(DestTypeStream); + + if (auto EC = TypeDeserializer::deserializeAs(CVR, R)) + return EC; + bool Success = true; for (OneMethodRecord &Meth : R.Methods) Success &= remapTypeIndex(Meth.Type); - return writeRecord(R, Success); + return writeKnownTypeRecord(R, Success); } -Error TypeStreamMerger::visitKnownRecord(CVType &, FieldListRecord &R) { +Error TypeStreamMerger::visitKnownRecord(CVType &CVR, FieldListRecord &R) { assert(DestTypeStream); // Visit the members inside the field list. HadUntranslatedMember = false; FieldListBuilder = llvm::make_unique<FieldListRecordBuilder>(*DestTypeStream); FieldListBuilder->begin(); - if (auto EC = codeview::visitMemberRecordStream(R.Data, *this)) + if (auto EC = codeview::visitMemberRecordStream(CVR.content(), *this)) return EC; // Write the record if we translated all field list members. @@ -524,7 +598,11 @@ Error TypeStreamMerger::mergeTypesAndIds(TypeTableBuilder &DestIds, Error TypeStreamMerger::doit(const CVTypeArray &Types) { LastError = Error::success(); - if (auto EC = codeview::visitTypeStream(Types, *this, Handler)) + // We don't want to deserialize records. I guess this flag is poorly named, + // but it really means "Don't deserialize records before switching on the + // concrete type. + if (auto EC = + codeview::visitTypeStream(Types, *this, VDS_BytesExternal, Handler)) return EC; // If we found bad indices but no other errors, try doing another pass and see @@ -540,7 +618,8 @@ Error TypeStreamMerger::doit(const CVTypeArray &Types) { NumBadIndices = 0; CurIndex = TypeIndex(TypeIndex::FirstNonSimpleIndex); - if (auto EC = codeview::visitTypeStream(Types, *this, Handler)) + if (auto EC = + codeview::visitTypeStream(Types, *this, VDS_BytesExternal, Handler)) return EC; assert(NumBadIndices <= BadIndicesRemaining && diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp index f00567db743..6ef987354aa 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp @@ -57,7 +57,13 @@ PDBTypeServerHandler::handleInternal(PDBFile &File, if (!ExpectedTpi) return ExpectedTpi.takeError(); - if (auto EC = codeview::visitTypeStream(ExpectedTpi->typeArray(), Callbacks)) + // For handling a type server, we should be using whatever the callback array + // was + // that is being used for the original file. We shouldn't allow the visitor + // to + // arbitrarily stick a deserializer in there. + if (auto EC = codeview::visitTypeStream(ExpectedTpi->typeArray(), Callbacks, + VDS_BytesExternal)) return std::move(EC); return true; |