diff options
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, | 
