diff --git a/internal/compilers.h b/internal/compilers.h index 8f32030c60..781dd9cfc9 100644 --- a/internal/compilers.h +++ b/internal/compilers.h @@ -85,6 +85,7 @@ # * granular. */ # /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66970 */ # define __has_builtin(...) __has_builtin_##__VA_ARGS__ +# define __has_builtin____builtin_add_overflow GCC_VERSION_SINCE(5, 1, 0) # define __has_builtin____builtin_bswap16 GCC_VERSION_SINCE(4, 8, 0) /* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52624 */ # define __has_builtin____builtin_bswap32 GCC_VERSION_SINCE(3, 6, 0) # define __has_builtin____builtin_bswap64 GCC_VERSION_SINCE(3, 6, 0) @@ -94,12 +95,17 @@ # define __has_builtin____builtin_ctz GCC_VERSION_SINCE(3, 6, 0) # define __has_builtin____builtin_ctzl GCC_VERSION_SINCE(3, 6, 0) # define __has_builtin____builtin_ctzll GCC_VERSION_SINCE(3, 6, 0) -# define __has_builtin____builtin_mul_overflow GCC_VERSION_SINCE(5, 0, 0) +# define __has_builtin____builtin_mul_overflow GCC_VERSION_SINCE(5, 1, 0) # define __has_builtin____builtin_mul_overflow_p GCC_VERSION_SINCE(7, 0, 0) # define __has_builtin____builtin_popcount GCC_VERSION_SINCE(3, 6, 0) # define __has_builtin____builtin_popcountl GCC_VERSION_SINCE(3, 6, 0) # define __has_builtin____builtin_popcountll GCC_VERSION_SINCE(3, 6, 0) +# define __has_builtin____builtin_sub_overflow GCC_VERSION_SINCE(5, 1, 0) # /* Take config.h definition when available */ +# ifdef HAVE_BUILTIN____BUILTIN_ADD_OVERFLOW +# undef __has_builtin____builtin_add_overflow +# define __has_builtin____builtin_add_overflow HAVE_BUILTIN____BUILTIN_ADD_OVERFLOW +# endif # ifdef HAVE_BUILTIN____BUILTIN_BSWAP16 # undef __has_builtin____builtin_bswap16 # define __has_builtin____builtin_bswap16 HAVE_BUILTIN____BUILTIN_BSWAP16 @@ -156,6 +162,10 @@ # undef __has_builtin____builtin_popcountll # define __has_builtin____builtin_popcountll HAVE_BUILTIN____BUILTIN_POPCOUNTLL # endif +# ifdef HAVE_BUILTIN____BUILTIN_SUB_OVERFLOW +# undef __has_builtin____builtin_SUB_overflow +# define __has_builtin____builtin_sub_overflow HAVE_BUILTIN____BUILTIN_SUB_OVERFLOW +# endif #endif #ifndef __has_feature diff --git a/internal/fixnum.h b/internal/fixnum.h index 08ca7bcec7..a388ddb36a 100644 --- a/internal/fixnum.h +++ b/internal/fixnum.h @@ -9,6 +9,12 @@ * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ +#include "ruby/config.h" /* for HAVE_LONG_LONG */ +#include /* for CHAR_BIT */ +#include "internal/compilers.h" /* for __has_builtin */ +#include "internal/stdbool.h" /* for bool */ +#include "ruby/intern.h" /* for rb_big_mul */ +#include "ruby/ruby.h" /* for RB_FIXABLE */ #if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG # define DLONG LONG_LONG @@ -16,9 +22,20 @@ #elif defined(HAVE_INT128_T) # define DLONG int128_t # define DL2NUM(x) (RB_FIXABLE(x) ? LONG2FIX(x) : rb_int128t2big(x)) -VALUE rb_int128t2big(int128_t n); +VALUE rb_int128t2big(int128_t n); /* in bignum.c */ #endif +static inline long rb_overflowed_fix_to_int(long x); +static inline VALUE rb_fix_plus_fix(VALUE x, VALUE y); +static inline VALUE rb_fix_minus_fix(VALUE x, VALUE y); +static inline VALUE rb_fix_mul_fix(VALUE x, VALUE y); +static inline void rb_fix_divmod_fix(VALUE x, VALUE y, VALUE *divp, VALUE *modp); +static inline VALUE rb_fix_div_fix(VALUE x, VALUE y); +static inline VALUE rb_fix_mod_fix(VALUE x, VALUE y); +static inline bool FIXNUM_POSITIVE_P(VALUE num); +static inline bool FIXNUM_NEGATIVE_P(VALUE num); +static inline bool FIXNUM_ZERO_P(VALUE num); + static inline long rb_overflowed_fix_to_int(long x) { @@ -28,7 +45,10 @@ rb_overflowed_fix_to_int(long x) static inline VALUE rb_fix_plus_fix(VALUE x, VALUE y) { -#ifdef HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW +#if !__has_builtin(__builtin_add_overflow) + long lz = FIX2LONG(x) + FIX2LONG(y); + return LONG2NUM(lz); +#else long lz; /* NOTE * (1) `LONG2FIX(FIX2LONG(x)+FIX2LONG(y))` @@ -56,16 +76,16 @@ rb_fix_plus_fix(VALUE x, VALUE y) else { return (VALUE)lz; } -#else - long lz = FIX2LONG(x) + FIX2LONG(y); - return LONG2NUM(lz); #endif } static inline VALUE rb_fix_minus_fix(VALUE x, VALUE y) { -#ifdef HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW +#if !__has_builtin(__builtin_sub_overflow) + long lz = FIX2LONG(x) - FIX2LONG(y); + return LONG2NUM(lz); +#else long lz; if (__builtin_sub_overflow((long)x, (long)y-1, &lz)) { return rb_int2big(rb_overflowed_fix_to_int(lz)); @@ -73,9 +93,6 @@ rb_fix_minus_fix(VALUE x, VALUE y) else { return (VALUE)lz; } -#else - long lz = FIX2LONG(x) - FIX2LONG(y); - return LONG2NUM(lz); #endif } @@ -147,4 +164,22 @@ rb_fix_mod_fix(VALUE x, VALUE y) rb_fix_divmod_fix(x, y, NULL, &mod); return mod; } + +static inline bool +FIXNUM_POSITIVE_P(VALUE num) +{ + return (SIGNED_VALUE)num > (SIGNED_VALUE)INT2FIX(0); +} + +static inline bool +FIXNUM_NEGATIVE_P(VALUE num) +{ + return (SIGNED_VALUE)num < 0; +} + +static inline bool +FIXNUM_ZERO_P(VALUE num) +{ + return num == INT2FIX(0); +} #endif /* INTERNAL_FIXNUM_H */ diff --git a/internal/numeric.h b/internal/numeric.h index 3e64b82daf..c85327ea82 100644 --- a/internal/numeric.h +++ b/internal/numeric.h @@ -9,6 +9,7 @@ * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ +#include "internal/fixnum.h" /* for FIXNUM_POSITIVE_P */ struct RFloat { struct RBasic basic; @@ -19,10 +20,6 @@ struct RFloat { /* numeric.c */ -#define FIXNUM_POSITIVE_P(num) ((SIGNED_VALUE)(num) > (SIGNED_VALUE)INT2FIX(0)) -#define FIXNUM_NEGATIVE_P(num) ((SIGNED_VALUE)(num) < 0) -#define FIXNUM_ZERO_P(num) ((num) == INT2FIX(0)) - #define INT_NEGATIVE_P(x) (FIXNUM_P(x) ? FIXNUM_NEGATIVE_P(x) : BIGNUM_NEGATIVE_P(x)) #define FLOAT_ZERO_P(x) (RFLOAT_VALUE(x) == 0.0)