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
hashType(ArrayRef<uint8_t> RecordData)29 LocallyHashedType LocallyHashedType::hashType(ArrayRef<uint8_t> RecordData) {
30 return {llvm::hash_value(RecordData), RecordData};
31 }
32
33 GloballyHashedType
hashType(ArrayRef<uint8_t> RecordData,ArrayRef<GloballyHashedType> PreviousTypes,ArrayRef<GloballyHashedType> PreviousIds)34 GloballyHashedType::hashType(ArrayRef<uint8_t> RecordData,
35 ArrayRef<GloballyHashedType> PreviousTypes,
36 ArrayRef<GloballyHashedType> PreviousIds) {
37 SmallVector<TiReference, 4> Refs;
38 discoverTypeIndices(RecordData, Refs);
39 SHA1 S;
40 S.init();
41 uint32_t Off = 0;
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);
48 S.update(PreData);
49 auto Prev = (Ref.Kind == TiRefKind::IndexRef) ? PreviousIds : PreviousTypes;
50
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));
61 } else {
62 BytesToHash = Prev[TI.toArrayIndex()].Hash;
63 }
64 S.update(BytesToHash);
65 }
66
67 Off = Ref.Offset + Ref.Count * sizeof(TypeIndex);
68 }
69
70 // Don't forget to add in any trailing bytes.
71 auto TrailingBytes = RecordData.drop_front(Off);
72 S.update(TrailingBytes);
73
74 return {S.final().take_back(8)};
75 }
76