This is actually a rather nice method. Of course, it turns out
that people want finer granularity of testing for integer overflow.
You might consider using C99's _Pragma() construct to turn this
automatic overflow-testing on and off. (_Pragma is better than
#pragma as "_Pragma"s can be hidden behind preprocessor macros.)
2) Using the _overflow() intrinsic to test for overflow after
a specific operation, for instance:
int a,n; [presumably here "n" is set to some value; "a" is irrelevant]
n = n*59876;
if (_overflow())
printf("It did not work\n");
In another compiler systems the best thing is to use assembly:
.text
.globl _overflow
_overflow:
movl $0,%eax
seto %al
ret
This function will return 1 if the overflow flag is set,
zero otherwise. Note that a move is done to zero eax, NOT
xor eax,eax because that would destroy the flags.
This method will not work in general, for reasons I will mention in
a moment.
You apparently have not read the assembly language manual for the sparc
thoroughly.
1. BVS does (as the name implies) a branch when the overflow bit is set.
I think you mean SVS (or something like that) which sets a register
to 0 or 1 depending on the overflow bit.
The SPARC does not have an "svs", though it does have a "tvs" (trap
if overflow is set). One could use bvs, if it were not for a rather
different problem that you also mention:
2. If the compiler uses the instructions that do not set the overflow
bit, this will not help at all. "add" will not set it on addition,
"addcc" will set it on addition. I think most compilers do not use
"addcc" as it might trap.
Actually addcc never traps; it merely sets the condition codes
(both %icc and %xcc on V9; V8 and earlier have only %icc) based on
the result of the add. You may be thinking of "taddcc", although
that instruction is intended for Lisp systems.
It is, however, true that most compilers generate a simple "add"
or -- for multiply -- one of three instructions or instruction
sequences, none of which set the "v" flag in %icc and/or %xcc.
So this method will not work on SPARC systems.
Unfortunately, the overflow() function will also not work on x86
systems -- or rather, worse, it will *sometimes* work, but sometimes
fail, in a manner anywhere from "difficult" to "impossible" to
predict. The reason is that there is no requirement that the
compiler call overflow() immediately after the "obvious" instruction
(in this case imull). The code:
n = n * 59876;
if (_overflow())
...
use(n);
might -- as long as n is a local variable, thus "obviously" not
accessible from a function like _overflow() -- quite legitimately
compile to:
call _overflow
testl %eax,%eax
je .Laround
...
..Laround:
# multiply n by 59876 *now*, *after* calling overflow()
imull ... # or equivalent (gcc uses a sequence of "leal"s)
pushl [n] #
call use
As it happens, gcc (2.95.3, and not using -march=k6 or -march=i686)
does not move the multiply itself in a small sample routine I
created, but it does use leal instead of imull, and leal does not
set the "v" bit:
# at this point, "n" is in %ebx
leal (%ebx,%ebx,2),%eax
leal (%ebx,%eax,4),%eax
leal (%eax,%eax,8),%eax
sall $4,%eax
subl %ebx,%eax
leal (%ebx,%eax,8),%eax
leal 0(,%eax,4),%ebx
call _overflow
...
The "v" bit value will be left over from the "subl" instruction,
and will have little to do with whether the multiply really
overflowed. (But note that with 686 or k6 architecture or CPU
selected, the cost of the imull is reduced, so the instruction
selector chooses it instead of the leal-sequence.)