xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/fuzzer/FuzzerValueBitMap.h (revision a7c257b03e4462df2b1020128fb82716512d7856)
1*a7c257b0Skamil //===- FuzzerValueBitMap.h - INTERNAL - Bit map -----------------*- C++ -* ===//
2*a7c257b0Skamil //
3*a7c257b0Skamil //                     The LLVM Compiler Infrastructure
4*a7c257b0Skamil //
5*a7c257b0Skamil // This file is distributed under the University of Illinois Open Source
6*a7c257b0Skamil // License. See LICENSE.TXT for details.
7*a7c257b0Skamil //
8*a7c257b0Skamil //===----------------------------------------------------------------------===//
9*a7c257b0Skamil // ValueBitMap.
10*a7c257b0Skamil //===----------------------------------------------------------------------===//
11*a7c257b0Skamil 
12*a7c257b0Skamil #ifndef LLVM_FUZZER_VALUE_BIT_MAP_H
13*a7c257b0Skamil #define LLVM_FUZZER_VALUE_BIT_MAP_H
14*a7c257b0Skamil 
15*a7c257b0Skamil #include "FuzzerDefs.h"
16*a7c257b0Skamil 
17*a7c257b0Skamil namespace fuzzer {
18*a7c257b0Skamil 
19*a7c257b0Skamil // A bit map containing kMapSizeInWords bits.
20*a7c257b0Skamil struct ValueBitMap {
21*a7c257b0Skamil   static const size_t kMapSizeInBits = 1 << 16;
22*a7c257b0Skamil   static const size_t kMapPrimeMod = 65371;  // Largest Prime < kMapSizeInBits;
23*a7c257b0Skamil   static const size_t kBitsInWord = (sizeof(uintptr_t) * 8);
24*a7c257b0Skamil   static const size_t kMapSizeInWords = kMapSizeInBits / kBitsInWord;
25*a7c257b0Skamil  public:
26*a7c257b0Skamil 
27*a7c257b0Skamil   // Clears all bits.
ResetValueBitMap28*a7c257b0Skamil   void Reset() { memset(Map, 0, sizeof(Map)); }
29*a7c257b0Skamil 
30*a7c257b0Skamil   // Computes a hash function of Value and sets the corresponding bit.
31*a7c257b0Skamil   // Returns true if the bit was changed from 0 to 1.
32*a7c257b0Skamil   ATTRIBUTE_NO_SANITIZE_ALL
AddValueValueBitMap33*a7c257b0Skamil   inline bool AddValue(uintptr_t Value) {
34*a7c257b0Skamil     uintptr_t Idx = Value % kMapSizeInBits;
35*a7c257b0Skamil     uintptr_t WordIdx = Idx / kBitsInWord;
36*a7c257b0Skamil     uintptr_t BitIdx = Idx % kBitsInWord;
37*a7c257b0Skamil     uintptr_t Old = Map[WordIdx];
38*a7c257b0Skamil     uintptr_t New = Old | (1UL << BitIdx);
39*a7c257b0Skamil     Map[WordIdx] = New;
40*a7c257b0Skamil     return New != Old;
41*a7c257b0Skamil   }
42*a7c257b0Skamil 
43*a7c257b0Skamil   ATTRIBUTE_NO_SANITIZE_ALL
AddValueModPrimeValueBitMap44*a7c257b0Skamil   inline bool AddValueModPrime(uintptr_t Value) {
45*a7c257b0Skamil     return AddValue(Value % kMapPrimeMod);
46*a7c257b0Skamil   }
47*a7c257b0Skamil 
GetValueBitMap48*a7c257b0Skamil   inline bool Get(uintptr_t Idx) {
49*a7c257b0Skamil     assert(Idx < kMapSizeInBits);
50*a7c257b0Skamil     uintptr_t WordIdx = Idx / kBitsInWord;
51*a7c257b0Skamil     uintptr_t BitIdx = Idx % kBitsInWord;
52*a7c257b0Skamil     return Map[WordIdx] & (1UL << BitIdx);
53*a7c257b0Skamil   }
54*a7c257b0Skamil 
SizeInBitsValueBitMap55*a7c257b0Skamil   size_t SizeInBits() const { return kMapSizeInBits; }
56*a7c257b0Skamil 
57*a7c257b0Skamil   template <class Callback>
58*a7c257b0Skamil   ATTRIBUTE_NO_SANITIZE_ALL
ForEachValueBitMap59*a7c257b0Skamil   void ForEach(Callback CB) const {
60*a7c257b0Skamil     for (size_t i = 0; i < kMapSizeInWords; i++)
61*a7c257b0Skamil       if (uintptr_t M = Map[i])
62*a7c257b0Skamil         for (size_t j = 0; j < sizeof(M) * 8; j++)
63*a7c257b0Skamil           if (M & ((uintptr_t)1 << j))
64*a7c257b0Skamil             CB(i * sizeof(M) * 8 + j);
65*a7c257b0Skamil   }
66*a7c257b0Skamil 
67*a7c257b0Skamil  private:
68*a7c257b0Skamil   uintptr_t Map[kMapSizeInWords] __attribute__((aligned(512)));
69*a7c257b0Skamil };
70*a7c257b0Skamil 
71*a7c257b0Skamil }  // namespace fuzzer
72*a7c257b0Skamil 
73*a7c257b0Skamil #endif  // LLVM_FUZZER_VALUE_BIT_MAP_H
74