• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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