dwl@mercury.udev.cdc.com (Daren W Latham) (03/06/90)
I have just run across what I believe is a bug in the C compiler. It doesn't
matter if optimization is turned on or not. This program works correctly with
other C compilers. Does anybody (mips perhaps) know if this bug is documented,
or just what the status of this is. I am running on:
RC2030: MIPS R2000A Processor Chip, Revision 2.0
MIPS R2010A VLSI Floating Point Chip Revision: 2.0
RISC/os Release 4.10 mips Version UMIPS
and on a
M2000: MIPS R3000 Processor Chip, Revision 2.0
MIPS R3010 VLSI Floating Point Chip Revision: 2.0
RISC/os Release 4_0 mips Version UMIPS
--
Daren W. Latham | <dwl@udev.cdc.com>
Control Data Corporation | (612)482-3457
Arden Hills, MN |
/* sample program to show compiler bug
*
* Note that the first printf displays a value of 10 and the second
* printf correctly displays a value of 13 for 5+8.
*
* It doesn't make a difference if optimization is turned on or off.
*
*/
#include <stdio.h>
#define PushArg(n) argStack[argStackP++] = n
#define PopArg() argStack[--argStackP]
main()
{
int argStack[10];
int argStackP = 0;
int temp;
PushArg(5);
PushArg(8);
temp = PopArg() + PopArg();
printf ("temp = %d \n", temp);
PushArg(5);
PushArg(8);
temp = PopArg();
temp += PopArg();
printf ("temp = %d \n", temp);
}
rex@mips.COM (Rex Di Bona) (03/06/90)
In article <18302@shamash.cdc.com> dwl@mercury.udev.cdc.com (Daren W Latham) writes: >I have just run across what I believe is a bug in the C compiler. It doesn't >matter if optimization is turned on or not. This program works correctly with >other C compilers. Does anybody (mips perhaps) know if this bug is documented, >or just what the status of this is. I am running on: This is not a "bug". What you have done is illegal under `standard' C. You have two side effects in the one line that refer to the same variable. This usually gives "undefined" results, and is a common source of errors. This is because the order in which the side effects are done in relation to the rest of the code is undefined. Reference: "K&R Section 2.12" (Both first, and second (ansi) editions) >#define PushArg(n) argStack[argStackP++] = n >#define PopArg() argStack[--argStackP] > >main() >{ > int argStack[10]; > int argStackP = 0; > int temp; > > PushArg(5); > PushArg(8); > > temp = PopArg() + PopArg(); This is the line in question. This is it after the preprocessor is done with it. temp = argStack[--argStackP] + argStack[--argStackP] The compiler produces the following for this line: (non optimised) # 24 temp = PopArg() + PopArg(); addu $13, $12, -1 sw $13, 28($sp) addu $14, $13, -1 sw $14, 28($sp) mul $15, $14, 4 addu $24, $sp, $15 lw $24, 32($24) addu $25, $24, $24 sw $25, 24($sp) The compiler has decided to do the two decrements first (this is legal) and has then removed the second lookup in the array to save a multiply. It has finally done the addition. > > printf ("temp = %d \n", temp); > > PushArg(5); > PushArg(8); > > temp = PopArg(); > > temp += PopArg(); > > printf ("temp = %d \n", temp); >} The second version forces the two decrements to be done in the order you expected. The side effects have to be completed before the next line is executed, and so you get both elements. I hope this helps. Rex. -- Rex di Bona Penguin Lust is NOT immoral! rex@mips.com apply STD disclaimers here.
rogerk@servitude.mips.com (Roger B.A. Klorese) (03/10/90)
(I've been asked by Frank Yellin to post this reply, since his followup hasn't made it off Lucid's machines.) ----- Newsgroups: comp.sys.mips Subject: Re: compiler bug Summary: Expires: References: <18302@shamash.cdc.com> <36721@mips.mips.COM> Sender: Reply-To: fy@sunvalleymall.UUCP (Frank Yellin) Followup-To: Distribution: Organization: Lucid, Inc., Menlo Park, CA Keywords: In article <18302@shamash.cdc.com> dwl@mercury.udev.cdc.com (Daren W Latham) writes that the following doesn't compile correctly. >#define PushArg(n) argStack[argStackP++] = n >#define PopArg() argStack[--argStackP] > >main() >{ > int argStack[10]; > int argStackP = 0; > int temp; > > PushArg(5); > PushArg(8); > > temp = PopArg() + PopArg(); > } and in article <36721@mips.mips.COM> rex@mips.COM (Rex Di Bona) replies > The compiler has decided to do the two decrements first > (this is legal) and has then removed the second lookup > in the array to save a multiply. It has finally done the addition. In the Second Edition of "C: A Reference Manual" by Harbison and Steele, they write (p. 190), When evaluating the actual arguments in a function call, the order in which the arguments are evaluated is not specified; but the program must behave as if it chose one argument, evaluated it fully, then chose another argument, evaluated it fully, and so on. . . . A similar restring holds for binary operators: The two operands may be evaluated in either order, but the program must behave as if one of the two operands were evaluated completely before commencement of the evaluation of the second operand. [In] the original description of C. . . . the matter of interleaving was not discussed. . . . We advise implementors to adhere rigidly to the restrictions outlined here (which actually are quite sensible and not terribly restrictive). We also advice programmers not to exploit these restrictions too cleverly. . . . The entire purpose of the restrictions is to make the behavior of the program more understandable. I don't know whether Harbison and Steele is considered authoritative, but they certainly would consider the MIPS implementation to be incorrect. -- Frank Yellin fy@lucid.com --- ROGER B.A. KLORESE MIPS Computer Systems, Inc. phone: +1 408 720-2939 MS 4-02 928 E. Arques Ave. Sunnyvale, CA 94086 rogerk@mips.COM {ames,decwrl,pyramid}!mips!rogerk "I'm the NLA" "Two guys, one cart, fresh pasta... *you* figure it out." -- Suzanne Sugarbaker
chris@mimsy.umd.edu (Chris Torek) (03/10/90)
In article <36884@mips.mips.COM> rogerk@servitude.mips.com (Roger B.A. Klorese) writes for fy@sunvalleymall.UUCP (Frank Yellin): >... the Second Edition of "C: A Reference Manual" by Harbison and Steele [recommends against `interleaving' expression evaluation the way the MIPS compiler did for `result = a[--i] + a[--i]'], then: >I don't know whether Harbison and Steele is considered authoritative, but >they certainly would consider the MIPS implementation to be incorrect. The new authority is the ANSI standard (X3.159); it allows the MIPS implementation. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
davecb@yunexus.UUCP (David Collier-Brown) (03/11/90)
>In article <18302@shamash.cdc.com> dwl@mercury.udev.cdc.com (Daren W Latham) >writes that the following doesn't compile correctly. >>#define PushArg(n) argStack[argStackP++] = n >>#define PopArg() argStack[--argStackP] >> [...] >> temp = PopArg() + PopArg(); >> } Erk! That expands to temp = argStack[--argStackP] + argStack[--argStackP]; for which a legal archaic (K&R) interpretation is (argStackP -= 2, temp = argStack[argStackP] + argStack[argStackP]); In other words, because there are no ";"s in the expression, it's subject to having the addressing operations either pulled to the front (unusual, admittedly) or delayed to the end of the expression (common if they're postfix ++'s). The old rule-of-the-thumb was "anything that doesn't contain a semicolon can be reordered", and several compilers happily did so, typically to avoid generating **horrible** sequences for b[a++] that looked like load a,R1 increment R1 store R1,a decrement R1 load address b,R2 (I'll give you three guesses about who's machine needed this optimization). The ANSI interpretation is substantially similar, if stated and reasoned about quite differently... --dave -- David Collier-Brown, | davecb@yunexus, ...!yunexus!davecb or 72 Abitibi Ave., | {toronto area...}lethe!dave Willowdale, Ontario, | Joyce C-B: CANADA. 416-223-8968 | He's so smart he's dumb.
seanf@sco.COM (Sean Fagan) (03/14/90)
In article <36884@mips.mips.COM> rogerk@servitude.mips.com (Roger B.A. Klorese) writes: >>#define PushArg(n) argStack[argStackP++] = n >>#define PopArg() argStack[--argStackP] >> temp = PopArg() + PopArg(); > When evaluating the actual arguments in a function call, the order in > which the arguments are evaluated is not specified; but the program > must behave as if it chose one argument, evaluated it fully, then chose > another argument, evaluated it fully, and so on. . . . Uhm, I don't see a function call there. I see to macros which are expanded. If you are going to continue this, please move it to comp.lang.c, where it belongs. Please note that Chris Torek has already replied to this, and he is considered a comp.lang.c.deity (right up there with Doug Gwyn and Henry Spencer, right below Dennis Ritchie 8-)). -- -----------------+ Sean Eric Fagan | "Time has little to do with infinity and jelly donuts." seanf@sco.COM | -- Thomas Magnum (Tom Selleck), _Magnum, P.I._ (408) 458-1422 | Any opinions expressed are my own, not my employers'.
diamond@jit345.swstokyo.dec.com (Norman Diamond) (01/23/91)
In article <1685@svin02.info.win.tue.nl> debra@svin02.info.win.tue.nl (Paul de Bra) writes: >struct a { int b, int c } d , e ; should be ; >main() >{ > int f; > f = (d=e).b; >} After correcting your bug, I saw the same error message that you saw. Actually it's inherited from BSD's pcc, which is probably inherited from System III's pcc (because the last time I touched a System V machine, its pcc-based compiler accepted this usage of "."). In ANSI C, (d=e) is a perfectly legal non-lvalue value, therefore (d=e).b is also a perfectly legal non-lvalue value. (I would say rvalue but ANSI C doesn't use this word, except for a dangling reference in the index.) (d=e),d.b also yields a perfectly legal non-lvalue value, so I would agree with your suggestion that it should be equivalent. In K&R-I, the left operand of "." had to be an lvalue. Therefore, if your vendor does not claim ANSI conformance, it might not be a compiler bug. -- Norman Diamond diamond@tkov50.enet.dec.com If this were the company's opinion, I wouldn't be allowed to post it.
rogerk@mips.COM (Roger B.A. Klorese) (01/24/91)
In article <1991Jan23.031214.544@tkou02.enet.dec.com> diamond@jit345.enet@tkou02.enet.dec.com (Norman Diamond) writes: >In ANSI C, (d=e) is a perfectly legal non-lvalue value, therefore (d=e).b >is also a perfectly legal non-lvalue value. >(d=e),d.b also yields a perfectly legal non-lvalue value, so I would >agree with your suggestion that it should be equivalent. > >In K&R-I, the left operand of "." had to be an lvalue. Therefore, if your >vendor does not claim ANSI conformance, it might not be a compiler bug. And, of course, MIPS-C claims K&R-I compliance only. This reference is accepted in the new ANSI C compiler which is in beta test. (Sorry, we have a full complement of test sites, and are not accepting any more.) It is accepted in the K&R mode of the 2.20 compilers as well, as of now; we will check if this should be rejected. -- ROGER B.A. KLORESE MIPS Computer Systems, Inc. MS 6-05 930 DeGuigne Dr. Sunnyvale, CA 94086 +1 408 524-7421 rogerk@mips.COM {ames,decwrl,pyramid}!mips!rogerk "I'm the NLA" "WAR: been there, done that... hated it." -- QueerPeace/DAGGER chant