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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.