globus@nas.nasa.gov (Al Globus) (08/22/90)
I have a program that can potentially generate an integer overflow. I'd like to detect this when it happens and deal with it. According to SGI's Hotline folks, no can do. The OS catches the interrupt and then allows the process to go on its merry way with no mechanism to detect the overflow. Is there really no way? There's good mechanisms for floating point exceptions, why not for integer exceptions?
karsh@trifolium.esd.sgi.com (Bruce Karsh) (08/25/90)
In article <GLOBUS.90Aug21114837@wk208.nas.nasa.gov> globus@nas.nasa.gov (Al Globus) writes: >I have a program that can potentially generate an integer overflow. >I'd like to detect this when it happens and deal with it. According >to SGI's Hotline folks, no can do. The OS catches the interrupt >and then allows the process to go on its merry way with no mechanism >to detect the overflow. Well, our illustrious Hotline crew is usually gives perfectly reliable information, but I think they may have missed this time. Here's the straight scoop: The MIPS CPU will generate an integer overflow exception for signed arithmetic instructions, but not unsigned ones. So if the MIPS ADD instruction overflows, a SIGFPE signal is posted, while if an ADDU instruction overflows, there's no interrupt and hence, no signal is posted. In fact, this is the only difference between the operation of the ADD and ADDU instructions. The MIPS C compiler generates unsigned arithmetic instructions. This is the right thing for it to do since most C compilers do not treat 2's complement overflow as an error and some programs even depend on this. I think similar considerations would apply to the Fortran compiler, but I haven't looked. >Is there really no way? There's good mechanisms for floating point >exceptions, why not for integer exceptions? There is a pretty good way if you know the operation which can potentially overflow. If a and b are added, then this test will detect whether c, their sum, has overflowed. c = a + b if( (~a^b && a^c) < 0) handle_overflow(); Bruce Karsh karsh@sgi.com
karsh@trifolium.esd.sgi.com (Bruce Karsh) (08/25/90)
In article <67688@sgi.sgi.com> karsh@trifolium.sgi.com (Bruce Karsh) writes: > if( (~a^b && a^c) < 0) handle_overflow(); This should be if( (~a^b & a^c) < 0) handle_overflow(); I.e., a single &. Ted Wilcox at sgi pointed this out to me. Bruce Karsh karsh@sgi.com
karsh@trifolium.esd.sgi.com (Bruce Karsh) (08/25/90)
In article <67702@sgi.sgi.com> karsh@trifolium.sgi.com (Bruce Karsh) writes: >This should be > if( (~a^b & a^c) < 0) handle_overflow(); I can't get anything right today. Bruce Holloway pointed out the precedence problem. It should be: if( ((~a^b) & (a^c)) < 0) handle_overflow(); because the precedence of & is higher than the precedence of ^. Just to make sure this is right this time, a test case is attached below. /* Test of software overflow handling. */ main() { ofltst(0x80000000,0x80000000); ofltst(0x80000000,0x00000000); ofltst(0x80000000,0x7fffffff); ofltst(0x00000000,0x80000000); ofltst(0x00000000,0x00000000); ofltst(0x00000000,0x7fffffff); ofltst(0x7fffffff,0x80000000); ofltst(0x7fffffff,0x00000000); ofltst(0x7fffffff,0x7fffffff); } ofltst(a,b) int a,b; { int c; c=a+b; if( ((~a^b) & (a^c)) < 0) handle_overflow(a,b,c); else handle_nooverflow(a,b,c); } handle_overflow(a,b,c) int a,b,c; { printf("%11d = %11d + %-11d overflow\n",c,a,b); } handle_nooverflow(a,b,c) int a,b,c; { printf("%11d = %11d + %-11d no overflow\n",c,a,b); } Bruce Karsh karsh@sgi.com
mitch@sgi.com (Thomas Mitchell) (08/29/90)
In article <67688@sgi.sgi.com> karsh@trifolium.sgi.com (Bruce Karsh) writes: * In article <GLOBUS.90Aug21114837@wk208.nas.nasa.gov> globus@nas.nasa.gov (Al Globus) writes: * >I have a program that can potentially generate an integer overflow. * >I'd like to detect this when it happens and deal with it. According * >to SGI's Hotline folks, no can do. Well not in 'c' without testing the values as Ted and Bruce pointed out. This in effect doubles the amount of work that needs to be done on each operation. * > The OS catches the interrupt * >and then allows the process to go on its merry way with no mechanism * >to detect the overflow. * Well, our illustrious Hotline crew is usually gives perfectly reliable * information, but I think they may have missed this time. Here's the * straight scoop: Perhaps we got caught by the simple answer to a simple question. But there are multiple solutions to this problem. * The MIPS CPU will generate an integer overflow exception for signed * arithmetic instructions, but not unsigned ones. So if the MIPS ADD * instruction overflows, a SIGFPE signal is posted, while if an ADDU * instruction overflows, there's no interrupt and hence, no signal is posted. * In fact, this is the only difference between the operation of the ADD and * ADDU instructions. * * The MIPS C compiler generates unsigned arithmetic instructions. This is * the right thing for it to do since most C compilers do not treat 2's * complement overflow as an error and some programs even depend on this. Exactly -- this is what 'C' does. Other languages need to do things differently. Other languages..... Hmmm what is coming here? * I think similar considerations would apply to the Fortran compiler, but * I haven't looked. * * >Is there really no way? There's good mechanisms for floating point * >exceptions, why not for integer exceptions? There are goo ways and good reasons -- 'C' just does not care. If you want a portable test at the expense of extra work. Pre-test: * There is a pretty good way if you know the operation which can potentially * overflow. If a and b are added, then this test will detect whether c, their * sum, has overflowed. if( (~a^b & a^c) < 0) handle_overflow(); I.e., a single &. Thanks Ted W. yet we are solving the problem multiple times. There is an experimental language "Icon" with its roots in Snobol IV. This University of Arizona language project had to deal with exactly this integer overflow problem. Unlike 'c' Icon cares about overflow. Below is some MIPS assemble language which addresses the problem. The contributer of of this code to the Icon language project is: David Bacon Center for Advanced Research in Biotechnology Washington, D.C. The below is from the machine specific portions of the Icon Language interpreter. The distribution has code for 45 flavors of machines (yea, this is a common problem). The Icon Language not to be confused with them little pictures in the corner. The user must provide an entry point for " jal fatalerr" so he can handle the error stuff. Note how an error code is passed to the handler. Perhaps the best thing to do after looking at the following code is to dis-assemble (or capture '-S') the code generated by the compiler and compare. ------------ snip the leading X ---------------------- X .text X .align 2 X .globl ckadd X # 1 #define negative(a) ((unsigned)(a) < (unsigned)(0)) /* test sign bit */ X # 2 long ckadd(x,y) X # 3 long x,y; X # 4 { X .ent ckadd X ckadd: X subu $sp, 24 X sw $31, 20($sp) X .mask 0x80000000, -4 X .frame $sp, 24, $31 X # 5 long r; X # 6 r = x + y; X addu $3, $4, $5 X # 7 if negative(x ^ y) { X xor $14, $4, $5 X bltz $14, $33 X # 8 /* signs are different - sum is safe */ X # 9 return (r); X # 10 } else { X # 11 /* signs are the same - caution is needed */ X # 12 if negative(x ^ r) { X xor $15, $4, $3 X bgez $15, $33 X # 13 /* result sign differs from operand sign */ X # 14 fatalerr (-203, 0); /* overflow */ X li $4, -203 X move $5, $0 X jal fatalerr X move $2,$0 # return 0 if fatalerr returns X b $34 X # 15 } else { X $33: X # 16 return (r); X move $2, $3 X $34: X lw $31, 20($sp) X addu $sp, 24 X j $31 X .end ckadd X .text X .align 2 X .globl cksub X # 23 { X .ent cksub X cksub: X subu $sp, 24 X sw $31, 20($sp) X .mask 0x80000000, -4 X .frame $sp, 24, $31 X # 24 long r; X # 25 r = x - y; X subu $3, $4, $5 X # 26 if negative(x ^ y) { X xor $14, $4, $5 X bgez $14, $35 X # 27 /* signs are different - caution is needed */ X # 28 if negative(x ^ r) { X xor $15, $4, $3 X bgez $15, $35 X # 29 /* x and r have different signs - overflow */ X # 30 fatalerr (-203, 0); X li $4, -203 X move $5, $0 X jal fatalerr X move $2,$0 # return 0 if fatalerr returns X b $37 X # 31 } else { X $35: X # 32 return (r); X # 33 } X # 34 } else { X # 35 /* signs are the same - difference is safe */ X # 36 return (r); X move $2, $3 X # 37 } X # 38 } X $37: X lw $31, 20($sp) X addu $sp, 24 X j $31 X .end cksub X .text X .align 2 X .globl ckmul X # 39 X # 40 long ckmul(x,y) X # 41 long x,y; X # 42 { X .ent ckmul X ckmul: X subu $sp, 24 X sw $31, 20($sp) X .mask 0x80000000, -4 X .frame $sp, 24, $31 X mult $4,$5 # 64-bit product X mfhi $3 # hi part (should be 0 or -1 for no overflow) X mflo $2 # lo part X move $8,$2 # copy of lo part X sra $8,31 # propagate lo's sign bit thru whole word X beq $8,$3,$38 # no overflow if this matches hi part X li $4, -203 X move $5, $0 X jal fatalerr X $38: X lw $31, 20($sp) X addu $sp, 24 X j $31 X .end ckmul X X -- -- Thomas P. Mitchell -- mitch@sgi.com or mitch%relay.csd@sgi.com "All things in moderation; including moderation."