1 //===- TypeHashing.cpp -------------------------------------------*- C++-*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/CodeView/TypeHashing.h"
11 #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
12 #include "llvm/Support/BLAKE3.h"
15 using namespace llvm::codeview
;
17 LocallyHashedType DenseMapInfo
<LocallyHashedType
>::Empty
{0, {}};
18 LocallyHashedType DenseMapInfo
<LocallyHashedType
>::Tombstone
{hash_code(-1), {}};
20 static std::array
<uint8_t, 8> EmptyHash
= {
21 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
22 static std::array
<uint8_t, 8> TombstoneHash
= {
23 {0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
25 GloballyHashedType DenseMapInfo
<GloballyHashedType
>::Empty
{EmptyHash
};
26 GloballyHashedType DenseMapInfo
<GloballyHashedType
>::Tombstone
{TombstoneHash
};
28 LocallyHashedType
LocallyHashedType::hashType(ArrayRef
<uint8_t> RecordData
) {
29 return {llvm::hash_value(RecordData
), RecordData
};
33 GloballyHashedType::hashType(ArrayRef
<uint8_t> RecordData
,
34 ArrayRef
<GloballyHashedType
> PreviousTypes
,
35 ArrayRef
<GloballyHashedType
> PreviousIds
) {
36 SmallVector
<TiReference
, 4> Refs
;
37 discoverTypeIndices(RecordData
, Refs
);
41 S
.update(RecordData
.take_front(sizeof(RecordPrefix
)));
42 RecordData
= RecordData
.drop_front(sizeof(RecordPrefix
));
43 for (const auto &Ref
: Refs
) {
44 // Hash any data that comes before this TiRef.
45 uint32_t PreLen
= Ref
.Offset
- Off
;
46 ArrayRef
<uint8_t> PreData
= RecordData
.slice(Off
, PreLen
);
48 auto Prev
= (Ref
.Kind
== TiRefKind::IndexRef
) ? PreviousIds
: PreviousTypes
;
50 auto RefData
= RecordData
.slice(Ref
.Offset
, Ref
.Count
* sizeof(TypeIndex
));
51 // For each type index referenced, add in the previously computed hash
52 // value of that type.
53 ArrayRef
<TypeIndex
> Indices(
54 reinterpret_cast<const TypeIndex
*>(RefData
.data()), Ref
.Count
);
55 for (TypeIndex TI
: Indices
) {
56 ArrayRef
<uint8_t> BytesToHash
;
57 if (TI
.isSimple() || TI
.isNoneType()) {
58 const uint8_t *IndexBytes
= reinterpret_cast<const uint8_t *>(&TI
);
59 BytesToHash
= ArrayRef(IndexBytes
, sizeof(TypeIndex
));
61 if (TI
.toArrayIndex() >= Prev
.size() ||
62 Prev
[TI
.toArrayIndex()].empty()) {
63 // There are references to yet-unhashed records. Suspend hashing for
64 // this record until all the other records are processed.
67 BytesToHash
= Prev
[TI
.toArrayIndex()].Hash
;
69 S
.update(BytesToHash
);
72 Off
= Ref
.Offset
+ Ref
.Count
* sizeof(TypeIndex
);
75 // Don't forget to add in any trailing bytes.
76 auto TrailingBytes
= RecordData
.drop_front(Off
);
77 S
.update(TrailingBytes
);