[llvm] r320719 - [COFF] Teach LLD to use the COFF .debug$H section.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 14 10:07:04 PST 2017


Author: zturner
Date: Thu Dec 14 10:07:04 2017
New Revision: 320719

URL: http://llvm.org/viewvc/llvm-project?rev=320719&view=rev
Log:
[COFF] Teach LLD to use the COFF .debug$H section.

This adds the /DEBUG:GHASH option to LLD which will look for
the existence of .debug$H sections in linker inputs and use them
to accelerate type merging.  The clang-cl side has already been
added, so this completes the work necessary to begin experimenting
with this feature.

Differential Revision: https://reviews.llvm.org/D40980

Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeHashing.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
    llvm/trunk/include/llvm/Object/COFF.h
    llvm/trunk/lib/DebugInfo/CodeView/TypeHashing.cpp
    llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeHashing.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeHashing.h?rev=320719&r1=320718&r2=320719&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeHashing.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeHashing.h Thu Dec 14 10:07:04 2017
@@ -88,18 +88,39 @@ struct GloballyHashedType {
                                      ArrayRef<GloballyHashedType> PreviousTypes,
                                      ArrayRef<GloballyHashedType> PreviousIds);
 
+  /// Given a sequence of bytes representing a record, compute a global hash for
+  /// this record.  Due to the nature of global hashes incorporating the hashes
+  /// of referenced records, this function requires a list of types and ids
+  /// that RecordData might reference, indexable by TypeIndex.
+  static GloballyHashedType hashType(CVType Type,
+                                     ArrayRef<GloballyHashedType> PreviousTypes,
+                                     ArrayRef<GloballyHashedType> PreviousIds) {
+    return hashType(Type.RecordData, PreviousTypes, PreviousIds);
+  }
+
   /// Given a sequence of combined type and ID records, compute global hashes
   /// for each of them, returning the results in a vector of hashed types.
   template <typename Range>
   static std::vector<GloballyHashedType> hashTypes(Range &&Records) {
     std::vector<GloballyHashedType> Hashes;
-    Hashes.reserve(std::distance(std::begin(Records), std::end(Records)));
     for (const auto &R : Records)
       Hashes.push_back(hashType(R, Hashes, Hashes));
 
     return Hashes;
   }
 
+  /// Given a sequence of combined type and ID records, compute global hashes
+  /// for each of them, returning the results in a vector of hashed types.
+  template <typename Range>
+  static std::vector<GloballyHashedType>
+  hashIds(Range &&Records, ArrayRef<GloballyHashedType> TypeHashes) {
+    std::vector<GloballyHashedType> IdHashes;
+    for (const auto &R : Records)
+      IdHashes.push_back(hashType(R, TypeHashes, IdHashes));
+
+    return IdHashes;
+  }
+
   static std::vector<GloballyHashedType>
   hashTypeCollection(TypeCollection &Types) {
     std::vector<GloballyHashedType> Hashes;
@@ -109,6 +130,11 @@ struct GloballyHashedType {
     return Hashes;
   }
 };
