1 //===- HashTable.cpp - PDB Hash Table -------------------------------------===//
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/HashTable.h"
10 #include "llvm/ADT/Optional.h"
11 #include "llvm/DebugInfo/PDB/Native/RawError.h"
12 #include "llvm/Support/BinaryStreamReader.h"
13 #include "llvm/Support/BinaryStreamWriter.h"
14 #include "llvm/Support/Error.h"
15 #include "llvm/Support/MathExtras.h"
16 #include <algorithm>
17 #include <cassert>
18 #include <cstdint>
19 #include <utility>
20 
21 using namespace llvm;
22 using namespace llvm::pdb;
23 
readSparseBitVector(BinaryStreamReader & Stream,SparseBitVector<> & V)24 Error llvm::pdb::readSparseBitVector(BinaryStreamReader &Stream,
25                                      SparseBitVector<> &V) {
26   uint32_t NumWords;
27   if (auto EC = Stream.readInteger(NumWords))
28     return joinErrors(
29         std::move(EC),
30         make_error<RawError>(raw_error_code::corrupt_file,
31                              "Expected hash table number of words"));
32 
33   for (uint32_t I = 0; I != NumWords; ++I) {
34     uint32_t Word;
35     if (auto EC = Stream.readInteger(Word))
36       return joinErrors(std::move(EC),
37                         make_error<RawError>(raw_error_code::corrupt_file,
38                                              "Expected hash table word"));
39     for (unsigned Idx = 0; Idx < 32; ++Idx)
40       if (Word & (1U << Idx))
41         V.set((I * 32) + Idx);
42   }
43   return Error::success();
44 }
45 
writeSparseBitVector(BinaryStreamWriter & Writer,SparseBitVector<> & Vec)46 Error llvm::pdb::writeSparseBitVector(BinaryStreamWriter &Writer,
47                                       SparseBitVector<> &Vec) {
48   constexpr int BitsPerWord = 8 * sizeof(uint32_t);
49 
50   int ReqBits = Vec.find_last() + 1;
51   uint32_t ReqWords = alignTo(ReqBits, BitsPerWord) / BitsPerWord;
52   if (auto EC = Writer.writeInteger(ReqWords))
53     return joinErrors(
54         std::move(EC),
55         make_error<RawError>(raw_error_code::corrupt_file,
56                              "Could not write linear map number of words"));
57 
58   uint32_t Idx = 0;
59   for (uint32_t I = 0; I != ReqWords; ++I) {
60     uint32_t Word = 0;
61     for (uint32_t WordIdx = 0; WordIdx < 32; ++WordIdx, ++Idx) {
62       if (Vec.test(Idx))
63         Word |= (1 << WordIdx);
64     }
65     if (auto EC = Writer.writeInteger(Word))
66       return joinErrors(std::move(EC), make_error<RawError>(
67                                            raw_error_code::corrupt_file,
68                                            "Could not write linear map word"));
69   }
70   return Error::success();
71 }
72