diff --git a/compiler-rt/lib/builtins/fixdfdi.c b/compiler-rt/lib/builtins/fixdfdi.c --- a/compiler-rt/lib/builtins/fixdfdi.c +++ b/compiler-rt/lib/builtins/fixdfdi.c @@ -27,8 +27,8 @@ // flags to set, and we don't want to code-gen to an unknown soft-float // implementation. -typedef di_int fixint_t; -typedef du_int fixuint_t; +#define fixint_t di_int +#define fixuint_t du_int #include "fp_fixint_impl.inc" COMPILER_RT_ABI di_int __fixdfdi(fp_t a) { return __fixint(a); } diff --git a/compiler-rt/lib/builtins/fixdfsi.c b/compiler-rt/lib/builtins/fixdfsi.c --- a/compiler-rt/lib/builtins/fixdfsi.c +++ b/compiler-rt/lib/builtins/fixdfsi.c @@ -8,8 +8,8 @@ #define DOUBLE_PRECISION #include "fp_lib.h" -typedef si_int fixint_t; -typedef su_int fixuint_t; +#define fixint_t si_int +#define fixuint_t su_int #include "fp_fixint_impl.inc" COMPILER_RT_ABI si_int __fixdfsi(fp_t a) { return __fixint(a); } diff --git a/compiler-rt/lib/builtins/fixdfti.c b/compiler-rt/lib/builtins/fixdfti.c --- a/compiler-rt/lib/builtins/fixdfti.c +++ b/compiler-rt/lib/builtins/fixdfti.c @@ -12,8 +12,8 @@ #define DOUBLE_PRECISION #include "fp_lib.h" -typedef ti_int fixint_t; -typedef tu_int fixuint_t; +#define fixint_t ti_int +#define fixuint_t tu_int #include "fp_fixint_impl.inc" COMPILER_RT_ABI ti_int __fixdfti(fp_t a) { return __fixint(a); } diff --git a/compiler-rt/lib/builtins/fixsfdi.c b/compiler-rt/lib/builtins/fixsfdi.c --- a/compiler-rt/lib/builtins/fixsfdi.c +++ b/compiler-rt/lib/builtins/fixsfdi.c @@ -27,8 +27,8 @@ // flags to set, and we don't want to code-gen to an unknown soft-float // implementation. -typedef di_int fixint_t; -typedef du_int fixuint_t; +#define fixint_t di_int +#define fixuint_t du_int #include "fp_fixint_impl.inc" COMPILER_RT_ABI di_int __fixsfdi(fp_t a) { return __fixint(a); } diff --git a/compiler-rt/lib/builtins/fixsfsi.c b/compiler-rt/lib/builtins/fixsfsi.c --- a/compiler-rt/lib/builtins/fixsfsi.c +++ b/compiler-rt/lib/builtins/fixsfsi.c @@ -8,8 +8,8 @@ #define SINGLE_PRECISION #include "fp_lib.h" -typedef si_int fixint_t; -typedef su_int fixuint_t; +#define fixint_t si_int +#define fixuint_t su_int #include "fp_fixint_impl.inc" COMPILER_RT_ABI si_int __fixsfsi(fp_t a) { return __fixint(a); } diff --git a/compiler-rt/lib/builtins/fixsfti.c b/compiler-rt/lib/builtins/fixsfti.c --- a/compiler-rt/lib/builtins/fixsfti.c +++ b/compiler-rt/lib/builtins/fixsfti.c @@ -11,9 +11,8 @@ #ifdef CRT_HAS_128BIT #define SINGLE_PRECISION #include "fp_lib.h" - -typedef ti_int fixint_t; -typedef tu_int fixuint_t; +#define fixint_t ti_int +#define fixuint_t tu_int #include "fp_fixint_impl.inc" COMPILER_RT_ABI ti_int __fixsfti(fp_t a) { return __fixint(a); } diff --git a/compiler-rt/lib/builtins/fixtfdi.c b/compiler-rt/lib/builtins/fixtfdi.c --- a/compiler-rt/lib/builtins/fixtfdi.c +++ b/compiler-rt/lib/builtins/fixtfdi.c @@ -10,8 +10,8 @@ #include "fp_lib.h" #if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) -typedef di_int fixint_t; -typedef du_int fixuint_t; +#define fixint_t di_int +#define fixuint_t du_int #include "fp_fixint_impl.inc" COMPILER_RT_ABI di_int __fixtfdi(fp_t a) { return __fixint(a); } diff --git a/compiler-rt/lib/builtins/fixtfsi.c b/compiler-rt/lib/builtins/fixtfsi.c --- a/compiler-rt/lib/builtins/fixtfsi.c +++ b/compiler-rt/lib/builtins/fixtfsi.c @@ -10,8 +10,8 @@ #include "fp_lib.h" #if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) -typedef si_int fixint_t; -typedef su_int fixuint_t; +#define fixint_t si_int +#define fixuint_t su_int #include "fp_fixint_impl.inc" COMPILER_RT_ABI si_int __fixtfsi(fp_t a) { return __fixint(a); } diff --git a/compiler-rt/lib/builtins/fixtfti.c b/compiler-rt/lib/builtins/fixtfti.c --- a/compiler-rt/lib/builtins/fixtfti.c +++ b/compiler-rt/lib/builtins/fixtfti.c @@ -10,8 +10,8 @@ #include "fp_lib.h" #if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) -typedef ti_int fixint_t; -typedef tu_int fixuint_t; +#define fixint_t ti_int +#define fixuint_t tu_int #include "fp_fixint_impl.inc" COMPILER_RT_ABI ti_int __fixtfti(fp_t a) { return __fixint(a); } diff --git a/compiler-rt/lib/builtins/fp_fixint_impl.inc b/compiler-rt/lib/builtins/fp_fixint_impl.inc --- a/compiler-rt/lib/builtins/fp_fixint_impl.inc +++ b/compiler-rt/lib/builtins/fp_fixint_impl.inc @@ -14,8 +14,8 @@ #include "fp_lib.h" static __inline fixint_t __fixint(fp_t a) { - const fixint_t fixint_max = (fixint_t)((~(fixuint_t)0) / 2); - const fixint_t fixint_min = -fixint_max - 1; + const fixint_t fixint_max = MAX_SIGNED(fixint_t); + const fixint_t fixint_min = MIN_SIGNED(fixint_t); // Break a into sign, exponent, significand parts. const rep_t aRep = toRep(a); const rep_t aAbs = aRep & absMask; diff --git a/compiler-rt/lib/builtins/int_mulo_impl.inc b/compiler-rt/lib/builtins/int_mulo_impl.inc --- a/compiler-rt/lib/builtins/int_mulo_impl.inc +++ b/compiler-rt/lib/builtins/int_mulo_impl.inc @@ -16,10 +16,21 @@ // Effects: sets *overflow to 1 if a * b overflows -static __inline fixint_t __muloXi4(fixint_t a, fixint_t b, int *overflow) { - const int N = (int)(sizeof(fixint_t) * CHAR_BIT); - const fixint_t MIN = (fixint_t)1 << (N - 1); - const fixint_t MAX = ~MIN; +// UBSan may be useful for testing the compiler-rt/builtins library by manually +// setting CFLAGS="-fsanitize=undefined -fsanitize-undefined-trap-on-error" +// when configuring compiler-rt and then running check-builtins. +// The problem with __mulo[sdt]i4 LibCalls is that they may recursively call +// themselves indefinitely when compiled with UBSan. +#if defined(__clang__) +#define NO_UBSAN __attribute__((no_sanitize("undefined"))) +#else +#define NO_UBSAN +#endif + +static __inline NO_UBSAN fixint_t __muloXi4(fixint_t a, fixint_t b, int *overflow) { + const int N = bitsizeof(fixint_t); + const fixint_t MIN = MIN_SIGNED(fixint_t); + const fixint_t MAX = MAX_SIGNED(fixint_t); *overflow = 0; fixint_t result = a * b; if (a == MIN) { diff --git a/compiler-rt/lib/builtins/int_mulv_impl.inc b/compiler-rt/lib/builtins/int_mulv_impl.inc --- a/compiler-rt/lib/builtins/int_mulv_impl.inc +++ b/compiler-rt/lib/builtins/int_mulv_impl.inc @@ -17,9 +17,9 @@ // Effects: aborts if a * b overflows static __inline fixint_t __mulvXi3(fixint_t a, fixint_t b) { - const int N = (int)(sizeof(fixint_t) * CHAR_BIT); - const fixint_t MIN = (fixint_t)1 << (N - 1); - const fixint_t MAX = ~MIN; + const int N = bitsizeof(fixint_t); + const fixint_t MIN = MIN_SIGNED(fixint_t); + const fixint_t MAX = MAX_SIGNED(fixint_t); if (a == MIN) { if (b == 0 || b == 1) return a * b; diff --git a/compiler-rt/lib/builtins/int_types.h b/compiler-rt/lib/builtins/int_types.h --- a/compiler-rt/lib/builtins/int_types.h +++ b/compiler-rt/lib/builtins/int_types.h @@ -1,4 +1,4 @@ -//===-- int_lib.h - configuration header for compiler-rt -----------------===// +//===-- int_types.h - type definitions for compiler-rt --------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -37,6 +37,30 @@ typedef int64_t di_int; typedef uint64_t du_int; +// Helpers for standard type aliases to get signed from unsigned and vice versa +#define AS_SIGNED(type) type##_AS_SIGNED +#define AS_UNSIGNED(type) type##_AS_UNSIGNED +#define si_int_AS_SIGNED si_int +#define su_int_AS_SIGNED si_int +#define di_int_AS_SIGNED di_int +#define du_int_AS_SIGNED di_int +#define ti_int_AS_SIGNED ti_int +#define tu_int_AS_SIGNED ti_int +#define si_int_AS_UNSIGNED su_int +#define su_int_AS_UNSIGNED su_int +#define di_int_AS_UNSIGNED du_int +#define du_int_AS_UNSIGNED du_int +#define ti_int_AS_UNSIGNED tu_int +#define tu_int_AS_UNSIGNED tu_int + +// Misc macroses incapsulating common hacks. +// Supposed to replace the ad-hoc UB-prone implementations. +#define bitsizeof(type_or_value) ((int)(sizeof(type_or_value) * CHAR_BIT)) +#define SIGN_BIT(type) ((AS_UNSIGNED(type))1 << (bitsizeof(type) - 1)) +#define MIN_SIGNED(type) ((AS_SIGNED(type))SIGN_BIT(type)) +#define MAX_SIGNED(type) ((AS_SIGNED(type))(SIGN_BIT(type) - 1U)) +#define MAX_UNSIGNED(type) (~(AS_UNSIGNED(type))0)) + typedef union { di_int all; struct { diff --git a/compiler-rt/lib/builtins/negdi2.c b/compiler-rt/lib/builtins/negdi2.c --- a/compiler-rt/lib/builtins/negdi2.c +++ b/compiler-rt/lib/builtins/negdi2.c @@ -17,5 +17,5 @@ COMPILER_RT_ABI di_int __negdi2(di_int a) { // Note: this routine is here for API compatibility; any sane compiler // should expand it inline. - return -a; + return -(du_int)a; } diff --git a/compiler-rt/lib/builtins/negti2.c b/compiler-rt/lib/builtins/negti2.c --- a/compiler-rt/lib/builtins/negti2.c +++ b/compiler-rt/lib/builtins/negti2.c @@ -19,7 +19,7 @@ COMPILER_RT_ABI ti_int __negti2(ti_int a) { // Note: this routine is here for API compatibility; any sane compiler // should expand it inline. - return -a; + return -(tu_int)a; } #endif // CRT_HAS_128BIT diff --git a/compiler-rt/lib/builtins/negvdi2.c b/compiler-rt/lib/builtins/negvdi2.c --- a/compiler-rt/lib/builtins/negvdi2.c +++ b/compiler-rt/lib/builtins/negvdi2.c @@ -17,8 +17,7 @@ // Effects: aborts if -a overflows COMPILER_RT_ABI di_int __negvdi2(di_int a) { - const di_int MIN = (di_int)1 << ((int)(sizeof(di_int) * CHAR_BIT) - 1); - if (a == MIN) + if (a == MIN_SIGNED(di_int)) compilerrt_abort(); return -a; } diff --git a/compiler-rt/lib/builtins/negvsi2.c b/compiler-rt/lib/builtins/negvsi2.c --- a/compiler-rt/lib/builtins/negvsi2.c +++ b/compiler-rt/lib/builtins/negvsi2.c @@ -17,8 +17,7 @@ // Effects: aborts if -a overflows COMPILER_RT_ABI si_int __negvsi2(si_int a) { - const si_int MIN = (si_int)1 << ((int)(sizeof(si_int) * CHAR_BIT) - 1); - if (a == MIN) + if (a == MIN_SIGNED(si_int)) compilerrt_abort(); return -a; } diff --git a/compiler-rt/lib/builtins/negvti2.c b/compiler-rt/lib/builtins/negvti2.c --- a/compiler-rt/lib/builtins/negvti2.c +++ b/compiler-rt/lib/builtins/negvti2.c @@ -19,8 +19,7 @@ // Effects: aborts if -a overflows COMPILER_RT_ABI ti_int __negvti2(ti_int a) { - const ti_int MIN = (ti_int)1 << ((int)(sizeof(ti_int) * CHAR_BIT) - 1); - if (a == MIN) + if (a == MIN_SIGNED(ti_int)) compilerrt_abort(); return -a; }