<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>