cchris@BBN.COM (Carl Christofferson) (09/13/89)
We recently installed g++ on a Sun3, and I proceeded to try out a very simple minded program of the hello.c variety. To my surprise, I got a segmentation violation. After much wrangling I decided that it was in fact a compiler bug, although I am not at all certain it isn't just an installation problem. I need help in either case. The program bug.cc can be compiled with BUG=0 (bug is off) or BUG=1 (bug is on) and if this re-produces the problem on someone else's Sun3 installation then we have verification. It seems that under certain conditions the compiler messes up parameter passing. The specifics are illustrated in the enclosed file, bugon.out. When evaluating an expression the compiler loads the stack with all the parameters, then calls the functions that act on the parameters in order. Kind of like: return (foo(a,b), bar(d)) evaluating like: push d push a push b call foo popd 1 call bar popd 2 Actually, the real example is somewhat more complex. In anycase, the bug appears because of context: blat(e,f); return (foo(a,b), bar(d)) Which might reasonably look like this: push e push f call blat pop 2 push d push a push b call foo popd 1 call bar popd 2 The compiler seems to want to produce this: push e push f call blat pop 2 replace e with d replace f with a push b call foo popd 1 call bar popd 2 And instead does something like this: push e push f call blat pop 2 push d replace f with a replace d with b call foo popd 1 call bar popd 2 And so by the time bar is called the stack doesn't have the correct parameter on it. Well, that is the best I can do by way of explanation at the moment If it isn't enough, write or call. Thanks, I eagerly await reply. Carl Christofferson cchris@bbn.com (206) 746-6800 14100 SE 36th St. Bellevue, WA 98006 ######################## Enclosure #1 _main: _main: linkw a6,#-0x10 _main+4: moveml a2/a3,sp@- _main+8: clrl sp@- _main+0xa: movl #0x40000000,sp@- _main+0x10: clrl sp@- _main+0x12: movl #0x3ff00000,sp@- _main+0x18: lea a6@(-0x10),a2 _main+0x1c: movl a2,sp@- _main+0x1e: jsr _complex_PScomplex_DF_DF:l // Here is where the stack gets messed up: _main+0x24: pea _op$alshift_expr_Sostream_Scomplex+0x5c _main+0x28: lea sp@(4),a3 _main+0x2c: movl a2,a0 _main+0x2e: movl a3,a1 _main+0x30: movl a2@,a3@ _main+0x32: addqw #4,a1 _main+0x34: addqw #4,a0 _main+0x36: movl a0@+,a1@+ _main+0x38: movl a0@+,a1@+ _main+0x3a: movl a0@,a1@ // The stack is messed up by here. _main+0x3c: movl #0x20046,sp@ _main+0x42: bsr _op$alshift_expr_Sostream_Scomplex _main+0x46: addw #0x14,a7 _main+0x4a: movl d0,sp@- _main+0x4c: bsrl _op$alshift_expr_PSostream_PQI _main+0x52: clrl d0 _main+0x54: moveml a6@(-0x18),a2/a3 _main+0x5a: unlk a6 _main+0x5c: rts ######################## Enclosure #2 #include <stream.h> #include <math.h> #define bugon 1 #define bugoff 0 // // Here is the parameter problem inducing code. // It appears that ALL three of the conditions must be // true before this particular problem arises. That is, // the overload function for '<<' must pass 'complex' by value, // the complex class must not have a constructor with a complex argument // (curiously this isn't used even if it is declared) // and the constructor from two real values must not be inline. // #if BUG==bugon #define CONDITION1 complex #define CONDITION2 #define CONDITION3 #else if BUG==bugon #define CONDITION1 complex& #define CONDITION2 complex(complex& c); #define CONDITION3 inline #endif else if BUG==bugon class complex { protected: double re; double im; public: complex(); CONDITION2 complex(double r, double i = 0.0); ~complex(); friend ostream& operator << (ostream& s, CONDITION1 x); }; inline complex:: complex() {} inline complex::~complex() {} CONDITION3 complex::complex(double r, double i = 0.0) { re = r; im = i; } ostream& operator << (ostream& s, CONDITION1 x) { return s << "(" << x.re << ", " << x.im << ")" ; } int main() { complex x(1,2); cout << x << "\n"; return 0; } ######################## Enclosure #3 ## The Makefile GXX = g++ LIBDIR = /usr/local/lib TFLAGS = -DLDXX=\"$(LIBDIR)/gcc-ld++\" -DCRT1X=\"$(LIBDIR)/crt1+.o\" GFLAGS = -g -O -fchar-charconst -I/usr/local/lib/g++-include -I. -fstrength-reduce #GFLAGS = -g -O -fchar-charconst -I../g++-include -I. -fstrength-reduce -mgnu # all g++ files should have extension .cc .SUFFIXES: .cc .o .cc.o: $(GXX) $(GFLAGS) -c $< .o: $(GXX) $< -o $* bugon.o: bug.cc $(GXX) $(GFLAGS) -DBUG=1 -c bug.cc mv bug.o bugon.o bugoff.o: bug.cc $(GXX) $(GFLAGS) -DBUG=0 -c bug.cc mv bug.o bugoff.o bugon: bugon.o $(GXX) bugon.o -o bugon adb bugon <adb.in2 >bugon.out bugoff: bugoff.o $(GXX) bugoff.o -o bugoff adb bugoff <adb.in2 >bugoff.out bug: bug.o $(GXX) bug.o -o bug adb bug <adb.in2 >bug.out
tom@tnosoes.UUCP (Tom Vijlbrief) (09/14/89)
There is a problem with parameter passing with call by value. Use -fno-defer-pop to fix this. I assume Michael fixed this bug in g++1.36 but I have no access to his latest compiler. Tom =============================================================================== Tom Vijlbrief TNO Institute for Perception P.O. Box 23 Phone: +31 34 63 562 11 3769 ZG Soesterberg E-mail: tnosoes!tom@mcvax.cwi.nl The Netherlands or: uunet!mcvax!tnosoes!tom ===============================================================================