<div dir="ltr">is_trivially_copyable is only available in libstdc++ starting from gcc 5. So this coded doesn't build on gcc 4.8.5</div><div class="gmail_extra"><br clear="all"><div><div class="gmail_signature" data-smartmail="gmail_signature">~Craig</div></div>
<br><div class="gmail_quote">On Thu, Dec 14, 2017 at 10:07 AM, Zachary Turner via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">Author: zturner<br>
Date: Thu Dec 14 10:07:04 2017<br>
New Revision: 320719<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=320719&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=320719&view=rev</a><br>
Log:<br>
[COFF] Teach LLD to use the COFF .debug$H section.<br>
<br>
This adds the /DEBUG:GHASH option to LLD which will look for<br>
the existence of .debug$H sections in linker inputs and use them<br>
to accelerate type merging.  The clang-cl side has already been<br>
added, so this completes the work necessary to begin experimenting<br>
with this feature.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D40980" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D40980</a><br>
<br>
</span>Modified:<br>
    llvm/trunk/include/llvm/<wbr>DebugInfo/CodeView/<wbr>TypeHashing.h<br>
    llvm/trunk/include/llvm/<wbr>DebugInfo/CodeView/<wbr>TypeStreamMerger.h<br>
    llvm/trunk/include/llvm/<wbr>Object/COFF.h<br>
    llvm/trunk/lib/DebugInfo/<wbr>CodeView/TypeHashing.cpp<br>
    llvm/trunk/lib/DebugInfo/<wbr>CodeView/TypeStreamMerger.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/<wbr>DebugInfo/CodeView/<wbr>TypeHashing.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeHashing.h?rev=320719&r1=320718&r2=320719&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/include/<wbr>llvm/DebugInfo/CodeView/<wbr>TypeHashing.h?rev=320719&r1=<wbr>320718&r2=320719&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/<wbr>DebugInfo/CodeView/<wbr>TypeHashing.h (original)<br>
+++ llvm/trunk/include/llvm/<wbr>DebugInfo/CodeView/<wbr>TypeHashing.h Thu Dec 14 10:07:04 2017<br>
@@ -88,18 +88,39 @@ struct GloballyHashedType {<br>
                                      ArrayRef<GloballyHashedType> PreviousTypes,<br>
                                      ArrayRef<GloballyHashedType> PreviousIds);<br>
<br>
+  /// Given a sequence of bytes representing a record, compute a global hash for<br>
+  /// this record.  Due to the nature of global hashes incorporating the hashes<br>
+  /// of referenced records, this function requires a list of types and ids<br>
+  /// that RecordData might reference, indexable by TypeIndex.<br>
+  static GloballyHashedType hashType(CVType Type,<br>
+                                     ArrayRef<GloballyHashedType> PreviousTypes,<br>
+                                     ArrayRef<GloballyHashedType> PreviousIds) {<br>
+    return hashType(Type.RecordData, PreviousTypes, PreviousIds);<br>
+  }<br>
+<br>
   /// Given a sequence of combined type and ID records, compute global hashes<br>
   /// for each of them, returning the results in a vector of hashed types.<br>
   template <typename Range><br>
   static std::vector<<wbr>GloballyHashedType> hashTypes(Range &&Records) {<br>
     std::vector<<wbr>GloballyHashedType> Hashes;<br>
-    Hashes.reserve(std::distance(<wbr>std::begin(Records), std::end(Records)));<br>
     for (const auto &R : Records)<br>
       Hashes.push_back(hashType(R, Hashes, Hashes));<br>
<br>
     return Hashes;<br>
   }<br>
<br>
+  /// Given a sequence of combined type and ID records, compute global hashes<br>
+  /// for each of them, returning the results in a vector of hashed types.<br>
+  template <typename Range><br>
+  static std::vector<<wbr>GloballyHashedType><br>
+  hashIds(Range &&Records, ArrayRef<GloballyHashedType> TypeHashes) {<br>
+    std::vector<<wbr>GloballyHashedType> IdHashes;<br>
+    for (const auto &R : Records)<br>
+      IdHashes.push_back(hashType(R, TypeHashes, IdHashes));<br>
+<br>
+    return IdHashes;<br>
+  }<br>
+<br>
   static std::vector<<wbr>GloballyHashedType><br>
   hashTypeCollection(<wbr>TypeCollection &Types) {<br>
     std::vector<<wbr>GloballyHashedType> Hashes;<br>
@@ -109,6 +130,11 @@ struct GloballyHashedType {<br>
     return Hashes;<br>
   }<br>
 };<br>
