Re: Make check on FreeBSD 10.x - Intel
Holger Freyther <[email protected]>
| Newsgroups | gmane.comp.lang.smalltalk.gnu.general |
|---|---|
| Message-ID | <[email protected]> |
> On 16 Apr 2015, at 01:14, Holger Freyther <[email protected]> wrote: > Our mul_with_check doesn’t properly detect the overflow on a multiplication > like (380536542838076625 * 576687883419648000) printNl. The result is > negative. I don’t have a fix yet but that is easy now. We need to review the > other routines with an overflow check too. We run the tests on travis-ci so > I wonder how intmax_t is different between BSD and GNU. the compiler optimizes the overflow check away. Shall we move to use a routine like __builtin_mul_overflow (if it is available)? The below is taken from GNU Smalltalk to see what is happening. With clang from apple (Apple LLVM version 6.1.0 (clang-602.0.49) (based on LLVM 3.6.0svn)) generates different output depending on -O0 vs. -O3. result / b == a seems to be considered always true by the compiler. I don’t know the C specification but I assume that “a * b” is assumed to never overflow so that the result of “a * b / b” is certainly “a”. #include <stdint.h> #include <stdio.h> #define PTR void* #define ST_INT_SIZE ((sizeof (PTR) * 8) - 2) #define MAX_ST_INT ((1L << ST_INT_SIZE) - 1) #define MIN_ST_INT ( ~MAX_ST_INT) #define INT_OVERFLOW(i) (((i) ^ ((i) << 1)) < 0) intptr_t mul_with_check(intptr_t a, intptr_t b, int *overflow) { intmax_t result = (intmax_t)a * b; *overflow = 0; /* We define the largest int type in stdintx.h, but we can only use it if it is two times the width of an intptr_t. */ if (sizeof (intmax_t) >= 2 * sizeof (intptr_t)) { if (result > MAX_ST_INT || result < MIN_ST_INT) *overflow = 1; else return (intptr_t) (result); } /* This fallback method uses a division to do overflow check */ else { if ((((uintptr_t) (a | b)) < (1L << (ST_INT_SIZE / 2)) || b == 0 || result / b == a) && !INT_OVERFLOW (result)) return (result); else *overflow = 1; } return (0); } int main(int argc, char **argv) { int overflow; mul_with_check(380536542838076625, 576687883419648000, &overflow); printf("overflow.. %d\n", overflow); } _______________________________________________ help-smalltalk mailing list [email protected] https://lists.gnu.org/mailman/listinfo/help-smalltalk