|
35 | 35 | #include <stdbool.h> |
36 | 36 | #include <stdint.h> |
37 | 37 | #include <stddef.h> |
| 38 | +#if __cplusplus // Required on at least one compiler to get ULLONG_MAX |
| 39 | +#include <climits> |
| 40 | +#else |
38 | 41 | #include <limits.h> |
| 42 | +#endif |
39 | 43 |
|
40 | 44 | typedef unsigned char byte; |
41 | 45 | typedef unsigned int uint; |
@@ -454,53 +458,36 @@ static inline uint32_t mp_clz_mpi(mp_int_t x) { |
454 | 458 | #endif |
455 | 459 | } |
456 | 460 |
|
457 | | -// Overflow-checked operations for long long |
| 461 | +// Overflow-checked operations |
458 | 462 |
|
459 | 463 | // Integer overflow builtins were added to GCC 5, but __has_builtin only in GCC 10 |
460 | 464 | // |
461 | 465 | // Note that the builtins has a defined result when overflow occurs, whereas the custom |
462 | 466 | // functions below don't update the result if an overflow would occur (to avoid UB). |
463 | 467 | #define MP_GCC_HAS_BUILTIN_OVERFLOW (__GNUC__ >= 5) |
464 | 468 |
|
465 | | -#if __has_builtin(__builtin_umulll_overflow) || MP_GCC_HAS_BUILTIN_OVERFLOW |
| 469 | +#if MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC |
| 470 | + |
466 | 471 | #define mp_mul_ull_overflow __builtin_umulll_overflow |
| 472 | +#define mp_mul_ll_overflow __builtin_smulll_overflow |
| 473 | +static inline bool mp_mul_mp_int_t_overflow(mp_int_t x, mp_int_t y, mp_int_t *res) { |
| 474 | + // __builtin_mul_overflow is a type-generic function, this inline ensures the argument |
| 475 | + // types are checked to match mp_int_t. |
| 476 | + return __builtin_mul_overflow(x, y, res); |
| 477 | +} |
| 478 | + |
467 | 479 | #else |
468 | | -inline static bool mp_mul_ull_overflow(unsigned long long int x, unsigned long long int y, unsigned long long int *res) { |
| 480 | + |
| 481 | +bool mp_mul_ll_overflow(long long int x, long long int y, long long int *res); |
| 482 | +bool mp_mul_mp_int_t_overflow(mp_int_t x, mp_int_t y, mp_int_t *res); |
| 483 | +static inline bool mp_mul_ull_overflow(unsigned long long int x, unsigned long long int y, unsigned long long int *res) { |
469 | 484 | if (y > 0 && x > (ULLONG_MAX / y)) { |
470 | 485 | return true; // overflow |
471 | 486 | } |
472 | 487 | *res = x * y; |
473 | 488 | return false; |
474 | 489 | } |
475 | | -#endif |
476 | | - |
477 | | -#if __has_builtin(__builtin_smulll_overflow) || MP_GCC_HAS_BUILTIN_OVERFLOW |
478 | | -#define mp_mul_ll_overflow __builtin_smulll_overflow |
479 | | -#else |
480 | | -inline static bool mp_mul_ll_overflow(long long int x, long long int y, long long int *res) { |
481 | | - bool overflow; |
482 | 490 |
|
483 | | - // Check for multiply overflow; see CERT INT32-C |
484 | | - if (x > 0) { // x is positive |
485 | | - if (y > 0) { // x and y are positive |
486 | | - overflow = (x > (LLONG_MAX / y)); |
487 | | - } else { // x positive, y nonpositive |
488 | | - overflow = (y < (LLONG_MIN / x)); |
489 | | - } // x positive, y nonpositive |
490 | | - } else { // x is nonpositive |
491 | | - if (y > 0) { // x is nonpositive, y is positive |
492 | | - overflow = (x < (LLONG_MIN / y)); |
493 | | - } else { // x and y are nonpositive |
494 | | - overflow = (x != 0 && y < (LLONG_MAX / x)); |
495 | | - } // End if x and y are nonpositive |
496 | | - } // End if x is nonpositive |
497 | | - |
498 | | - if (!overflow) { |
499 | | - *res = x * y; |
500 | | - } |
501 | | - |
502 | | - return overflow; |
503 | | -} |
504 | 491 | #endif |
505 | 492 |
|
506 | 493 | #if __has_builtin(__builtin_saddll_overflow) || MP_GCC_HAS_BUILTIN_OVERFLOW |
|
0 commit comments