Line data Source code
1 : //===- TypeHashing.cpp -------------------------------------------*- C++-*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/DebugInfo/CodeView/TypeHashing.h"
11 :
12 : #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
13 : #include "llvm/Support/SHA1.h"
14 :
15 : using namespace llvm;
16 : using namespace llvm::codeview;
17 :
18 : LocallyHashedType DenseMapInfo<LocallyHashedType>::Empty{0, {}};
19 : LocallyHashedType DenseMapInfo<LocallyHashedType>::Tombstone{hash_code(-1), {}};
20 :
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}};
25 :
26 : GloballyHashedType DenseMapInfo<GloballyHashedType>::Empty{EmptyHash};
27 : GloballyHashedType DenseMapInfo<GloballyHashedType>::Tombstone{TombstoneHash};
28 :
29 11 : LocallyHashedType LocallyHashedType::hashType(ArrayRef<uint8_t> RecordData) {
30 11 : return {llvm::hash_value(RecordData), RecordData};
31 : }
32 :
33 : GloballyHashedType
34 1980 : GloballyHashedType::hashType(ArrayRef<uint8_t> RecordData,
35 : ArrayRef<GloballyHashedType> PreviousTypes,
36 : ArrayRef<GloballyHashedType> PreviousIds) {
37 : SmallVector<TiReference, 4> Refs;
38 1980 : discoverTypeIndices(RecordData, Refs);
39 : SHA1 S;
40 1980 : S.init();
41 : uint32_t Off = 0;
42 1980 : S.update(RecordData.take_front(sizeof(RecordPrefix)));
43 : RecordData = RecordData.drop_front(sizeof(RecordPrefix));
44 4483 : for (const auto &Ref : Refs) {
45 : // Hash any data that comes before this TiRef.
46 2503 : uint32_t PreLen = Ref.Offset - Off;
47 2503 : ArrayRef<uint8_t> PreData = RecordData.slice(Off, PreLen);
48 2503 : S.update(PreData);
49 2503 : auto Prev = (Ref.Kind == TiRefKind::IndexRef) ? PreviousIds : PreviousTypes;
50 :
51 2503 : 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 6237 : for (TypeIndex TI : Indices) {
57 3734 : ArrayRef<uint8_t> BytesToHash;
58 3734 : if (TI.isSimple() || TI.isNoneType() || TI.toArrayIndex() >= Prev.size()) {
59 : const uint8_t *IndexBytes = reinterpret_cast<const uint8_t *>(&TI);
60 1977 : BytesToHash = makeArrayRef(IndexBytes, sizeof(TypeIndex));
61 : } else {
62 1757 : BytesToHash = Prev[TI.toArrayIndex()].Hash;
63 : }
64 3734 : S.update(BytesToHash);
65 : }
66 :
67 2503 : Off = Ref.Offset + Ref.Count * sizeof(TypeIndex);
68 : }
69 :
70 : // Don't forget to add in any trailing bytes.
71 1980 : auto TrailingBytes = RecordData.drop_front(Off);
72 1980 : S.update(TrailingBytes);
73 :
74 3960 : return {S.final().take_back(8)};
75 : }
|