Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/DebugInfo/PDB/Native/TpiHashing.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- TpiHashing.cpp -----------------------------------------------------===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
10
11
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
12
#include "llvm/DebugInfo/PDB/Native/Hash.h"
13
#include "llvm/Support/JamCRC.h"
14
15
using namespace llvm;
16
using namespace llvm::codeview;
17
using namespace llvm::pdb;
18
19
// Corresponds to `fUDTAnon`.
20
2.14k
static bool isAnonymous(StringRef Name) {
21
2.14k
  return Name == "<unnamed-tag>" || Name == "__unnamed" ||
22
2.14k
         Name.endswith("::<unnamed-tag>") || Name.endswith("::__unnamed");
23
2.14k
}
24
25
// Computes the hash for a user-defined type record. This could be a struct,
26
// class, union, or enum.
27
static uint32_t getHashForUdt(const TagRecord &Rec,
28
2.14k
                              ArrayRef<uint8_t> FullRecord) {
29
2.14k
  ClassOptions Opts = Rec.getOptions();
30
2.14k
  bool ForwardRef = bool(Opts & ClassOptions::ForwardReference);
31
2.14k
  bool Scoped = bool(Opts & ClassOptions::Scoped);
32
2.14k
  bool HasUniqueName = bool(Opts & ClassOptions::HasUniqueName);
33
2.14k
  bool IsAnon = HasUniqueName && isAnonymous(Rec.getName());
34
2.14k
35
2.14k
  if (!ForwardRef && 
!Scoped1.11k
&&
!IsAnon1.11k
)
36
1.11k
    return hashStringV1(Rec.getName());
37
1.03k
  if (!ForwardRef && 
HasUniqueName6
&&
!IsAnon6
)
38
6
    return hashStringV1(Rec.getUniqueName());
39
1.03k
  return hashBufferV8(FullRecord);
40
1.03k
}
41
42
template <typename T>
43
1.37k
static Expected<uint32_t> getHashForUdt(const CVType &Rec) {
44
1.37k
  T Deserialized;
45
1.37k
  if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
46
0
                                               Deserialized))
47
0
    return std::move(E);
48
1.37k
  return getHashForUdt(Deserialized, Rec.data());
49
1.37k
}
TpiHashing.cpp:llvm::Expected<unsigned int> getHashForUdt<llvm::codeview::ClassRecord>(llvm::codeview::CVRecord<llvm::codeview::TypeLeafKind> const&)
Line
Count
Source
43
1.27k
static Expected<uint32_t> getHashForUdt(const CVType &Rec) {
44
1.27k
  T Deserialized;
45
1.27k
  if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
46
0
                                               Deserialized))
47
0
    return std::move(E);
48
1.27k
  return getHashForUdt(Deserialized, Rec.data());
49
1.27k
}
Unexecuted instantiation: TpiHashing.cpp:llvm::Expected<unsigned int> getHashForUdt<llvm::codeview::UnionRecord>(llvm::codeview::CVRecord<llvm::codeview::TypeLeafKind> const&)
TpiHashing.cpp:llvm::Expected<unsigned int> getHashForUdt<llvm::codeview::EnumRecord>(llvm::codeview::CVRecord<llvm::codeview::TypeLeafKind> const&)
Line
Count
Source
43
100
static Expected<uint32_t> getHashForUdt(const CVType &Rec) {
44
100
  T Deserialized;
45
100
  if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
46
0
                                               Deserialized))
47
0
    return std::move(E);
48
100
  return getHashForUdt(Deserialized, Rec.data());
49
100
}
50
51
template <typename T>
52
774
static Expected<TagRecordHash> getTagRecordHashForUdt(const CVType &Rec) {
53
774
  T Deserialized;
54
774
  if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
55
0
                                               Deserialized))
56
0
    return std::move(E);
57
774
58
774
  ClassOptions Opts = Deserialized.getOptions();
59
774
60
774
  bool ForwardRef = bool(Opts & ClassOptions::ForwardReference);
61
774
62
774
  uint32_t ThisRecordHash = getHashForUdt(Deserialized, Rec.data());
