aboutsummaryrefslogtreecommitdiff
path: root/third_party/subzero/src/IceRNG.cpp
blob: b0d9077c5ddbcc9b7c9ac412572106ec1855a4ff (plain)
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
//===- subzero/src/IceRNG.cpp - PRNG implementation -----------------------===//
//
//                        The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Implements the random number generator.
///
//===----------------------------------------------------------------------===//

#include "IceRNG.h"

#include <climits>
#include <ctime>

namespace Ice {

namespace {
constexpr unsigned MAX = 2147483647;
} // end of anonymous namespace

// TODO(wala,stichnot): Switch to RNG implementation from LLVM or C++11.
//
// TODO(wala,stichnot): Make it possible to replay the RNG sequence in a
// subsequent run, for reproducing a bug. Print the seed in a comment in the
// asm output. Embed the seed in the binary via metadata that an attacker can't
// introspect.
RandomNumberGenerator::RandomNumberGenerator(uint64_t Seed, llvm::StringRef)
    : State(Seed) {}

RandomNumberGenerator::RandomNumberGenerator(
    uint64_t Seed, RandomizationPassesEnum RandomizationPassID, uint64_t Salt) {
  constexpr unsigned NumBitsGlobalSeed = CHAR_BIT * sizeof(State);
  constexpr unsigned NumBitsPassID = 4;
  constexpr unsigned NumBitsSalt = 12;
  static_assert(RPE_num < (1 << NumBitsPassID), "NumBitsPassID too small");
  State =
      Seed ^
      ((uint64_t)RandomizationPassID << (NumBitsGlobalSeed - NumBitsPassID)) ^
      (Salt << (NumBitsGlobalSeed - NumBitsPassID - NumBitsSalt));
}
uint64_t RandomNumberGenerator::next(uint64_t Max) {
  // Lewis, Goodman, and Miller (1969)
  State = (16807 * State) % MAX;
  return State % Max;
}

bool RandomNumberGeneratorWrapper::getTrueWithProbability(float Probability) {
  return static_cast<float>(RNG.next(MAX)) < Probability * static_cast<float>(MAX);
}

} // end of namespace Ice