1 //===- TypeHashing.cpp -------------------------------------------*- C++-*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/CodeView/TypeHashing.h"
12 #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
13 #include "llvm/Support/SHA1.h"
16 using namespace llvm::codeview
;
18 LocallyHashedType DenseMapInfo
<LocallyHashedType
>::Empty
{0, {}};
19 LocallyHashedType DenseMapInfo
<LocallyHashedType
>::Tombstone
{hash_code(-1), {}};
21 static std::array
<uint8_t, 8> EmptyHash
= {
22 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
23 static std::array
<uint8_t, 8> TombstoneHash
= {
24 {0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
26 GloballyHashedType DenseMapInfo
<GloballyHashedType
>::Empty
{EmptyHash
};
27 GloballyHashedType DenseMapInfo
<GloballyHashedType
>::Tombstone
{TombstoneHash
};
29 LocallyHashedType
LocallyHashedType::hashType(ArrayRef
<uint8_t> RecordData
) {
30 return {llvm::hash_value(RecordData
), RecordData
};
34 GloballyHashedType::hashType(ArrayRef
<uint8_t> RecordData
,
35 ArrayRef
<GloballyHashedType
> PreviousTypes
,
36 ArrayRef
<GloballyHashedType
> PreviousIds
) {
37 SmallVector
<TiReference
, 4> Refs
;
38 discoverTypeIndices(RecordData
, Refs
);
42 S
.update(RecordData
.take_front(sizeof(RecordPrefix
)));
43 RecordData
= RecordData
.drop_front(sizeof(RecordPrefix
));
44 for (const auto &Ref
: Refs
) {
45 // Hash any data that comes before this TiRef.
46 uint32_t PreLen
= Ref
.Offset
- Off
;
47 ArrayRef
<uint8_t> PreData
= RecordData
.slice(Off
, PreLen
);
49 auto Prev
= (Ref
.Kind
== TiRefKind::IndexRef
) ? PreviousIds
: PreviousTypes
;
51 auto RefData
= RecordData
.slice(Ref
.Offset
, Ref
.Count
* sizeof(TypeIndex
));
52 // For each type index referenced, add in the previously computed hash
53 // value of that type.
54 ArrayRef
<TypeIndex
> Indices(
55 reinterpret_cast<const TypeIndex
*>(RefData
.data()), Ref
.Count
);
56 for (TypeIndex TI
: Indices
) {
57 ArrayRef
<uint8_t> BytesToHash
;
58 if (TI
.isSimple() || TI
.isNoneType() || TI
.toArrayIndex() >= Prev
.size()) {
59 const uint8_t *IndexBytes
= reinterpret_cast<const uint8_t *>(&TI
);
60 BytesToHash
= makeArrayRef(IndexBytes
, sizeof(TypeIndex
));
62 BytesToHash
= Prev
[TI
.toArrayIndex()].Hash
;
64 S
.update(BytesToHash
);
67 Off
= Ref
.Offset
+ Ref
.Count
* sizeof(TypeIndex
);
70 // Don't forget to add in any trailing bytes.
71 auto TrailingBytes
= RecordData
.drop_front(Off
);
72 S
.update(TrailingBytes
);
74 return {S
.final().take_back(8)};