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
21using namespace llvm;
22using namespace llvm::pdb;
23
24Error 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
46Error 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