[gnu.gcc.bug] gcc 1.30 bug

waynec@UUNET.UU.NET (10/23/88)

I have found a problem with version 1.30 of gcc.  It occurs when
trying to build the i386v  (386, system V) compiler, on a 386 system
running Unix 386, System V, Release 3.2.
(I have previously built a working 1.28 compiler on this system; the
bug has appeared since then.  I haven't snagged 1.29 to see if it
exists on that version.)

The problem occurs when attempting to use the stage1 compiler (built
by the att 386 compiler) to compile gcc:
	make CC=stage1/gcc CFLAGS="-g -O -Bstage1/"
The file insn-output.c cannot be compiled.  Examination of
insn-output.c shows that it has garbage.  The reason it has  garbage
is that genoutput is bad.  Further checking showed that version 1.30
was compiling a bad genoutput.o.  Compiling genoutput.c with gcc 1.28
yielded a genoutput which was able to build a correct insn-output.c.
I compiled genoutput.c
with the 1.28 compiler and the stage1 1.30 compiler (-O in both cases;
without -O there is no problem).  When I compared the assembler
output, I noticed three code differences.  Two were benign, but the
third was incorrect code.  It occured in the following code at the end
of the function  gen_insn(), in genoutput.c:

	{
	  register char *cp = &(XSTR (insn, 3)[1]);
	  while (*cp) putchar (*cp++);
	  putchar ('\n');
	}
	printf ("}\n");

The offending code is in the while line, in the putchar(*cp++)
statement.  In <stdio.h> on this system,
we have the following definitions:

#define putchar(x)	putc((x), stdout)
#define putc(x, p)	(--(p)->_cnt < 0 ? \
			_flsbuf((unsigned char) (x), (p)) : \
			(int) (*(p)->_ptr++ = (unsigned char) (x)))

The bad code is in the assignment statement making up the 'false' part
of the ?: conditional expression:
			(int) (*(p)->_ptr++ = (unsigned char) (x)))
which will expand to:
	(int) (*(stdout)->_ptr++ = (unsigned char) (*cp++)))

[Going into the following code, %esi = stdout, %ebx = cp]

gcc 1.28 with -O produced the following code for this statement:

	leal 4(%esi),%eax
	movl (%eax),%ecx
	movl %ecx,%edx
	movb (%ebx),%cl
	movb %cl,(%edx)
	incl %ebx
	incl (%eax)

gcc 1.30 with -O produced the following:

	leal 4(%esi),%eax
	movl (%eax),%ecx
	movl %ecx,-4(%ebp)
	movb (%ebx),%cl
	movb %cl,(%ecx)
	incl %ebx
	incl (%eax)

In gcc 1.30, the  "movb  (%ebx),%cl"  overwrites the pointer which
is then used in the next instruction.

By taking all functions other than gen_insn() out of genoutput.c I was
able to still generate the error.  As suggested by the bug reporting
hints in the documentation, I did not attempt to narrow done the
envelope much further than this;  a few attempts showed that the
presence of the bug depended on the complexity of the surrounding
code.  I am not yet familiar enough with the internals of of gcc to be
able to suggest which of the changes from 1.28 to 1.30 caused the
problem.

If you require further information, please let me know.

[End of bug report.  Beginning of extraneous comments about gcc]:

Despite the bug in 1.30, I have been quite impressed with the 1.28 386
compiler.  Once I faked out an alloca(), it built under the att 386
compiler with no trouble.  My initial measurements show that gcc
(with -O) beats
both the ATT pcc2 386 compiler, and the Microsoft C compiler in terms
of size of code generated, by 10-15%.  I have not measured speed of
the generated code. 
Based on this superiority, I plan to use it as the compiler
for the 386 4.3BSD port that I'm doing as a personal fun project.

[Oh, I also quite agree with the "GNU philosophy", even though my 
employers probably don't.  The newly formed "Business Software
Association", which they have helped form, with the stated purpose
to "combat international software piracy, to promote strong
intellectual property protection,
and to reduce international trade barriers", probably needs to be
opposed.]

Wayne Chapeskie
Microsoft
16011 NE 36th Way, Box 97017, Redmond WA 98073-9717
(206)-882-8080			UUCP:  ...{uw-beaver,uunet}!microsoft!waynec