From 2848923a2f5099b6d105b0b30212134d84377dee Mon Sep 17 00:00:00 2001 From: lhchavez Date: Tue, 8 Jan 2019 17:32:23 -0800 Subject: Let GCC use the add/mul overflow intrinsics This change tweaks the macros for git__{add,multiply}_sizet_overflow so that GCC can use them. It also stops using the uadd,umul versions since the add,mul can handle way more cases. --- src/integer.h | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/integer.h b/src/integer.h index 30528db59..98d2b73c5 100644 --- a/src/integer.h +++ b/src/integer.h @@ -55,16 +55,36 @@ GIT_INLINE(bool) git__add_uint64_overflow(uint64_t *out, uint64_t one, uint64_t } /* Use clang/gcc compiler intrinsics whenever possible */ -#if (SIZE_MAX == ULONG_MAX) && __has_builtin(__builtin_uaddl_overflow) -# define git__add_sizet_overflow(out, one, two) \ - __builtin_uaddl_overflow(one, two, out) -# define git__multiply_sizet_overflow(out, one, two) \ - __builtin_umull_overflow(one, two, out) -#elif (SIZE_MAX == UINT_MAX) && __has_builtin(__builtin_uadd_overflow) -# define git__add_sizet_overflow(out, one, two) \ - __builtin_uadd_overflow(one, two, out) -# define git__multiply_sizet_overflow(out, one, two) \ - __builtin_umul_overflow(one, two, out) +#if (__has_builtin(__builtin_add_overflow) || \ + (defined(__GNUC__) && (__GNUC__ >= 5))) + +/* + * Even though __builtin_{add,mul}_overflow should be able to handle all + * possible cases (since it can accept any type), under some configurations + * clang would need a dependency on compiler-rt. In order to avoid that, we + * attempt to choose one of the explicit unsigned long long / unsigned long + * versions of the intrinsics if possible. Unfortunately, unsigned long long + * and unsigned long are still different types to the compiler, so we need to + * still do some additional sniffing to prevent MinGW 64 from choosing the + * wrong version and triggering compiler warnings. + */ +# if (SIZE_MAX == ULLONG_MAX) && (ULONG_MAX == ULLONG_MAX) && defined(_WIN64) +# define git__add_sizet_overflow(out, one, two) \ + __builtin_uaddll_overflow(one, two, out) +# define git__multiply_sizet_overflow(out, one, two) \ + __builtin_umulll_overflow(one, two, out) +# elif (SIZE_MAX == ULONG_MAX) && (ULONG_MAX == ULLONG_MAX) +# define git__add_sizet_overflow(out, one, two) \ + __builtin_uaddl_overflow(one, two, out) +# define git__multiply_sizet_overflow(out, one, two) \ + __builtin_umull_overflow(one, two, out) +# else +# define git__add_sizet_overflow(out, one, two) \ + __builtin_add_overflow(one, two, out) +# define git__multiply_sizet_overflow(out, one, two) \ + __builtin_mul_overflow(one, two, out) +# endif + #else /** -- cgit v1.2.1