aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp
blob: f4c46f3c3b0b7dc4eb8129e2d3380b5422cfb74f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//===- NamedStreamMap.cpp - PDB Named Stream Map --------------------------===// 
// 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
// See https://llvm.org/LICENSE.txt for license information. 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
// 
//===----------------------------------------------------------------------===// 
 
#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h" 
#include "llvm/ADT/StringMap.h" 
#include "llvm/ADT/StringRef.h" 
#include "llvm/ADT/iterator_range.h" 
#include "llvm/DebugInfo/PDB/Native/Hash.h" 
#include "llvm/DebugInfo/PDB/Native/HashTable.h" 
#include "llvm/DebugInfo/PDB/Native/RawError.h" 
#include "llvm/Support/BinaryStreamReader.h" 
#include "llvm/Support/BinaryStreamRef.h" 
#include "llvm/Support/BinaryStreamWriter.h" 
#include "llvm/Support/Endian.h" 
#include "llvm/Support/Error.h" 
#include <algorithm> 
#include <cassert> 
#include <cstdint> 
#include <tuple> 
 
using namespace llvm; 
using namespace llvm::pdb; 
 
NamedStreamMapTraits::NamedStreamMapTraits(NamedStreamMap &NS) : NS(&NS) {} 
 
uint16_t NamedStreamMapTraits::hashLookupKey(StringRef S) const { 
  // In the reference implementation, this uses 
  // HASH Hasher<ULONG*, USHORT*>::hashPbCb(PB pb, size_t cb, ULONG ulMod). 
  // Here, the type HASH is a typedef of unsigned short. 
  // ** It is not a bug that we truncate the result of hashStringV1, in fact 
  //    it is a bug if we do not! ** 
  // See NMTNI::hash() in the reference implementation. 
  return static_cast<uint16_t>(hashStringV1(S)); 
} 
 
StringRef NamedStreamMapTraits::storageKeyToLookupKey(uint32_t Offset) const { 
  return NS->getString(Offset); 
} 
 
uint32_t NamedStreamMapTraits::lookupKeyToStorageKey(StringRef S) { 
  return NS->appendStringData(S); 
} 
 
NamedStreamMap::NamedStreamMap() : HashTraits(*this), OffsetIndexMap(1) {} 
 
Error NamedStreamMap::load(BinaryStreamReader &Stream) { 
  uint32_t StringBufferSize; 
  if (auto EC = Stream.readInteger(StringBufferSize)) 
    return joinErrors(std::move(EC), 
                      make_error<RawError>(raw_error_code::corrupt_file, 
                                           "Expected string buffer size")); 
 
  StringRef Buffer; 
  if (auto EC = Stream.readFixedString(Buffer, StringBufferSize)) 
    return EC; 
  NamesBuffer.assign(Buffer.begin(), Buffer.end()); 
 
  return OffsetIndexMap.load(Stream); 
} 
 
Error NamedStreamMap::commit(BinaryStreamWriter &Writer) const { 
  // The first field is the number of bytes of string data. 
  if (auto EC = Writer.writeInteger<uint32_t>(NamesBuffer.size())) 
    return EC; 
 
  // Then the actual string data. 
  StringRef Data(NamesBuffer.data(), NamesBuffer.size()); 
  if (auto EC = Writer.writeFixedString(Data)) 
    return EC; 
 
  // And finally the Offset Index map. 
  if (auto EC = OffsetIndexMap.commit(Writer)) 
    return EC; 
 
  return Error::success(); 
} 
 
uint32_t NamedStreamMap::calculateSerializedLength() const { 
  return sizeof(uint32_t)                              // String data size 
         + NamesBuffer.size()                          // String data 
         + OffsetIndexMap.calculateSerializedLength(); // Offset Index Map 
} 
 
uint32_t NamedStreamMap::size() const { return OffsetIndexMap.size(); } 
 
StringRef NamedStreamMap::getString(uint32_t Offset) const { 
  assert(NamesBuffer.size() > Offset); 
  return StringRef(NamesBuffer.data() + Offset); 
} 
 
uint32_t NamedStreamMap::hashString(uint32_t Offset) const { 
  return hashStringV1(getString(Offset)); 
} 
 
bool NamedStreamMap::get(StringRef Stream, uint32_t &StreamNo) const { 
  auto Iter = OffsetIndexMap.find_as(Stream, HashTraits); 
  if (Iter == OffsetIndexMap.end()) 
    return false; 
  StreamNo = (*Iter).second; 
  return true; 
} 
 
StringMap<uint32_t> NamedStreamMap::entries() const { 
  StringMap<uint32_t> Result; 
  for (const auto &Entry : OffsetIndexMap) { 
    StringRef Stream(NamesBuffer.data() + Entry.first); 
    Result.try_emplace(Stream, Entry.second); 
  } 
  return Result; 
} 
 
uint32_t NamedStreamMap::appendStringData(StringRef S) { 
  uint32_t Offset = NamesBuffer.size(); 
  llvm::append_range(NamesBuffer, S);
  NamesBuffer.push_back('\0'); 
  return Offset; 
} 
 
void NamedStreamMap::set(StringRef Stream, uint32_t StreamNo) { 
  OffsetIndexMap.set_as(Stream, support::ulittle32_t(StreamNo), HashTraits); 
}