+static_assert(std::is_trivially_copyable<GloballyHashedType>::value,
+              "GloballyHashedType must be trivially copyable so that we can "
+              "reinterpret_cast arrays of hash data to arrays of "
+              "GloballyHashedType");
+
 } // namespace codeview
 
 template <> struct DenseMapInfo<codeview::LocallyHashedType> {

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h?rev=320719&r1=320718&r2=320719&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h Thu Dec 14 10:07:04 2017
@@ -19,6 +19,8 @@ namespace llvm {
 namespace codeview {
 
 class TypeIndex;
+struct GloballyHashedType;
+class GlobalTypeTableBuilder;
 class MergingTypeTableBuilder;
 
 /// \brief Merge one set of type records into another.  This method assumes
@@ -83,6 +85,22 @@ Error mergeTypeAndIdRecords(MergingTypeT
                             SmallVectorImpl<TypeIndex> &SourceToDest,
                             const CVTypeArray &IdsAndTypes);
 
+Error mergeTypeAndIdRecords(GlobalTypeTableBuilder &DestIds,
+                            GlobalTypeTableBuilder &DestTypes,
+                            SmallVectorImpl<TypeIndex> &SourceToDest,
+                            const CVTypeArray &IdsAndTypes,
+                            ArrayRef<GloballyHashedType> Hashes);
+
+Error mergeTypeRecords(GlobalTypeTableBuilder &Dest,
+                       SmallVectorImpl<TypeIndex> &SourceToDest,
+                       const CVTypeArray &Types,
+                       ArrayRef<GloballyHashedType> Hashes);
+
+Error mergeIdRecords(GlobalTypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,
+                     SmallVectorImpl<TypeIndex> &SourceToDest,
+                     const CVTypeArray &Ids,
+                     ArrayRef<GloballyHashedType> Hashes);
+
 } // end namespace codeview
 } // end namespace llvm
 

Modified: llvm/trunk/include/llvm/Object/COFF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/COFF.h?rev=320719&r1=320718&r2=320719&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/COFF.h (original)
+++ llvm/trunk/include/llvm/Object/COFF.h Thu Dec 14 10:07:04 2017
@@ -743,6 +743,12 @@ struct coff_resource_dir_table {
   support::ulittle16_t NumberOfIDEntries;
 };
 
+struct debug_h_header {
+  support::ulittle32_t Magic;
+  support::ulittle16_t Version;
+  support::ulittle16_t HashAlgorithm;
+};
+
 class COFFObjectFile : public ObjectFile {
 private:
   friend class ImportDirectoryEntryRef;

Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeHashing.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeHashing.cpp?rev=320719&r1=320718&r2=320719&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeHashing.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeHashing.cpp Thu Dec 14 10:07:04 2017
@@ -54,7 +54,7 @@ GloballyHashedType::hashType(ArrayRef<ui
         reinterpret_cast<const TypeIndex *>(RefData.data()), Ref.Count);
     for (TypeIndex TI : Indices) {
       ArrayRef<uint8_t> BytesToHash;
-      if (TI.isSimple() || TI.isNoneType()) {
+      if (TI.isSimple() || TI.isNoneType() || TI.toArrayIndex() >= Prev.size()) {
         const uint8_t *IndexBytes = reinterpret_cast<const uint8_t *>(&TI);
         BytesToHash = makeArrayRef(IndexBytes, sizeof(TypeIndex));
       } else {

Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp?rev=320719&r1=320718&r2=320719&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp Thu Dec 14 10:07:04 2017
@@ -10,6 +10,7 @@
 #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
 #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
@@ -62,6 +63,7 @@ public:
 
   static const TypeIndex Untranslated;
 
+  // Local hashing entry points
   Error mergeTypesAndIds(MergingTypeTableBuilder &DestIds,
                          MergingTypeTableBuilder &DestTypes,
                          const CVTypeArray &IdsAndTypes);
@@ -71,6 +73,18 @@ public:
   Error mergeTypeRecords(MergingTypeTableBuilder &Dest,
                          const CVTypeArray &Types);
 
+  // Global hashing entry points
+  Error mergeTypesAndIds(GlobalTypeTableBuilder &DestIds,
+                         GlobalTypeTableBuilder &DestTypes,
+                         const CVTypeArray &IdsAndTypes,
+                         ArrayRef<GloballyHashedType> Hashes);
+  Error mergeIdRecords(GlobalTypeTableBuilder &Dest,
+                       ArrayRef<TypeIndex> TypeSourceToDest,
+                       const CVTypeArray &Ids,
+                       ArrayRef<GloballyHashedType> Hashes);
+  Error mergeTypeRecords(GlobalTypeTableBuilder &Dest, const CVTypeArray &Types,
+                         ArrayRef<GloballyHashedType> Hashes);
+
 private:
   Error doit(const CVTypeArray &Types);
 
@@ -83,6 +97,14 @@ private:
   bool remapTypeIndex(TypeIndex &Idx);
   bool remapItemIndex(TypeIndex &Idx);
 
+  bool hasTypeStream() const {
+    return (UseGlobalHashes) ? (!!DestGlobalTypeStream) : (!!DestTypeStream);
+  }
+
+  bool hasIdStream() const {
+    return (UseGlobalHashes) ? (!!DestGlobalIdStream) : (!!DestIdStream);
+  }
+
   ArrayRef<uint8_t> serializeRemapped(const RemappedType &Record);
 
   bool remapIndices(RemappedType &Record, ArrayRef<TiReference> Refs);
@@ -100,6 +122,8 @@ private:
 
   Optional<Error> LastError;
 
+  bool UseGlobalHashes = false;
+
   bool IsSecondPass = false;
 
   unsigned NumBadIndices = 0;
@@ -109,6 +133,11 @@ private:
   MergingTypeTableBuilder *DestIdStream = nullptr;
   MergingTypeTableBuilder *DestTypeStream = nullptr;
 
+  GlobalTypeTableBuilder *DestGlobalIdStream = nullptr;
+  GlobalTypeTableBuilder *DestGlobalTypeStream = nullptr;
+
+  ArrayRef<GloballyHashedType> GlobalHashes;
+
   // If we're only mapping id records, this array contains the mapping for
   // type records.
   ArrayRef<TypeIndex> TypeLookup;
@@ -209,7 +238,7 @@ bool TypeStreamMerger::remapTypeIndex(Ty
   // 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 (DestTypeStream == nullptr)
+  if (!hasTypeStream())
     return remapIndex(Idx, TypeLookup);
 
   assert(TypeLookup.empty());
@@ -217,13 +246,15 @@ bool TypeStreamMerger::remapTypeIndex(Ty
 }
 
 bool TypeStreamMerger::remapItemIndex(TypeIndex &Idx) {
-  assert(DestIdStream);
+  assert(hasIdStream());
   return remapIndex(Idx, IndexMap);
 }
 
+// Local hashing entry points
 Error TypeStreamMerger::mergeTypeRecords(MergingTypeTableBuilder &Dest,
                                          const CVTypeArray &Types) {
   DestTypeStream = &Dest;
+  UseGlobalHashes = false;
 
   return doit(Types);
 }
@@ -233,6 +264,7 @@ Error TypeStreamMerger::mergeIdRecords(M
                                        const CVTypeArray &Ids) {
   DestIdStream = &Dest;
   TypeLookup = TypeSourceToDest;
+  UseGlobalHashes = false;
 
   return doit(Ids);
 }
@@ -242,6 +274,41 @@ Error TypeStreamMerger::mergeTypesAndIds
                                          const CVTypeArray &IdsAndTypes) {
   DestIdStream = &DestIds;
   DestTypeStream = &DestTypes;
+  UseGlobalHashes = false;
+  return doit(IdsAndTypes);
+}
+
+// Global hashing entry points
+Error TypeStreamMerger::mergeTypeRecords(GlobalTypeTableBuilder &Dest,
+                                         const CVTypeArray &Types,
+                                         ArrayRef<GloballyHashedType> Hashes) {
+  DestGlobalTypeStream = &Dest;
+  UseGlobalHashes = true;
+  GlobalHashes = Hashes;
+
+  return doit(Types);
+}
+
+Error TypeStreamMerger::mergeIdRecords(GlobalTypeTableBuilder &Dest,
+                                       ArrayRef<TypeIndex> TypeSourceToDest,
+                                       const CVTypeArray &Ids,
+                                       ArrayRef<GloballyHashedType> Hashes) {
+  DestGlobalIdStream = &Dest;
+  TypeLookup = TypeSourceToDest;
+  UseGlobalHashes = true;
+  GlobalHashes = Hashes;
+
+  return doit(Ids);
+}
+
+Error TypeStreamMerger::mergeTypesAndIds(GlobalTypeTableBuilder &DestIds,
+                                         GlobalTypeTableBuilder &DestTypes,
+                                         const CVTypeArray &IdsAndTypes,
+                                         ArrayRef<GloballyHashedType> Hashes) {
+  DestGlobalIdStream = &DestIds;
+  DestGlobalTypeStream = &DestTypes;
+  UseGlobalHashes = true;
+  GlobalHashes = Hashes;
   return doit(IdsAndTypes);
 }
 
@@ -286,18 +353,29 @@ Error TypeStreamMerger::remapAllTypes(co
 }
 
 Error TypeStreamMerger::remapType(const CVType &Type) {
-  MergingTypeTableBuilder &Dest =
-      isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream;
-
-  RemappedType R(Type);
-  SmallVector<TiReference, 32> Refs;
-  discoverTypeIndices(Type.RecordData, Refs);
-  bool MappedAllIndices = remapIndices(R, Refs);
-  ArrayRef<uint8_t> Data = serializeRemapped(R);
+  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);
+  };
 
   TypeIndex DestIdx = Untranslated;
-  if (MappedAllIndices)
-    DestIdx = Dest.insertRecordBytes(Data);
+  if (UseGlobalHashes) {
+    GlobalTypeTableBuilder &Dest =
+        isIdRecord(Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream;
+    GloballyHashedType H = GlobalHashes[CurIndex.toArrayIndex()];
+    DestIdx = Dest.insertRecordAs(H, DoSerialize);
+  } else {
+    MergingTypeTableBuilder &Dest =
+        isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream;
+
+    auto Data = DoSerialize();
+    if (!Data.empty())
+      DestIdx = Dest.insertRecordBytes(Data);
+  }
   addMapping(DestIdx);
 
   ++CurIndex;
@@ -350,3 +428,28 @@ Error llvm::codeview::mergeTypeAndIdReco
   TypeStreamMerger M(SourceToDest);
   return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes);
 }
+
+Error llvm::codeview::mergeTypeAndIdRecords(
+    GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes,
+    SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes,
+    ArrayRef<GloballyHashedType> Hashes) {
+  TypeStreamMerger M(SourceToDest);
+  return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes);
+}
+
+Error llvm::codeview::mergeTypeRecords(GlobalTypeTableBuilder &Dest,
+                                       SmallVectorImpl<TypeIndex> &SourceToDest,
+                                       const CVTypeArray &Types,
+                                       ArrayRef<GloballyHashedType> Hashes) {
+  TypeStreamMerger M(SourceToDest);
+  return M.mergeTypeRecords(Dest, Types, Hashes);
+}
+
+Error llvm::codeview::mergeIdRecords(GlobalTypeTableBuilder &Dest,
+                                     ArrayRef<TypeIndex> Types,
+                                     SmallVectorImpl<TypeIndex> &SourceToDest,
+                                     const CVTypeArray &Ids,
+                                     ArrayRef<GloballyHashedType> Hashes) {
+  TypeStreamMerger M(SourceToDest);
+  return M.mergeIdRecords(Dest, Types, Ids, Hashes);
+}




More information about the llvm-commits mailing list