apparent codegen bug on sparc

der Mouse mouse@Rodents.Montreal.QC.CA
Wed Aug 11 09:42:00 GMT 1999


I seem to have found a codegen bug on the SPARC port.  First the brief
form; I'll give full details later in this note.

I use nested functions with nonlocal gotos to provide a catch/throw
facility somewhat more cleanly than setjmp/longjmp.  But it appears the
nested function is getting miscompiled under some circumstances.  To
make things more interesting, turning on the optimizer "fixes" it.

The code looks like

	static int wrap(void (*fn)(unsigned char), unsigned char arg)
	{
	 __label__ fail;
	
	 static void _fail(void)
	  { goto fail;
	  }
[...]
	}

Unoptimized, this turns into

	.align 4
	.type	 __fail.4,@function
	.proc	020
__fail.4:
.stabn 68,0,12,LM1
LM1:
	!#PROLOGUE# 0
	save %sp,-112,%sp
	!#PROLOGUE# 1
	st %g2,[%fp-12]
.stabn 68,0,12,LM2
LM2:
	ta 3
	ld [%fp-16],%o0
	add %o0,8,%o1
	mov %o1,%fp
	sethi %hi(L6),%o1
	or %o1,%lo(L6),%o0
	ld [%fp-20],%fp
	ld [%fp-12],%g2
	jmp %o0+0
	restore

but optimized (-O1),

	.align 4
	.type	 __fail.4,@function
	.proc	020
__fail.4:
.stabn 68,0,12,LM1
LM1:
	!#PROLOGUE# 0
	save %sp,-112,%sp
	!#PROLOGUE# 1
	st %g2,[%fp-12]
	ta 3
	add %g2,8,%fp
	sethi %hi(L6),%o0
	or %o0,%lo(L6),%o0
	ld [%fp-16],%fp
	jmp %o0+0
	restore

Note that it appears that %fp should be loaded with 8 more than %g2 on
entry (since that's what the optimized - working - code does), but in
the unoptimized version, %g2 is stored to %fp-12 but the code that sets
%fp uses a value loaded from %fp-16.  The difference between %fp-20 and
%fp-16 later also looks suspicious, as if the compiler had managed to
get confused by 4 bytes about stackframe offsets.  (Note that when the
unoptimized code reloads %g2 before the jump, it loads it from the
correct place.)  Using -dapA and looking at the .rtl file with
optimization on and off makes me think the problem is arising very
early, since it looks to me as though the RTL is wrong even by the time
the .rtl file is dumped.  However, I'm not familiar enough with RTL to
be sure.

Details: I discovered this on NetBSD/sparc (on a SS1+).  I have patched
the compiler (to add -Wmissing-init and -Wno-missing-init), but after
reporting the trouble on the port-sparc list I received two independent
reports of others seeing the same behavior.  Additionally, one person
says it "[d]oesn't seem NetBSD-specific", apparently after trying it on
a Solaris 2.5 machine.  The compiler I discovered it on identifies
itself as "gcc version egcs-2.91.60 19981201 (egcs-1.1.1 release)"; the
last-mentioned confirmation says (in part)

	kauri:~ 6> gcc -v
	Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.5/egcs-2.91.66/specs
	gcc version egcs-2.91.66 19990314 (egcs-1.1.2 release)
	kauri:~ 7> uname -a
	SunOS kauri 5.5 Generic_103093-12 sun4m sparc SUNW,SPARCstation-20

The test program I've been using (and posted to the lists and therefore
presumably what the other people have been using), in full, is

	#include <stdio.h>
	
	static void (*failfn)(void);
	
	#define FAIL ((*failfn)())
	
	static int wrap(void (*fn)(unsigned char), unsigned char arg)
	{
	 __label__ fail;
	
	 static void _fail(void)
	  { goto fail;
	  }
	
	 if (0)
	  {
	fail:;
	    return(0);
	  }
	 failfn = &_fail;
	 (*fn)(arg);
	 return(1);
	}
	
	static void testfn(unsigned char x)
	{
	 if (x != 0) FAIL;
	}
	
	int main(void);
	int main(void)
	{
	 int v;
	
	 printf("start\n");
	 fflush(stdout);
	 v = wrap(testfn,0);
	 printf("wrap(0) -> %d\n",v);
	 fflush(stdout);
	 v = wrap(testfn,1);
	 printf("wrap(1) -> %d\n",v);
	 fflush(stdout);
	 exit(0);
	}

I've been calling it egcs-bug.c; the above report implies the person
called it z.c - I suspect the name is irrelevant.  When compiled
without optimization, I see

	% ./egcs-bug
	start
	wrap(0) -> 1
	Segmentation fault (core dumped)
	% 

(some reports show "Bus error" instead).  With optimization, or with
pre-egcs (2.7.2.2-based) gcc, I get

	% ./egcs-bug
	start
	wrap(0) -> 1
	wrap(1) -> 0
	% 

I can supply more details, up to and including .s, .i, .c.rtl, etc,
files, if they'll help.  I tried looking at the files in config/sparc
but rapidly got very lost, since I've never had occasion to learn
anything about gcc machine descriptions before.

					der Mouse

			       mouse@rodents.montreal.qc.ca
		     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B


More information about the Gcc-bugs mailing list