Xref: utzoo comp.sys.dec:2550 comp.sys.mips:452 Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!cs.utexas.edu!uwm.edu!uwvax!whey.cs.wisc.edu!schuh From: schuh@whey.cs.wisc.edu (Dan Schuh) Newsgroups: comp.sys.dec,comp.sys.mips Subject: Re: BUG is MIPS cc for "?" operator Keywords: compiler, MIPS Message-ID: <9652@spool.cs.wisc.edu> Date: 1 Feb 90 16:04:17 GMT References: <21624@pasteur.Berkeley.EDU> Sender: news@spool.cs.wisc.edu Organization: U of Wisconsin CS Dept Lines: 62 In <21624@pasteur.Berkeley.EDU> jac@modoc.berkeley.edu (Gordon Jacobs) writes: --The program below demonstrates various uses of the "?" --selection operator in c that seem to not work correctly on --a DEC3100 running Ultrix3.1. This has also been compiled --on a unit running a test version of Ultrix4.0 with the --exact same results. This seems like a fairly major bug and --it could affect much old software. Has anyone experience ... ( relatively long example deleted, excerpt below) This is not actually a bug, though I'm sure many have been and will continue to be bitten by it. It's actually an ansi-ism in the mips C compiler. The root of the problem is that sizeof is treated as unsigned by the mips C compiler.. K&R I listed sizeof as a signed value, but K&R II and ansi are both clear in making it an unsigned value. This can result in unexpected results in comparisions as the unsigned-ness of sizeof propagates through expressions, under the normal c rules. In the first 'wrong' result instance in your code, you have #define MAX(A,B) ((A)>(B))?(A):(B) #define BITS_PER_INT (sizeof(int)*8) ... int high, low; high= 19; ... low = MAX(0, high-BITS_PER_INT+1); and low ends up unexpectedly as -12 instead of 0. BITS_PER_INT is an unsigned expression due to the presence of sizeof, and therefore high-BITS_PER_INT+1 also becomes unsigned, turning into something undeniably greater that zero. When the value of (B) gets assigned to low, it is coerced back into a sized value and becomes -12; but in its unsized incarnation it couldn't possibly be less than 0. Note that in all the working examples, the comparable expressions do not contain sizeof, vis: #define BITS_PER_INT 32 low = MAX(0, high-BITS_PER_INT+1); When I first came across this I was pulling out hair as I looked at the assembler output of the offending code compared to the dissassembled output of the same code in the debugger; I had written something like if ( 0 < ( value - sizeof(something)) .... The assembler output at the relevant point in the expression jump code was: bgeu while the disassembled object said br So I was running around telling people bizarre things were happening in the mips linker/ backend optimizer or something, until enlightenment dawned and I realized that a branch greater than or equal unsigned (bgeu) was indeed a branch. Cheers, Dan, schuh@cs.wisc.edu