+static_assert(std::is_<wbr>trivially_copyable<<wbr>GloballyHashedType>::value,<br>
+              "GloballyHashedType must be trivially copyable so that we can "<br>
+              "reinterpret_cast arrays of hash data to arrays of "<br>
+              "GloballyHashedType");<br>
+<br>
 } // namespace codeview<br>
<br>
 template <> struct DenseMapInfo<codeview::<wbr>LocallyHashedType> {<br>
<br>
Modified: llvm/trunk/include/llvm/<wbr>DebugInfo/CodeView/<wbr>TypeStreamMerger.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h?rev=320719&r1=320718&r2=320719&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/include/<wbr>llvm/DebugInfo/CodeView/<wbr>TypeStreamMerger.h?rev=320719&<wbr>r1=320718&r2=320719&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/<wbr>DebugInfo/CodeView/<wbr>TypeStreamMerger.h (original)<br>
+++ llvm/trunk/include/llvm/<wbr>DebugInfo/CodeView/<wbr>TypeStreamMerger.h Thu Dec 14 10:07:04 2017<br>
@@ -19,6 +19,8 @@ namespace llvm {<br>
 namespace codeview {<br>
<br>
 class TypeIndex;<br>
+struct GloballyHashedType;<br>
+class GlobalTypeTableBuilder;<br>
 class MergingTypeTableBuilder;<br>
<br>
 /// \brief Merge one set of type records into another.  This method assumes<br>
@@ -83,6 +85,22 @@ Error mergeTypeAndIdRecords(<wbr>MergingTypeT<br>
                             SmallVectorImpl<TypeIndex> &SourceToDest,<br>
                             const CVTypeArray &IdsAndTypes);<br>
<br>
+Error mergeTypeAndIdRecords(<wbr>GlobalTypeTableBuilder &DestIds,<br>
+                            GlobalTypeTableBuilder &DestTypes,<br>
+                            SmallVectorImpl<TypeIndex> &SourceToDest,<br>
+                            const CVTypeArray &IdsAndTypes,<br>
+                            ArrayRef<GloballyHashedType> Hashes);<br>
+<br>
+Error mergeTypeRecords(<wbr>GlobalTypeTableBuilder &Dest,<br>
+                       SmallVectorImpl<TypeIndex> &SourceToDest,<br>
+                       const CVTypeArray &Types,<br>
+                       ArrayRef<GloballyHashedType> Hashes);<br>
+<br>
+Error mergeIdRecords(<wbr>GlobalTypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,<br>
+                     SmallVectorImpl<TypeIndex> &SourceToDest,<br>
+                     const CVTypeArray &Ids,<br>
+                     ArrayRef<GloballyHashedType> Hashes);<br>
+<br>
 } // end namespace codeview<br>
 } // end namespace llvm<br>
<br>
<br>
Modified: llvm/trunk/include/llvm/<wbr>Object/COFF.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/COFF.h?rev=320719&r1=320718&r2=320719&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/include/<wbr>llvm/Object/COFF.h?rev=320719&<wbr>r1=320718&r2=320719&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/<wbr>Object/COFF.h (original)<br>
+++ llvm/trunk/include/llvm/<wbr>Object/COFF.h Thu Dec 14 10:07:04 2017<br>
@@ -743,6 +743,12 @@ struct coff_resource_dir_table {<br>
   support::ulittle16_t NumberOfIDEntries;<br>
 };<br>
<br>
+struct debug_h_header {<br>
+  support::ulittle32_t Magic;<br>
+  support::ulittle16_t Version;<br>
+  support::ulittle16_t HashAlgorithm;<br>
+};<br>
+<br>
 class COFFObjectFile : public ObjectFile {<br>
 private:<br>
   friend class ImportDirectoryEntryRef;<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/<wbr>CodeView/TypeHashing.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeHashing.cpp?rev=320719&r1=320718&r2=320719&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>DebugInfo/CodeView/<wbr>TypeHashing.cpp?rev=320719&r1=<wbr>320718&r2=320719&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/DebugInfo/<wbr>CodeView/TypeHashing.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/<wbr>CodeView/TypeHashing.cpp Thu Dec 14 10:07:04 2017<br>
@@ -54,7 +54,7 @@ GloballyHashedType::hashType(<wbr>ArrayRef<ui<br>
         reinterpret_cast<const TypeIndex *>(RefData.data()), Ref.Count);<br>
     for (TypeIndex TI : Indices) {<br>
       ArrayRef<uint8_t> BytesToHash;<br>
-      if (TI.isSimple() || TI.isNoneType()) {<br>
+      if (TI.isSimple() || TI.isNoneType() || TI.toArrayIndex() >= Prev.size()) {<br>
         const uint8_t *IndexBytes = reinterpret_cast<const uint8_t *>(&TI);<br>
         BytesToHash = makeArrayRef(IndexBytes, sizeof(TypeIndex));<br>
       } else {<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/<wbr>CodeView/TypeStreamMerger.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp?rev=320719&r1=320718&r2=320719&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>DebugInfo/CodeView/<wbr>TypeStreamMerger.cpp?rev=<wbr>320719&r1=320718&r2=320719&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/DebugInfo/<wbr>CodeView/TypeStreamMerger.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/<wbr>CodeView/TypeStreamMerger.cpp Thu Dec 14 10:07:04 2017<br>
@@ -10,6 +10,7 @@<br>
 #include "llvm/DebugInfo/CodeView/<wbr>TypeStreamMerger.h"<br>
 #include "llvm/ADT/SmallString.h"<br>
 #include "llvm/ADT/StringExtras.h"<br>
+#include "llvm/DebugInfo/CodeView/<wbr>GlobalTypeTableBuilder.h"<br>
 #include "llvm/DebugInfo/CodeView/<wbr>MergingTypeTableBuilder.h"<br>
 #include "llvm/DebugInfo/CodeView/<wbr>TypeIndex.h"<br>
 #include "llvm/DebugInfo/CodeView/<wbr>TypeIndexDiscovery.h"<br>
@@ -62,6 +63,7 @@ public:<br>
<br>
   static const TypeIndex Untranslated;<br>
<br>
+  // Local hashing entry points<br>
   Error mergeTypesAndIds(<wbr>MergingTypeTableBuilder &DestIds,<br>
                          MergingTypeTableBuilder &DestTypes,<br>
                          const CVTypeArray &IdsAndTypes);<br>
@@ -71,6 +73,18 @@ public:<br>
   Error mergeTypeRecords(<wbr>MergingTypeTableBuilder &Dest,<br>
                          const CVTypeArray &Types);<br>
<br>
+  // Global hashing entry points<br>
+  Error mergeTypesAndIds(<wbr>GlobalTypeTableBuilder &DestIds,<br>
+                         GlobalTypeTableBuilder &DestTypes,<br>
+                         const CVTypeArray &IdsAndTypes,<br>
+                         ArrayRef<GloballyHashedType> Hashes);<br>
+  Error mergeIdRecords(<wbr>GlobalTypeTableBuilder &Dest,<br>
+                       ArrayRef<TypeIndex> TypeSourceToDest,<br>
+                       const CVTypeArray &Ids,<br>
+                       ArrayRef<GloballyHashedType> Hashes);<br>
+  Error mergeTypeRecords(<wbr>GlobalTypeTableBuilder &Dest, const CVTypeArray &Types,<br>
+                         ArrayRef<GloballyHashedType> Hashes);<br>
+<br>
 private:<br>
   Error doit(const CVTypeArray &Types);<br>
<br>
@@ -83,6 +97,14 @@ private:<br>
   bool remapTypeIndex(TypeIndex &Idx);<br>
   bool remapItemIndex(TypeIndex &Idx);<br>
<br>
+  bool hasTypeStream() const {<br>
+    return (UseGlobalHashes) ? (!!DestGlobalTypeStream) : (!!DestTypeStream);<br>
+  }<br>
+<br>
+  bool hasIdStream() const {<br>
+    return (UseGlobalHashes) ? (!!DestGlobalIdStream) : (!!DestIdStream);<br>
+  }<br>
+<br>
   ArrayRef<uint8_t> serializeRemapped(const RemappedType &Record);<br>
<br>
   bool remapIndices(RemappedType &Record, ArrayRef<TiReference> Refs);<br>
@@ -100,6 +122,8 @@ private:<br>
<br>
   Optional<Error> LastError;<br>
<br>
+  bool UseGlobalHashes = false;<br>
+<br>
   bool IsSecondPass = false;<br>
<br>
   unsigned NumBadIndices = 0;<br>
@@ -109,6 +133,11 @@ private:<br>
   MergingTypeTableBuilder *DestIdStream = nullptr;<br>
   MergingTypeTableBuilder *DestTypeStream = nullptr;<br>
<br>
+  GlobalTypeTableBuilder *DestGlobalIdStream = nullptr;<br>
+  GlobalTypeTableBuilder *DestGlobalTypeStream = nullptr;<br>
+<br>
+  ArrayRef<GloballyHashedType> GlobalHashes;<br>
+<br>
   // If we're only mapping id records, this array contains the mapping for<br>
   // type records.<br>
   ArrayRef<TypeIndex> TypeLookup;<br>
@@ -209,7 +238,7 @@ bool TypeStreamMerger::<wbr>remapTypeIndex(Ty<br>
   // special mapping from OldTypeStream -> NewTypeStream which was computed<br>
   // externally.  Regardless, we use this special map if and only if we are<br>
   // doing an id-only mapping.<br>
-  if (DestTypeStream == nullptr)<br>
+  if (!hasTypeStream())<br>
     return remapIndex(Idx, TypeLookup);<br>
<br>
   assert(TypeLookup.empty());<br>
@@ -217,13 +246,15 @@ bool TypeStreamMerger::<wbr>remapTypeIndex(Ty<br>
 }<br>
<br>
 bool TypeStreamMerger::<wbr>remapItemIndex(TypeIndex &Idx) {<br>
-  assert(DestIdStream);<br>
+  assert(hasIdStream());<br>
   return remapIndex(Idx, IndexMap);<br>
 }<br>
<br>
+// Local hashing entry points<br>
 Error TypeStreamMerger::<wbr>mergeTypeRecords(<wbr>MergingTypeTableBuilder &Dest,<br>
                                          const CVTypeArray &Types) {<br>
   DestTypeStream = &Dest;<br>
+  UseGlobalHashes = false;<br>
<br>
   return doit(Types);<br>
 }<br>
@@ -233,6 +264,7 @@ Error TypeStreamMerger::<wbr>mergeIdRecords(M<br>
                                        const CVTypeArray &Ids) {<br>
   DestIdStream = &Dest;<br>
   TypeLookup = TypeSourceToDest;<br>
+  UseGlobalHashes = false;<br>
<br>
   return doit(Ids);<br>
 }<br>
@@ -242,6 +274,41 @@ Error TypeStreamMerger::<wbr>mergeTypesAndIds<br>
                                          const CVTypeArray &IdsAndTypes) {<br>
   DestIdStream = &DestIds;<br>
   DestTypeStream = &DestTypes;<br>
+  UseGlobalHashes = false;<br>
+  return doit(IdsAndTypes);<br>
+}<br>
+<br>
+// Global hashing entry points<br>
+Error TypeStreamMerger::<wbr>mergeTypeRecords(<wbr>GlobalTypeTableBuilder &Dest,<br>
+                                         const CVTypeArray &Types,<br>
+                                         ArrayRef<GloballyHashedType> Hashes) {<br>
+  DestGlobalTypeStream = &Dest;<br>
+  UseGlobalHashes = true;<br>
+  GlobalHashes = Hashes;<br>
+<br>
+  return doit(Types);<br>
+}<br>
+<br>
+Error TypeStreamMerger::<wbr>mergeIdRecords(<wbr>GlobalTypeTableBuilder &Dest,<br>
+                                       ArrayRef<TypeIndex> TypeSourceToDest,<br>
+                                       const CVTypeArray &Ids,<br>
+                                       ArrayRef<GloballyHashedType> Hashes) {<br>
+  DestGlobalIdStream = &Dest;<br>
+  TypeLookup = TypeSourceToDest;<br>
+  UseGlobalHashes = true;<br>
+  GlobalHashes = Hashes;<br>
+<br>
+  return doit(Ids);<br>
+}<br>
+<br>
+Error TypeStreamMerger::<wbr>mergeTypesAndIds(<wbr>GlobalTypeTableBuilder &DestIds,<br>
+                                         GlobalTypeTableBuilder &DestTypes,<br>
+                                         const CVTypeArray &IdsAndTypes,<br>
+                                         ArrayRef<GloballyHashedType> Hashes) {<br>
+  DestGlobalIdStream = &DestIds;<br>
+  DestGlobalTypeStream = &DestTypes;<br>
+  UseGlobalHashes = true;<br>
+  GlobalHashes = Hashes;<br>
   return doit(IdsAndTypes);<br>
 }<br>
<br>
@@ -286,18 +353,29 @@ Error TypeStreamMerger::<wbr>remapAllTypes(co<br>
 }<br>
<br>
 Error TypeStreamMerger::remapType(<wbr>const CVType &Type) {<br>
-  MergingTypeTableBuilder &Dest =<br>
-      isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream;<br>
-<br>
-  RemappedType R(Type);<br>
-  SmallVector<TiReference, 32> Refs;<br>
-  discoverTypeIndices(Type.<wbr>RecordData, Refs);<br>
-  bool MappedAllIndices = remapIndices(R, Refs);<br>
-  ArrayRef<uint8_t> Data = serializeRemapped(R);<br>
+  auto DoSerialize = [this, Type]() -> ArrayRef<uint8_t> {<br>
+    RemappedType R(Type);<br>
+    SmallVector<TiReference, 32> Refs;<br>
+    discoverTypeIndices(Type.<wbr>RecordData, Refs);<br>
+    if (!remapIndices(R, Refs))<br>
+      return {};<br>
+    return serializeRemapped(R);<br>
+  };<br>
<br>
   TypeIndex DestIdx = Untranslated;<br>
-  if (MappedAllIndices)<br>
-    DestIdx = Dest.insertRecordBytes(Data);<br>
+  if (UseGlobalHashes) {<br>
+    GlobalTypeTableBuilder &Dest =<br>
+        isIdRecord(Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream;<br>
+    GloballyHashedType H = GlobalHashes[CurIndex.<wbr>toArrayIndex()];<br>
+    DestIdx = Dest.insertRecordAs(H, DoSerialize);<br>
+  } else {<br>
+    MergingTypeTableBuilder &Dest =<br>
+        isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream;<br>
+<br>
+    auto Data = DoSerialize();<br>
+    if (!Data.empty())<br>
+      DestIdx = Dest.insertRecordBytes(Data);<br>
+  }<br>
   addMapping(DestIdx);<br>
<br>
   ++CurIndex;<br>
@@ -350,3 +428,28 @@ Error llvm::codeview::<wbr>mergeTypeAndIdReco<br>
   TypeStreamMerger M(SourceToDest);<br>
   return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes);<br>
 }<br>
+<br>
+Error llvm::codeview::<wbr>mergeTypeAndIdRecords(<br>
+    GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes,<br>
+    SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes,<br>
+    ArrayRef<GloballyHashedType> Hashes) {<br>
+  TypeStreamMerger M(SourceToDest);<br>
+  return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes);<br>
+}<br>
+<br>
+Error llvm::codeview::<wbr>mergeTypeRecords(<wbr>GlobalTypeTableBuilder &Dest,<br>
+                                       SmallVectorImpl<TypeIndex> &SourceToDest,<br>
+                                       const CVTypeArray &Types,<br>
+                                       ArrayRef<GloballyHashedType> Hashes) {<br>
+  TypeStreamMerger M(SourceToDest);<br>
+  return M.mergeTypeRecords(Dest, Types, Hashes);<br>
+}<br>
+<br>
+Error llvm::codeview::<wbr>mergeIdRecords(<wbr>GlobalTypeTableBuilder &Dest,<br>
+                                     ArrayRef<TypeIndex> Types,<br>
+                                     SmallVectorImpl<TypeIndex> &SourceToDest,<br>
+                                     const CVTypeArray &Ids,<br>
+                                     ArrayRef<GloballyHashedType> Hashes) {<br>
+  TypeStreamMerger M(SourceToDest);<br>
+  return M.mergeIdRecords(Dest, Types, Ids, Hashes);<br>
+}<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</div></div></blockquote></div><br></div>