diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-30 16:33:32 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-30 16:33:32 +0000 |
commit | 51315c45ff5643a27f9c84b816db54ee870ba29b (patch) | |
tree | 1d87443fa0e53d3e6b315ce25787e64be0906bf7 /contrib/llvm/lib/DebugInfo/CodeView | |
parent | 6dfd050075216be8538ae375a22d30db72916f7e (diff) | |
parent | eb11fae6d08f479c0799db45860a98af528fa6e7 (diff) |
Merge llvm trunk r338150, and resolve conflicts.
Notes
Notes:
svn path=/projects/clang700-import/; revision=336916
Diffstat (limited to 'contrib/llvm/lib/DebugInfo/CodeView')
11 files changed, 191 insertions, 147 deletions
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp index ccc20eb74887..0f155a95d607 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp @@ -109,7 +109,7 @@ Error DebugChecksumsSubsection::commit(BinaryStreamWriter &Writer) const { } uint32_t DebugChecksumsSubsection::mapChecksumOffset(StringRef FileName) const { - uint32_t Offset = Strings.getStringId(FileName); + uint32_t Offset = Strings.getIdForString(FileName); auto Iter = OffsetMap.find(Offset); assert(Iter != OffsetMap.end()); return Iter->second; diff --git a/contrib/llvm/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp index 88c0076915b5..bf9dd7c86862 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp @@ -79,14 +79,14 @@ Error DebugCrossModuleImportsSubsection::commit( for (const auto &M : Mappings) Ids.push_back(&M); - std::sort(Ids.begin(), Ids.end(), [this](const T &L1, const T &L2) { - return Strings.getStringId(L1->getKey()) < - Strings.getStringId(L2->getKey()); + llvm::sort(Ids.begin(), Ids.end(), [this](const T &L1, const T &L2) { + return Strings.getIdForString(L1->getKey()) < + Strings.getIdForString(L2->getKey()); }); for (const auto &Item : Ids) { CrossModuleImport Imp; - Imp.ModuleNameOffset = Strings.getStringId(Item->getKey()); + Imp.ModuleNameOffset = Strings.getIdForString(Item->getKey()); Imp.Count = Item->getValue().size(); if (auto EC = Writer.writeObject(Imp)) return EC; diff --git a/contrib/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp index d723282eb715..d2acc9a21003 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp @@ -46,12 +46,15 @@ DebugStringTableSubsection::DebugStringTableSubsection() : DebugSubsection(DebugSubsectionKind::StringTable) {} uint32_t DebugStringTableSubsection::insert(StringRef S) { - auto P = Strings.insert({S, StringSize}); + auto P = StringToId.insert({S, StringSize}); // If a given string didn't exist in the string table, we want to increment - // the string table size. - if (P.second) + // the string table size and insert it into the reverse lookup. + if (P.second) { + IdToString.insert({P.first->getValue(), P.first->getKey()}); StringSize += S.size() + 1; // +1 for '\0' + } + return P.first->second; } @@ -67,7 +70,7 @@ Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const { if (auto EC = Writer.writeCString(StringRef())) return EC; - for (auto &Pair : Strings) { + for (auto &Pair : StringToId) { StringRef S = Pair.getKey(); uint32_t Offset = Begin + Pair.getValue(); Writer.setOffset(Offset); @@ -81,10 +84,25 @@ Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const { return Error::success(); } -uint32_t DebugStringTableSubsection::size() const { return Strings.size(); } +uint32_t DebugStringTableSubsection::size() const { return StringToId.size(); } + +std::vector<uint32_t> DebugStringTableSubsection::sortedIds() const { + std::vector<uint32_t> Result; + Result.reserve(IdToString.size()); + for (const auto &Entry : IdToString) + Result.push_back(Entry.first); + llvm::sort(Result.begin(), Result.end()); + return Result; +} + +uint32_t DebugStringTableSubsection::getIdForString(StringRef S) const { + auto Iter = StringToId.find(S); + assert(Iter != StringToId.end()); + return Iter->second; +} -uint32_t DebugStringTableSubsection::getStringId(StringRef S) const { - auto Iter = Strings.find(S); - assert(Iter != Strings.end()); +StringRef DebugStringTableSubsection::getStringForId(uint32_t Id) const { + auto Iter = IdToString.find(Id); + assert(Iter != IdToString.end()); return Iter->second; } diff --git a/contrib/llvm/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp index 3ecd684c1e39..e76f9e12f0af 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp @@ -55,9 +55,12 @@ Optional<TypeIndex> GlobalTypeTableBuilder::getNext(TypeIndex Prev) { CVType GlobalTypeTableBuilder::getType(TypeIndex Index) { CVType Type; Type.RecordData = SeenRecords[Index.toArrayIndex()]; - const RecordPrefix *P = - reinterpret_cast<const RecordPrefix *>(Type.RecordData.data()); - Type.Type = static_cast<TypeLeafKind>(uint16_t(P->RecordKind)); + if (!Type.RecordData.empty()) { + assert(Type.RecordData.size() >= sizeof(RecordPrefix)); + const RecordPrefix *P = + reinterpret_cast<const RecordPrefix *>(Type.RecordData.data()); + Type.Type = static_cast<TypeLeafKind>(uint16_t(P->RecordKind)); + } return Type; } @@ -89,31 +92,15 @@ void GlobalTypeTableBuilder::reset() { SeenRecords.clear(); } -static inline ArrayRef<uint8_t> stabilize(BumpPtrAllocator &Alloc, - ArrayRef<uint8_t> Data) { - uint8_t *Stable = Alloc.Allocate<uint8_t>(Data.size()); - memcpy(Stable, Data.data(), Data.size()); - return makeArrayRef(Stable, Data.size()); -} - -TypeIndex GlobalTypeTableBuilder::insertRecordAs(GloballyHashedType Hash, - CreateRecord Create) { - auto Result = HashedRecords.try_emplace(Hash, nextTypeIndex()); - - if (Result.second) { - ArrayRef<uint8_t> RecordData = stabilize(RecordStorage, Create()); - SeenRecords.push_back(RecordData); - SeenHashes.push_back(Hash); - } - - // Update the caller's copy of Record to point a stable copy. - return Result.first->second; -} - TypeIndex GlobalTypeTableBuilder::insertRecordBytes(ArrayRef<uint8_t> Record) { GloballyHashedType GHT = GloballyHashedType::hashType(Record, SeenHashes, SeenHashes); - return insertRecordAs(GHT, [Record]() { return Record; }); + return insertRecordAs(GHT, Record.size(), + [Record](MutableArrayRef<uint8_t> Data) { + assert(Data.size() == Record.size()); + ::memcpy(Data.data(), Record.data(), Record.size()); + return Data; + }); } TypeIndex diff --git a/contrib/llvm/lib/DebugInfo/CodeView/RecordName.cpp b/contrib/llvm/lib/DebugInfo/CodeView/RecordName.cpp index 15fb1724d23d..e50c43a1d481 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/RecordName.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/RecordName.cpp @@ -167,13 +167,6 @@ Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { StringRef Class = Types.getTypeName(MI.getContainingType()); Name = formatv("{0} {1}::*", Pointee, Class); } else { - if (Ptr.isConst()) - Name.append("const "); - if (Ptr.isVolatile()) - Name.append("volatile "); - if (Ptr.isUnaligned()) - Name.append("__unaligned "); - Name.append(Types.getTypeName(Ptr.getReferentType())); if (Ptr.getMode() == PointerMode::LValueReference) @@ -182,6 +175,17 @@ Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { Name.append("&&"); else if (Ptr.getMode() == PointerMode::Pointer) Name.append("*"); + + // Qualifiers in pointer records apply to the pointer, not the pointee, so + // they go on the right. + if (Ptr.isConst()) + Name.append(" const"); + if (Ptr.isVolatile()) + Name.append(" volatile"); + if (Ptr.isUnaligned()) + Name.append(" __unaligned"); + if (Ptr.isRestrict()) + Name.append(" __restrict"); } return Error::success(); } @@ -189,7 +193,6 @@ Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) { uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); - SmallString<256> TypeName; if (Mods & uint16_t(ModifierOptions::Const)) Name.append("const "); if (Mods & uint16_t(ModifierOptions::Volatile)) @@ -233,6 +236,16 @@ Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) { return Error::success(); } +Error TypeNameComputer::visitKnownRecord(CVType &CVR, + PrecompRecord &Precomp) { + return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, + EndPrecompRecord &EndPrecomp) { + return Error::success(); +} + std::string llvm::codeview::computeTypeName(TypeCollection &Types, TypeIndex Index) { TypeNameComputer Computer(Types); @@ -273,6 +286,8 @@ static int getSymbolNameOffset(CVSymbol Sym) { case SymbolKind::S_GMANDATA: case SymbolKind::S_LTHREAD32: case SymbolKind::S_GTHREAD32: + case SymbolKind::S_PROCREF: + case SymbolKind::S_LPROCREF: return 10; // See RegisterSym and LocalSym case SymbolKind::S_REGISTER: diff --git a/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp index df75f52661e1..af249adc9774 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -129,6 +129,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) { } Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) { + W.printString("Name", Thunk.Name); W.printNumber("Parent", Thunk.Parent); W.printNumber("End", Thunk.End); W.printNumber("Next", Thunk.Next); diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp index e7998b8732fe..7c68c9167c98 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp @@ -370,6 +370,7 @@ Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { W->printNumber("IsConst", Ptr.isConst()); W->printNumber("IsVolatile", Ptr.isVolatile()); W->printNumber("IsUnaligned", Ptr.isUnaligned()); + W->printNumber("IsRestrict", Ptr.isRestrict()); W->printNumber("SizeOf", Ptr.getSize()); if (Ptr.isPointerToMember()) { @@ -552,3 +553,18 @@ Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, LabelRecord &LR) { W->printEnum("Mode", uint16_t(LR.Mode), makeArrayRef(LabelTypeEnum)); return Error::success(); } + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, + PrecompRecord &Precomp) { + W->printHex("StartIndex", Precomp.getStartTypeIndex()); + W->printHex("Count", Precomp.getTypesCount()); + W->printHex("Signature", Precomp.getSignature()); + W->printString("PrecompFile", Precomp.getPrecompFilePath()); + return Error::success(); +} + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, + EndPrecompRecord &EndPrecomp) { + W->printHex("Signature", EndPrecomp.getSignature()); + return Error::success(); +} diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp index f5b28b2a2070..826faef35875 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp @@ -18,10 +18,10 @@ using namespace llvm::codeview; LocallyHashedType DenseMapInfo<LocallyHashedType>::Empty{0, {}}; LocallyHashedType DenseMapInfo<LocallyHashedType>::Tombstone{hash_code(-1), {}}; -static std::array<uint8_t, 20> EmptyHash; -static std::array<uint8_t, 20> TombstoneHash = { - {0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; +static std::array<uint8_t, 8> EmptyHash = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; +static std::array<uint8_t, 8> TombstoneHash = { + {0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; GloballyHashedType DenseMapInfo<GloballyHashedType>::Empty{EmptyHash}; GloballyHashedType DenseMapInfo<GloballyHashedType>::Tombstone{TombstoneHash}; @@ -39,6 +39,7 @@ GloballyHashedType::hashType(ArrayRef<uint8_t> RecordData, SHA1 S; S.init(); uint32_t Off = 0; + S.update(RecordData.take_front(sizeof(RecordPrefix))); RecordData = RecordData.drop_front(sizeof(RecordPrefix)); for (const auto &Ref : Refs) { // Hash any data that comes before this TiRef. @@ -70,5 +71,5 @@ GloballyHashedType::hashType(ArrayRef<uint8_t> RecordData, auto TrailingBytes = RecordData.drop_front(Off); S.update(TrailingBytes); - return {S.final()}; + return {S.final().take_back(8)}; } diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp index d283e9e6d2f1..95082d4a8e03 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp @@ -58,7 +58,7 @@ static inline uint32_t getEncodedIntegerLength(ArrayRef<uint8_t> Data) { 8, // LF_UQUADWORD }; - return Sizes[N - LF_NUMERIC]; + return 2 + Sizes[N - LF_NUMERIC]; } static inline uint32_t getCStringLength(ArrayRef<uint8_t> Data) { @@ -393,7 +393,7 @@ static bool discoverTypeIndices(ArrayRef<uint8_t> Content, SymbolKind Kind, Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type break; case SymbolKind::S_REGISTER: - Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type; + Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type break; case SymbolKind::S_CONSTANT: Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp index 9b8a6053da84..3203ff64d3b1 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp @@ -480,3 +480,18 @@ Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, return Error::success(); } + +Error TypeRecordMapping::visitKnownRecord(CVType &CVR, + PrecompRecord &Precomp) { + error(IO.mapInteger(Precomp.StartTypeIndex)); + error(IO.mapInteger(Precomp.TypesCount)); + error(IO.mapInteger(Precomp.Signature)); + error(IO.mapStringZ(Precomp.PrecompFilePath)); + return Error::success(); +} + +Error TypeRecordMapping::visitKnownRecord(CVType &CVR, + EndPrecompRecord &EndPrecomp) { + error(IO.mapInteger(EndPrecomp.Signature)); + return Error::success(); +} diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp index 6a94952c175b..e4f39dd988e1 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp @@ -20,6 +20,11 @@ using namespace llvm; using namespace llvm::codeview; +static inline size_t slotForIndex(TypeIndex Idx) { + assert(!Idx.isSimple() && "simple type indices have no slots"); + return Idx.getIndex() - TypeIndex::FirstNonSimpleIndex; +} + namespace { /// Implementation of CodeView type stream merging. @@ -94,8 +99,22 @@ private: void addMapping(TypeIndex Idx); - bool remapTypeIndex(TypeIndex &Idx); - bool remapItemIndex(TypeIndex &Idx); + inline bool remapTypeIndex(TypeIndex &Idx) { + // If we're mapping a pure index stream, then IndexMap only contains + // mappings from OldIdStream -> NewIdStream, in which case we will need to + // use the special mapping from OldTypeStream -> NewTypeStream which was + // computed externally. Regardless, we use this special map if and only if + // we are doing an id-only mapping. + if (!hasTypeStream()) + return remapIndex(Idx, TypeLookup); + + assert(TypeLookup.empty()); + return remapIndex(Idx, IndexMap); + } + inline bool remapItemIndex(TypeIndex &Idx) { + assert(hasIdStream()); + return remapIndex(Idx, IndexMap); + } bool hasTypeStream() const { return (UseGlobalHashes) ? (!!DestGlobalTypeStream) : (!!DestTypeStream); @@ -105,17 +124,34 @@ private: return (UseGlobalHashes) ? (!!DestGlobalIdStream) : (!!DestIdStream); } - ArrayRef<uint8_t> serializeRemapped(const RemappedType &Record); + ArrayRef<uint8_t> remapIndices(const CVType &OriginalType, + MutableArrayRef<uint8_t> Storage); - bool remapIndices(RemappedType &Record, ArrayRef<TiReference> Refs); + inline bool remapIndex(TypeIndex &Idx, ArrayRef<TypeIndex> Map) { + if (LLVM_LIKELY(remapIndexSimple(Idx, Map))) + return true; - bool remapIndex(TypeIndex &Idx, ArrayRef<TypeIndex> Map); + return remapIndexFallback(Idx, Map); + } + + inline bool remapIndexSimple(TypeIndex &Idx, ArrayRef<TypeIndex> Map) const { + // Simple types are unchanged. + if (Idx.isSimple()) + return true; - size_t slotForIndex(TypeIndex Idx) const { - assert(!Idx.isSimple() && "simple type indices have no slots"); - return Idx.getIndex() - TypeIndex::FirstNonSimpleIndex; + // Check if this type index refers to a record we've already translated + // successfully. If it refers to a type later in the stream or a record we + // had to defer, defer it until later pass. + unsigned MapPos = slotForIndex(Idx); + if (LLVM_UNLIKELY(MapPos >= Map.size() || Map[MapPos] == Untranslated)) + return false; + + Idx = Map[MapPos]; + return true; } + bool remapIndexFallback(TypeIndex &Idx, ArrayRef<TypeIndex> Map); + Error errorCorruptRecord() const { return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record); } @@ -153,27 +189,6 @@ private: } // end anonymous namespace -ArrayRef<uint8_t> -TypeStreamMerger::serializeRemapped(const RemappedType &Record) { - TypeIndex TI; - ArrayRef<uint8_t> OriginalData = Record.OriginalRecord.RecordData; - if (Record.Mappings.empty()) - return OriginalData; - - // At least one type index was remapped. We copy the full record bytes, - // re-write each type index, then return that. - 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 RemapRef; -} - const TypeIndex TypeStreamMerger::Untranslated(SimpleTypeKind::NotTranslated); static bool isIdRecord(TypeLeafKind K) { @@ -202,19 +217,9 @@ void TypeStreamMerger::addMapping(TypeIndex Idx) { } } -bool TypeStreamMerger::remapIndex(TypeIndex &Idx, ArrayRef<TypeIndex> Map) { - // Simple types are unchanged. - if (Idx.isSimple()) - return true; - - // Check if this type index refers to a record we've already translated - // successfully. If it refers to a type later in the stream or a record we - // had to defer, defer it until later pass. - unsigned MapPos = slotForIndex(Idx); - if (MapPos < Map.size() && Map[MapPos] != Untranslated) { - Idx = Map[MapPos]; - return true; - } +bool TypeStreamMerger::remapIndexFallback(TypeIndex &Idx, + ArrayRef<TypeIndex> Map) { + size_t MapPos = slotForIndex(Idx); // If this is the second pass and this index isn't in the map, then it points // outside the current type stream, and this is a corrupt record. @@ -232,24 +237,6 @@ bool TypeStreamMerger::remapIndex(TypeIndex &Idx, ArrayRef<TypeIndex> Map) { return false; } -bool TypeStreamMerger::remapTypeIndex(TypeIndex &Idx) { - // If we're mapping a pure index stream, then IndexMap only contains mappings - // from OldIdStream -> NewIdStream, in which case we will need to use the - // special mapping from OldTypeStream -> NewTypeStream which was computed - // externally. Regardless, we use this special map if and only if we are - // doing an id-only mapping. - if (!hasTypeStream()) - return remapIndex(Idx, TypeLookup); - - assert(TypeLookup.empty()); - return remapIndex(Idx, IndexMap); -} - -bool TypeStreamMerger::remapItemIndex(TypeIndex &Idx) { - assert(hasIdStream()); - return remapIndex(Idx, IndexMap); -} - // Local hashing entry points Error TypeStreamMerger::mergeTypeRecords(MergingTypeTableBuilder &Dest, const CVTypeArray &Types) { @@ -346,35 +333,34 @@ Error TypeStreamMerger::doit(const CVTypeArray &Types) { } Error TypeStreamMerger::remapAllTypes(const CVTypeArray &Types) { - for (const CVType &Type : Types) - if (auto EC = remapType(Type)) - return EC; - return Error::success(); + BinaryStreamRef Stream = Types.getUnderlyingStream(); + ArrayRef<uint8_t> Buffer; + cantFail(Stream.readBytes(0, Stream.getLength(), Buffer)); + + return forEachCodeViewRecord<CVType>( + Buffer, [this](const CVType &T) { return remapType(T); }); } Error TypeStreamMerger::remapType(const CVType &Type) { - auto DoSerialize = [this, Type]() -> ArrayRef<uint8_t> { - RemappedType R(Type); - SmallVector<TiReference, 32> Refs; - discoverTypeIndices(Type.RecordData, Refs); - if (!remapIndices(R, Refs)) - return {}; - return serializeRemapped(R); + auto DoSerialize = + [this, Type](MutableArrayRef<uint8_t> Storage) -> ArrayRef<uint8_t> { + return remapIndices(Type, Storage); }; TypeIndex DestIdx = Untranslated; - if (UseGlobalHashes) { + if (LLVM_LIKELY(UseGlobalHashes)) { GlobalTypeTableBuilder &Dest = isIdRecord(Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream; GloballyHashedType H = GlobalHashes[CurIndex.toArrayIndex()]; - DestIdx = Dest.insertRecordAs(H, DoSerialize); + DestIdx = Dest.insertRecordAs(H, Type.RecordData.size(), DoSerialize); } else { MergingTypeTableBuilder &Dest = isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream; - auto Data = DoSerialize(); - if (!Data.empty()) - DestIdx = Dest.insertRecordBytes(Data); + RemapStorage.resize(Type.RecordData.size()); + ArrayRef<uint8_t> Result = DoSerialize(RemapStorage); + if (!Result.empty()) + DestIdx = Dest.insertRecordBytes(Result); } addMapping(DestIdx); @@ -384,27 +370,32 @@ Error TypeStreamMerger::remapType(const CVType &Type) { return Error::success(); } -bool TypeStreamMerger::remapIndices(RemappedType &Record, - ArrayRef<TiReference> Refs) { - ArrayRef<uint8_t> OriginalData = Record.OriginalRecord.content(); - bool Success = true; +ArrayRef<uint8_t> +TypeStreamMerger::remapIndices(const CVType &OriginalType, + MutableArrayRef<uint8_t> Storage) { + SmallVector<TiReference, 4> Refs; + discoverTypeIndices(OriginalType.RecordData, Refs); + if (Refs.empty()) + return OriginalType.RecordData; + + ::memcpy(Storage.data(), OriginalType.RecordData.data(), + OriginalType.RecordData.size()); + + uint8_t *DestContent = Storage.data() + sizeof(RecordPrefix); + for (auto &Ref : Refs) { - uint32_t Offset = Ref.Offset; - ArrayRef<uint8_t> Bytes = OriginalData.slice(Ref.Offset, sizeof(TypeIndex)); - ArrayRef<TypeIndex> TIs(reinterpret_cast<const TypeIndex *>(Bytes.data()), - Ref.Count); - for (auto TI : TIs) { - TypeIndex NewTI = TI; - bool ThisSuccess = (Ref.Kind == TiRefKind::IndexRef) - ? remapItemIndex(NewTI) - : remapTypeIndex(NewTI); - if (ThisSuccess && NewTI != TI) - Record.Mappings.emplace_back(Offset, NewTI); - Offset += sizeof(TypeIndex); - Success &= ThisSuccess; + TypeIndex *DestTIs = + reinterpret_cast<TypeIndex *>(DestContent + Ref.Offset); + + for (size_t I = 0; I < Ref.Count; ++I) { + TypeIndex &TI = DestTIs[I]; + bool Success = (Ref.Kind == TiRefKind::IndexRef) ? remapItemIndex(TI) + : remapTypeIndex(TI); + if (LLVM_UNLIKELY(!Success)) + return {}; } } - return Success; + return Storage; } Error llvm::codeview::mergeTypeRecords(MergingTypeTableBuilder &Dest, |