1274955Ssvnmir//===-- RandomNumberGenerator.cpp - Implement RNG class -------------------===//
2274955Ssvnmir//
3274955Ssvnmir//                     The LLVM Compiler Infrastructure
4274955Ssvnmir//
5274955Ssvnmir// This file is distributed under the University of Illinois Open Source
6274955Ssvnmir// License. See LICENSE.TXT for details.
7274955Ssvnmir//
8274955Ssvnmir//===----------------------------------------------------------------------===//
9274955Ssvnmir//
10280031Sdim// This file implements deterministic random number generation (RNG).
11274955Ssvnmir// The current implementation is NOT cryptographically secure as it uses
12274955Ssvnmir// the C++11 <random> facilities.
13274955Ssvnmir//
14274955Ssvnmir//===----------------------------------------------------------------------===//
15274955Ssvnmir
16288943Sdim#include "llvm/Support/RandomNumberGenerator.h"
17274955Ssvnmir#include "llvm/Support/CommandLine.h"
18274955Ssvnmir#include "llvm/Support/Debug.h"
19288943Sdim#include "llvm/Support/raw_ostream.h"
20274955Ssvnmir
21274955Ssvnmirusing namespace llvm;
22274955Ssvnmir
23288943Sdim#define DEBUG_TYPE "rng"
24288943Sdim
25274955Ssvnmir// Tracking BUG: 19665
26274955Ssvnmir// http://llvm.org/bugs/show_bug.cgi?id=19665
27274955Ssvnmir//
28274955Ssvnmir// Do not change to cl::opt<uint64_t> since this silently breaks argument parsing.
29274955Ssvnmirstatic cl::opt<unsigned long long>
30274955SsvnmirSeed("rng-seed", cl::value_desc("seed"),
31274955Ssvnmir     cl::desc("Seed for the random number generator"), cl::init(0));
32274955Ssvnmir
33274955SsvnmirRandomNumberGenerator::RandomNumberGenerator(StringRef Salt) {
34274955Ssvnmir  DEBUG(
35274955Ssvnmir    if (Seed == 0)
36280031Sdim      dbgs() << "Warning! Using unseeded random number generator.\n"
37274955Ssvnmir  );
38274955Ssvnmir
39280031Sdim  // Combine seed and salts using std::seed_seq.
40280031Sdim  // Data: Seed-low, Seed-high, Salt
41280031Sdim  // Note: std::seed_seq can only store 32-bit values, even though we
42280031Sdim  // are using a 64-bit RNG. This isn't a problem since the Mersenne
43280031Sdim  // twister constructor copies these correctly into its initial state.
44274955Ssvnmir  std::vector<uint32_t> Data;
45280031Sdim  Data.reserve(2 + Salt.size());
46274955Ssvnmir  Data.push_back(Seed);
47274955Ssvnmir  Data.push_back(Seed >> 32);
48274955Ssvnmir
49280031Sdim  std::copy(Salt.begin(), Salt.end(), Data.end());
50274955Ssvnmir
51274955Ssvnmir  std::seed_seq SeedSeq(Data.begin(), Data.end());
52274955Ssvnmir  Generator.seed(SeedSeq);
53274955Ssvnmir}
54274955Ssvnmir
55280031Sdimuint_fast64_t RandomNumberGenerator::operator()() {
56280031Sdim  return Generator();
57274955Ssvnmir}
58