63
774
64
774
  // If we don't have a forward ref we can't compute the hash of it from the
65
774
  // full record because it requires hashing the entire buffer.
66
774
  if (!ForwardRef)
67
385
    return TagRecordHash{std::move(Deserialized), ThisRecordHash, 0};
68
389
69
389
  bool Scoped = bool(Opts & ClassOptions::Scoped);
70
389
71
389
  StringRef NameToHash =
72
389
      Scoped ? 
Deserialized.getUniqueName()6
:
Deserialized.getName()383
;
73
389
  uint32_t FullHash = hashStringV1(NameToHash);
74
389
  return TagRecordHash{std::move(Deserialized), FullHash, ThisRecordHash};
75
389
}
TpiHashing.cpp:llvm::Expected<llvm::pdb::TagRecordHash> getTagRecordHashForUdt<llvm::codeview::ClassRecord>(llvm::codeview::CVRecord<llvm::codeview::TypeLeafKind> const&)
Line
Count
Source
52
768
static Expected<TagRecordHash> getTagRecordHashForUdt(const CVType &Rec) {
53
768
  T Deserialized;
54
768
  if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
55
0
                                               Deserialized))
56
0
    return std::move(E);
57
768
58
768
  ClassOptions Opts = Deserialized.getOptions();
59
768
60
768
  bool ForwardRef = bool(Opts & ClassOptions::ForwardReference);
61
768
62
768
  uint32_t ThisRecordHash = getHashForUdt(Deserialized, Rec.data());
63
768
64
768
  // If we don't have a forward ref we can't compute the hash of it from the
65
768
  // full record because it requires hashing the entire buffer.
66
768
  if (!ForwardRef)
67
382
    return TagRecordHash{std::move(Deserialized), ThisRecordHash, 0};
68
386
69
386
  bool Scoped = bool(Opts & ClassOptions::Scoped);
70
386
71
386
  StringRef NameToHash =
72
386
      Scoped ? 
Deserialized.getUniqueName()6
:
Deserialized.getName()380
;
73
386
  uint32_t FullHash = hashStringV1(NameToHash);
74
386
  return TagRecordHash{std::move(Deserialized), FullHash, ThisRecordHash};
75
386
}
TpiHashing.cpp:llvm::Expected<llvm::pdb::TagRecordHash> getTagRecordHashForUdt<llvm::codeview::UnionRecord>(llvm::codeview::CVRecord<llvm::codeview::TypeLeafKind> const&)
Line
Count
Source
52
6
static Expected<TagRecordHash> getTagRecordHashForUdt(const CVType &Rec) {
53
6
  T Deserialized;
54
6
  if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
55
0
                                               Deserialized))
56
0
    return std::move(E);
57
6
58
6
  ClassOptions Opts = Deserialized.getOptions();
59
6
60
6
  bool ForwardRef = bool(Opts & ClassOptions::ForwardReference);
61
6
62
6
  uint32_t ThisRecordHash = getHashForUdt(Deserialized, Rec.data());
63
6
64
6
  // If we don't have a forward ref we can't compute the hash of it from the
65
6
  // full record because it requires hashing the entire buffer.
66
6
  if (!ForwardRef)
67
3
    return TagRecordHash{std::move(Deserialized), ThisRecordHash, 0};
68
3
69
3
  bool Scoped = bool(Opts & ClassOptions::Scoped);
70
3
71
3
  StringRef NameToHash =
72
3
      Scoped ? 
Deserialized.getUniqueName()0
: Deserialized.getName();
73
3
  uint32_t FullHash = hashStringV1(NameToHash);
74
3
  return TagRecordHash{std::move(Deserialized), FullHash, ThisRecordHash};
75
3
}
Unexecuted instantiation: TpiHashing.cpp:llvm::Expected<llvm::pdb::TagRecordHash> getTagRecordHashForUdt<llvm::codeview::EnumRecord>(llvm::codeview::CVRecord<llvm::codeview::TypeLeafKind> const&)
76
77
template <typename T>
78
710
static Expected<uint32_t> getSourceLineHash(const CVType &Rec) {
79
710
  T Deserialized;
80
710
  if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
81
0
                                               Deserialized))
