[libc] implement basic rand and srand
This provides the reference implementation of rand and srand. In future this will likely be upgraded to something that supports full ints. Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D135187
This commit is contained in:
parent
42fead6834
commit
38b6f58e33
|
@ -82,6 +82,8 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
libc.src.stdlib.llabs
|
||||
libc.src.stdlib.lldiv
|
||||
libc.src.stdlib.qsort
|
||||
libc.src.stdlib.rand
|
||||
libc.src.stdlib.srand
|
||||
libc.src.stdlib.strtod
|
||||
libc.src.stdlib.strtof
|
||||
libc.src.stdlib.strtol
|
||||
|
|
|
@ -157,6 +157,7 @@ add_gen_header(
|
|||
GEN_HDR stdlib.h
|
||||
DEPENDS
|
||||
.llvm_libc_common_h
|
||||
.llvm-libc-macros.stdlib_macros
|
||||
.llvm-libc-types.__bsearchcompare_t
|
||||
.llvm-libc-types.__qsortcompare_t
|
||||
.llvm-libc-types.div_t
|
||||
|
|
|
@ -22,6 +22,12 @@ add_header(
|
|||
.linux.signal_macros
|
||||
)
|
||||
|
||||
add_header(
|
||||
stdlib_macros
|
||||
HDR
|
||||
stdlib-macros.h
|
||||
)
|
||||
|
||||
add_header(
|
||||
sys_stat_macros
|
||||
HDR
|
||||
|
|
14
libc/include/llvm-libc-macros/stdlib-macros.h
Normal file
14
libc/include/llvm-libc-macros/stdlib-macros.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
//===-- Definition of macros to be used with stdlib functions ----------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __LLVM_LIBC_MACROS_STDLIB_MACROS_H
|
||||
#define __LLVM_LIBC_MACROS_STDLIB_MACROS_H
|
||||
|
||||
#define RAND_MAX 32767
|
||||
|
||||
#endif // __LLVM_LIBC_MACROS_STDLIB_MACROS_H
|
|
@ -10,6 +10,7 @@
|
|||
#define LLVM_LIBC_STDLIB_H
|
||||
|
||||
#include <__llvm-libc-common.h>
|
||||
#include <llvm-libc-macros/stdlib-macros.h>
|
||||
|
||||
%%public_api()
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ class RestrictedPtrType<Type type> : Type {
|
|||
def VarArgType : NamedType<"...">;
|
||||
def VoidType : NamedType<"void">;
|
||||
def IntType : NamedType<"int">;
|
||||
def UnsignedIntType : NamedType<"unsigned int">;
|
||||
def LongType : NamedType<"long">;
|
||||
def UnsignedLongType : NamedType<"unsigned long">;
|
||||
def LongLongType : NamedType<"long long">;
|
||||
|
|
|
@ -648,6 +648,9 @@ def StdC : StandardSpec<"stdc"> {
|
|||
|
||||
FunctionSpec<"qsort", RetValSpec<VoidType>, [ArgSpec<VoidPtr>, ArgSpec<SizeTType>, ArgSpec<SizeTType>, ArgSpec<QSortCompareT>]>,
|
||||
|
||||
FunctionSpec<"rand", RetValSpec<IntType>, [ArgSpec<VoidType>]>,
|
||||
FunctionSpec<"srand", RetValSpec<VoidType>, [ArgSpec<UnsignedIntType>]>,
|
||||
|
||||
FunctionSpec<"strtof", RetValSpec<FloatType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
|
||||
FunctionSpec<"strtod", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
|
||||
FunctionSpec<"strtold", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>,
|
||||
|
|
|
@ -201,6 +201,36 @@ add_entrypoint_object(
|
|||
libc.include.stdlib
|
||||
)
|
||||
|
||||
add_object_library(
|
||||
rand_util
|
||||
SRCS
|
||||
rand_util.cpp
|
||||
HDRS
|
||||
rand_util.h
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
rand
|
||||
SRCS
|
||||
rand.cpp
|
||||
HDRS
|
||||
rand.h
|
||||
DEPENDS
|
||||
.rand_util
|
||||
libc.include.stdlib
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
srand
|
||||
SRCS
|
||||
srand.cpp
|
||||
HDRS
|
||||
srand.h
|
||||
DEPENDS
|
||||
.rand_util
|
||||
libc.include.stdlib
|
||||
)
|
||||
|
||||
if(LLVM_LIBC_INCLUDE_SCUDO)
|
||||
set(SCUDO_DEPS "")
|
||||
|
||||
|
|
22
libc/src/stdlib/rand.cpp
Normal file
22
libc/src/stdlib/rand.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
//===-- Implementation of rand --------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdlib/rand.h"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/stdlib/rand_util.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
// This rand function is the example implementation from the C standard. It is
|
||||
// not cryptographically secure.
|
||||
LLVM_LIBC_FUNCTION(int, rand, (void)) { // RAND_MAX is assumed to be 32767
|
||||
rand_next = rand_next * 1103515245 + 12345;
|
||||
return static_cast<unsigned int>((rand_next / 65536) % 32768);
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
20
libc/src/stdlib/rand.h
Normal file
20
libc/src/stdlib/rand.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header for rand --------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STDLIB_RAND_H
|
||||
#define LLVM_LIBC_SRC_STDLIB_RAND_H
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int rand(void);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STDLIB_RAND_H
|
15
libc/src/stdlib/rand_util.cpp
Normal file
15
libc/src/stdlib/rand_util.cpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
//===-- Shared utility for rand -------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdlib/rand_util.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
thread_local unsigned long rand_next;
|
||||
|
||||
} // namespace __llvm_libc
|
18
libc/src/stdlib/rand_util.h
Normal file
18
libc/src/stdlib/rand_util.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
//===-- Implementation header for rand utilities ----------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STDLIB_RAND_UTIL_H
|
||||
#define LLVM_LIBC_SRC_STDLIB_RAND_UTIL_H
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
extern thread_local unsigned long rand_next;
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STDLIB_RAND_UTIL_H
|
17
libc/src/stdlib/srand.cpp
Normal file
17
libc/src/stdlib/srand.cpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
//===-- Implementation of srand -------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdlib/srand.h"
|
||||
#include "src/__support/common.h"
|
||||
#include "src/stdlib/rand_util.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(void, srand, (unsigned int seed)) { rand_next = seed; }
|
||||
|
||||
} // namespace __llvm_libc
|
20
libc/src/stdlib/srand.h
Normal file
20
libc/src/stdlib/srand.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header for srand -------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STDLIB_SRAND_H
|
||||
#define LLVM_LIBC_SRC_STDLIB_SRAND_H
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
void srand(unsigned int seed);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STDLIB_SRAND_H
|
|
@ -202,6 +202,18 @@ add_libc_unittest(
|
|||
libc.src.stdlib.qsort
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
rand_test
|
||||
SUITE
|
||||
libc_stdlib_unittests
|
||||
SRCS
|
||||
rand_test.cpp
|
||||
DEPENDS
|
||||
libc.include.stdlib
|
||||
libc.src.stdlib.rand
|
||||
libc.src.stdlib.srand
|
||||
)
|
||||
|
||||
if(LLVM_LIBC_FULL_BUILD)
|
||||
|
||||
add_libc_unittest(
|
||||
|
|
42
libc/test/src/stdlib/rand_test.cpp
Normal file
42
libc/test/src/stdlib/rand_test.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
//===-- Unittests for rand ------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdlib/rand.h"
|
||||
#include "src/stdlib/srand.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
TEST(LlvmLibcRandTest, UnsetSeed) {
|
||||
for (size_t i = 0; i < 1000; ++i) {
|
||||
int val = __llvm_libc::rand();
|
||||
ASSERT_GE(val, 0);
|
||||
ASSERT_LE(val, RAND_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LlvmLibcRandTest, SetSeed) {
|
||||
const unsigned int SEED = 12344321;
|
||||
__llvm_libc::srand(SEED);
|
||||
const size_t NUM_RESULTS = 10;
|
||||
int results[NUM_RESULTS];
|
||||
for (size_t i = 0; i < NUM_RESULTS; ++i) {
|
||||
results[i] = __llvm_libc::rand();
|
||||
ASSERT_GE(results[i], 0);
|
||||
ASSERT_LE(results[i], RAND_MAX);
|
||||
}
|
||||
|
||||
// If the seed is set to the same value, it should give the same sequence.
|
||||
__llvm_libc::srand(SEED);
|
||||
|
||||
for (size_t i = 0; i < NUM_RESULTS; ++i) {
|
||||
int val = __llvm_libc::rand();
|
||||
EXPECT_EQ(results[i], val);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user