[libc-commits] [libc] 38b6f58 - [libc] implement basic rand and srand
Michael Jones via libc-commits
libc-commits at lists.llvm.org
Tue Oct 4 13:31:34 PDT 2022
Author: Michael Jones
Date: 2022-10-04T13:31:26-07:00
New Revision: 38b6f58e33bbd8dc0be570f41806d0a9006610d9
URL: https://github.com/llvm/llvm-project/commit/38b6f58e33bbd8dc0be570f41806d0a9006610d9
DIFF: https://github.com/llvm/llvm-project/commit/38b6f58e33bbd8dc0be570f41806d0a9006610d9.diff
LOG: [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
Added:
libc/include/llvm-libc-macros/stdlib-macros.h
libc/src/stdlib/rand.cpp
libc/src/stdlib/rand.h
libc/src/stdlib/rand_util.cpp
libc/src/stdlib/rand_util.h
libc/src/stdlib/srand.cpp
libc/src/stdlib/srand.h
libc/test/src/stdlib/rand_test.cpp
Modified:
libc/config/linux/x86_64/entrypoints.txt
libc/include/CMakeLists.txt
libc/include/llvm-libc-macros/CMakeLists.txt
libc/include/stdlib.h.def
libc/spec/spec.td
libc/spec/stdc.td
libc/src/stdlib/CMakeLists.txt
libc/test/src/stdlib/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index c7e6c733bf743..3948220dd1506 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -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
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 3998d7228e681..88018ba1cfe61 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -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
diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
index 740802cd44293..f0d297d36d054 100644
--- a/libc/include/llvm-libc-macros/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -22,6 +22,12 @@ add_header(
.linux.signal_macros
)
+add_header(
+ stdlib_macros
+ HDR
+ stdlib-macros.h
+)
+
add_header(
sys_stat_macros
HDR
diff --git a/libc/include/llvm-libc-macros/stdlib-macros.h b/libc/include/llvm-libc-macros/stdlib-macros.h
new file mode 100644
index 0000000000000..930938dbe82f7
--- /dev/null
+++ b/libc/include/llvm-libc-macros/stdlib-macros.h
@@ -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
diff --git a/libc/include/stdlib.h.def b/libc/include/stdlib.h.def
index f4f8c4f5a907d..18df71a49a9b4 100644
--- a/libc/include/stdlib.h.def
+++ b/libc/include/stdlib.h.def
@@ -10,6 +10,7 @@
#define LLVM_LIBC_STDLIB_H
#include <__llvm-libc-common.h>
+#include <llvm-libc-macros/stdlib-macros.h>
%%public_api()
diff --git a/libc/spec/spec.td b/libc/spec/spec.td
index 10c34b9c58431..87974ece2f8d2 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -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">;
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 11d21ad831a30..8672811692f51 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -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>]>,
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index 7daecd92225bc..b067e847ebbc4 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -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 "")
diff --git a/libc/src/stdlib/rand.cpp b/libc/src/stdlib/rand.cpp
new file mode 100644
index 0000000000000..ef6a7211ab097
--- /dev/null
+++ b/libc/src/stdlib/rand.cpp
@@ -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
diff --git a/libc/src/stdlib/rand.h b/libc/src/stdlib/rand.h
new file mode 100644
index 0000000000000..3f37c5739af87
--- /dev/null
+++ b/libc/src/stdlib/rand.h
@@ -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
diff --git a/libc/src/stdlib/rand_util.cpp b/libc/src/stdlib/rand_util.cpp
new file mode 100644
index 0000000000000..afa6662093f4f
--- /dev/null
+++ b/libc/src/stdlib/rand_util.cpp
@@ -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
diff --git a/libc/src/stdlib/rand_util.h b/libc/src/stdlib/rand_util.h
new file mode 100644
index 0000000000000..61794065a80b6
--- /dev/null
+++ b/libc/src/stdlib/rand_util.h
@@ -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
diff --git a/libc/src/stdlib/srand.cpp b/libc/src/stdlib/srand.cpp
new file mode 100644
index 0000000000000..d93d86712ecd1
--- /dev/null
+++ b/libc/src/stdlib/srand.cpp
@@ -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
diff --git a/libc/src/stdlib/srand.h b/libc/src/stdlib/srand.h
new file mode 100644
index 0000000000000..86228b7a6e820
--- /dev/null
+++ b/libc/src/stdlib/srand.h
@@ -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
diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt
index c31c23c463651..c05bb94d5043f 100644
--- a/libc/test/src/stdlib/CMakeLists.txt
+++ b/libc/test/src/stdlib/CMakeLists.txt
@@ -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(
diff --git a/libc/test/src/stdlib/rand_test.cpp b/libc/test/src/stdlib/rand_test.cpp
new file mode 100644
index 0000000000000..5b03839f83f6f
--- /dev/null
+++ b/libc/test/src/stdlib/rand_test.cpp
@@ -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);
+ }
+}
More information about the libc-commits
mailing list