summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author卜部昌平 <shyouhei@ruby-lang.org>2024-04-25 09:25:15 +0200
committer卜部昌平 <shyouhei@ruby-lang.org>2024-04-27 21:55:28 +0900
commitbb5a53820703f5e1af886a0c5ca7178aa976be29 (patch)
tree4e7d416e1c1811cad81e0c7e73db8fde722875b5
parent9ea77cb3514664fc150515765fb9ede5b2b6ab4c (diff)
use of stdckdint.h
C23 is going to have this header. The industry is already moving towards accepting it; OSes and compilers started to implement theirs. Why not detect its presence and if any, prefer over other ways. See also: - https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2683.pdf - https://reviews.freebsd.org/D41734 - https://reviews.llvm.org/D157331 - https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=8441841a1b985d68245954af1ff023db121b0635
-rw-r--r--configure.ac1
-rw-r--r--gc.c3
-rw-r--r--hrtime.h14
-rw-r--r--include/ruby/internal/memory.h6
-rw-r--r--include/ruby/internal/stdckdint.h60
5 files changed, 81 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac
index c487128e31..e9a452ebee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1367,6 +1367,7 @@ AC_CHECK_HEADERS(ucontext.h)
AC_CHECK_HEADERS(utime.h)
AC_CHECK_HEADERS(sys/epoll.h)
AC_CHECK_HEADERS(sys/event.h)
+AC_CHECK_HEADERS(stdckdint.h)
AS_CASE("$target_cpu", [x64|x86_64|i[3-6]86*], [
AC_CHECK_HEADERS(x86intrin.h)
diff --git a/gc.c b/gc.c
index 41207b6eb2..59201458f1 100644
--- a/gc.c
+++ b/gc.c
@@ -224,6 +224,9 @@ size_add_overflow(size_t x, size_t y)
bool p;
#if 0
+#elif defined(ckd_add)
+ p = ckd_add(&z, x, y);
+
#elif __has_builtin(__builtin_add_overflow)
p = __builtin_add_overflow(x, y, &z);
diff --git a/hrtime.h b/hrtime.h
index 7ed4e6b04c..2ca7b0c088 100644
--- a/hrtime.h
+++ b/hrtime.h
@@ -6,6 +6,8 @@
# include <sys/time.h>
#endif
+#include "internal/compilers.h"
+
/*
* Hi-res monotonic clock. It is currently nsec resolution, which has over
* 500 years of range (with an unsigned 64-bit integer). Developers
@@ -61,7 +63,11 @@ rb_hrtime_mul(rb_hrtime_t a, rb_hrtime_t b)
{
rb_hrtime_t c;
-#ifdef HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW
+#ifdef ckd_mul
+ if (ckd_mul(&c, a, b))
+ return RB_HRTIME_MAX;
+
+#elif __has_builtin(__builtin_mul_overflow)
if (__builtin_mul_overflow(a, b, &c))
return RB_HRTIME_MAX;
#else
@@ -81,7 +87,11 @@ rb_hrtime_add(rb_hrtime_t a, rb_hrtime_t b)
{
rb_hrtime_t c;
-#ifdef HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW
+#ifdef ckd_add
+ if (ckd_add(&c, a, b))
+ return RB_HRTIME_MAX;
+
+#elif __has_builtin(__builtin_add_overflow)
if (__builtin_add_overflow(a, b, &c))
return RB_HRTIME_MAX;
#else
diff --git a/include/ruby/internal/memory.h b/include/ruby/internal/memory.h
index 3bd54cd6c7..270cc1ac8b 100644
--- a/include/ruby/internal/memory.h
+++ b/include/ruby/internal/memory.h
@@ -56,6 +56,7 @@
#include "ruby/internal/has/builtin.h"
#include "ruby/internal/stdalign.h"
#include "ruby/internal/stdbool.h"
+#include "ruby/internal/stdckdint.h"
#include "ruby/internal/xmalloc.h"
#include "ruby/backward/2/limits.h"
#include "ruby/backward/2/long_long.h"
@@ -567,7 +568,10 @@ rbimpl_size_mul_overflow(size_t x, size_t y)
{
struct rbimpl_size_mul_overflow_tag ret = { false, 0, };
-#if RBIMPL_HAS_BUILTIN(__builtin_mul_overflow)
+#if defined(ckd_mul)
+ ret.left = ckd_mul(&ret.right, x, y);
+
+#elif RBIMPL_HAS_BUILTIN(__builtin_mul_overflow)
ret.left = __builtin_mul_overflow(x, y, &ret.right);
#elif defined(DSIZE_T)
diff --git a/include/ruby/internal/stdckdint.h b/include/ruby/internal/stdckdint.h
new file mode 100644
index 0000000000..d02530136e
--- /dev/null
+++ b/include/ruby/internal/stdckdint.h
@@ -0,0 +1,60 @@
+#ifndef RBIMPL_STDCKDINT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_STDCKDINT_H
+/**
+ * @author Ruby developers <ruby-core@ruby-lang.org>
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
+ * implementation details. Don't take them as canon. They could
+ * rapidly appear then vanish. The name (path) of this header file
+ * is also an implementation detail. Do not expect it to persist
+ * at the place it is now. Developers are free to move it anywhere
+ * anytime at will.
+ * @note To ruby-core: remember that this header can be possibly
+ * recursively included from extension libraries written in C++.
+ * Do not expect for instance `__VA_ARGS__` is always available.
+ * We assume C99 for ruby itself but we don't assume languages of
+ * extension libraries. They could be written in C++98.
+ * @brief C23 shim for <stdckdint.h>
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/has/builtin.h"
+#include "ruby/internal/stdbool.h"
+
+#ifdef __has_include
+# if __has_include(<stdckdint.h>)
+# /* Conforming C23 situation; e.g. recent clang */
+# define RBIMPL_HAVE_STDCKDINT_H
+# endif
+#endif
+
+#ifdef HAVE_STDCKDINT_H
+# /* Some OSes (most notably FreeBSD) have this file. */
+# define RBIMPL_HAVE_STDCKDINT_H
+#endif
+
+#ifdef RBIMPL_HAVE_STDCKDINT_H
+# /* Take that. */
+# include <stdckdint.h>
+
+#elif RBIMPL_HAS_BUILTIN(__builtin_add_overflow)
+# define ckd_add(x, y, z) ((bool)__builtin_add_overflow((y), (z), (x)))
+# define ckd_sub(x, y, z) ((bool)__builtin_sub_overflow((y), (z), (x)))
+# define ckd_mul(x, y, z) ((bool)__builtin_mul_overflow((y), (z), (x)))
+# define __STDC_VERSION_STDCKDINT_H__ 202311L
+
+#/* elif defined(__cplusplus) */
+#/* :TODO: if we assume C++11 we can use `<type_traits>` to implement them. */
+
+#else
+# /* intentionally leave them undefined */
+# /* to make `#ifdef ckd_add` etc. work as intended. */
+# undef ckd_add
+# undef ckd_sub
+# undef ckd_mul
+# undef __STDC_VERSION_STDCKDINT_H__
+#endif
+
+#endif /* RBIMPL_STDCKDINT_H */