82
0
    return std::move(E);
83
710
  char Buf[4];
84
710
  support::endian::write32le(Buf, Deserialized.getUDT().getIndex());
85
710
  return hashStringV1(StringRef(Buf, 4));
86
710
}
TpiHashing.cpp:llvm::Expected<unsigned int> getSourceLineHash<llvm::codeview::UdtSourceLineRecord>(llvm::codeview::CVRecord<llvm::codeview::TypeLeafKind> const&)
Line
Count
Source
78
689
static Expected<uint32_t> getSourceLineHash(const CVType &Rec) {
79
689
  T Deserialized;
80
689
  if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
81
0
                                               Deserialized))
82
0
    return std::move(E);
83
689
  char Buf[4];
84
689
  support::endian::write32le(Buf, Deserialized.getUDT().getIndex());
85
689
  return hashStringV1(StringRef(Buf, 4));
86
689
}
TpiHashing.cpp:llvm::Expected<unsigned int> getSourceLineHash<llvm::codeview::UdtModSourceLineRecord>(llvm::codeview::CVRecord<llvm::codeview::TypeLeafKind> const&)
Line
Count
Source
78
21
static Expected<uint32_t> getSourceLineHash(const CVType &Rec) {
79
21
  T Deserialized;
80
21
  if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
81
0
                                               Deserialized))
82
0
    return std::move(E);
83
21
  char Buf[4];
84
21
  support::endian::write32le(Buf, Deserialized.getUDT().getIndex());
85
21
  return hashStringV1(StringRef(Buf, 4));
86
21
}
87
88
774
Expected<TagRecordHash> llvm::pdb::hashTagRecord(const codeview::CVType &Type) {
89
774
  switch (Type.kind()) {
90
774
  case LF_CLASS:
91
768
  case LF_STRUCTURE:
92
768
  case LF_INTERFACE:
93
768
    return getTagRecordHashForUdt<ClassRecord>(Type);
94
768
  case LF_UNION:
95
6
    return getTagRecordHashForUdt<UnionRecord>(Type);
96
768
  case LF_ENUM:
97
0
    return getTagRecordHashForUdt<EnumRecord>(Type);
98
768
  default:
99
0
    assert(false && "Type is not a tag record!");
100
774
  }
101
774
  return make_error<StringError>("Invalid record type",
102
0
                                 inconvertibleErrorCode());
103
774
}
104
105
5.56k
Expected<uint32_t> llvm::pdb::hashTypeRecord(const CVType &Rec) {
106
5.56k
  switch (Rec.kind()) {
107
5.56k
  case LF_CLASS:
108
1.27k
  case LF_STRUCTURE:
109
1.27k
  case LF_INTERFACE:
110
1.27k
    return getHashForUdt<ClassRecord>(Rec);
111
1.27k
  case LF_UNION:
112
0
    return getHashForUdt<UnionRecord>(Rec);
113
1.27k
  case LF_ENUM:
114
100
    return getHashForUdt<EnumRecord>(Rec);
115
1.27k
116
1.27k
  case LF_UDT_SRC_LINE:
117
689
    return getSourceLineHash<UdtSourceLineRecord>(Rec);
118
1.27k
  case LF_UDT_MOD_SRC_LINE:
119
21
    return getSourceLineHash<UdtModSourceLineRecord>(Rec);
120
1.27k
121
3.48k
  default:
122
3.48k
    break;
123
3.48k
  }
124
3.48k
125
3.48k
  // Run CRC32 over the bytes. This corresponds to `hashBufv8`.
126
3.48k
  JamCRC JC(/*Init=*/0U);
127
3.48k
  ArrayRef<char> Bytes(reinterpret_cast<const char *>(Rec.data().data()),
128
3.48k
                       Rec.data().size());
129
3.48k
  JC.update(Bytes);
130
3.48k
  return JC.getCRC();
131
3.48k
}