[comp.sys.amiga.tech] Another Manx v3.6 bug

ehoogerbeets@rose.waterloo.edu (Edwin Hoogerbeets) (06/10/89)

In article <14328@watdragon.waterloo.edu> ehoogerbeets@rose.waterloo.edu (Edwin Hoogerbeets) writes:
% I know it is pretty gross
% C code, but it occurs in GnuGrep (fish 204), and probably other Gnu
% code.

Speaking of Gnu code, here is another Manx bug:

main()
{
  char *list;
  char c;

  c = '8';

  list = &c;

  c = ( list , *list );
}

Causes guru 0x00000003, unaligned word or address error.
(It is valid, albeit strange, C code isn't it?)

Looking at the assembler:

[...etc...]
;  c = '8';
	move.b	#56,-5(a5)
;
;  list = &c;
	lea	-5(a5),a0         ; load the effective address of c into a0
	move.l	a0,-4(a5)     ; save that address in list
;
;  c = ( list , *list );
	move.l	-4(a5),a0     ; [redundantly] get the address again
	move.b	(a0),d0       ; move c into d0
	ext.w	d0              ; sign extend it to a word  [?????]
	move.w	d0,-5(a5)     ; Whoops! This is a no no!
;}

The assembler produced by compiling with +L is the same, except the
offensive lines are:

;  c = ( list , *list );
	move.l	-4(a5),a0     ; [redundantly] get the address again
	move.b	(a0),d0       ; move c into d0
	ext.w	d0              ; sign extend it to a word  [?????]
	ext.l	d0              ; sign extend it to a long  [2*?????]
	move.l	d0,-5(a5)     ; Even better...

Perhaps gnucc should be ported to the Amiga, since presumably it
compiles all the gnu stuff.

Edwin

addison@pollux.usc.edu (Richard Addison) (06/12/89)

In article <14395@watdragon.waterloo.edu> ehoogerbeets@rose.waterloo.edu (Edwin Hoogerbeets) writes:
>In article <14328@watdragon.waterloo.edu> ehoogerbeets@rose.waterloo.edu (Edwin Hoogerbeets) writes:
>% I know it is pretty gross
>% C code, but it occurs in GnuGrep (fish 204), and probably other Gnu
>% code.
> ...
>	ext.w	d0              ; sign extend it to a word  [?????]
> ...
>	ext.w	d0              ; sign extend it to a word  [?????]
>	ext.l	d0              ; sign extend it to a long  [2*?????]

This brings up something that I've always found horribly stupid.  I've seen
C compilers use ext.w (followed by ext.l if ints are long) to test to see if
a char is equal to 0, or to compare two chars, or to add, subtract two chars
when the result will end up in a char.  These are very clearly instances of
unnecessary promotion:  the additional high-order bits will never effect the
lower-order bits.

Caveat:  I haven't been looking as closely at the code generation of the most
current versions of Manx and Lattice because I have the source level debuggers.
I don't know if they are still as weird about this unnecesarry code generation.

Richard Addison
"Jim:  Life is not a dream." -- Spock, Star Trek V:  The Final (?) Frontier

stan@hpcvca.CV.HP.COM (Stan Gibbs) (06/14/89)

In <14395@watdragon.waterloo.edu> ehoogerbeets@rose.waterloo.edu 
  (Edwin Hoogerbeets) writes:

>> Speaking of Gnu code, here is another Manx bug:
>> 
>> main()
>> {
>>   char *list;
>>   char c;
>> 
>>   c = '8';
>> 
>>   list = &c;
>> 
>>   c = ( list , *list );
>> }
>> 
>> [ ... erroneous assembler code ... ]
>> 
>> Edwin

Here's how Lattice 5.02 handles it:

_main 0000-00

SECTION 00 "test.c" 00000020 BYTES
;   1: void
;   2: main()
;   3: {
       | 0000  4E 55 FF FA                    LINK      A5,#FFFA
;   4:   char *list;
;   5:   char c;
;   6:   c = '8';
       | 0004  1B 7C 00 38 FF FB              MOVE.B    #38,FFFB(A5)
;   7:   list = &c;
       | 000A  41 ED FF FB                    LEA       FFFB(A5),A0
       | 000E  2B 48 FF FC                    MOVE.L    A0,FFFC(A5)
;   8:   c = (list,*list);
       | 0012  20 6D FF FC                    MOVEA.L   FFFC(A5),A0
       | 0016  1B 50 FF FB                    MOVE.B    (A0),FFFB(A5)
;   9: }
       | 001A  4E 5D                          UNLK      A5
       | 001C  4E 75                          RTS

Seems much more straight forward.

Stan.

chk@client1.DRETOR.UUCP (C. Harald Koch) (06/16/89)

In article <17762@usc.edu> addison@pollux.usc.edu (Richard Addison) writes:
>This brings up something that I've always found horribly stupid.  I've seen
>C compilers use ext.w (followed by ext.l if ints are long) to test to see if
>a char is equal to 0, or to compare two chars, or to add, subtract two chars
>when the result will end up in a char.  These are very clearly instances of
>unnecessary promotion:  the additional high-order bits will never effect the
>lower-order bits.

The easiest way to handle C expression compilation is to always promote to
the correct size, whether or not it is necessary. It is much more difficult
to make sure that an arbitrary expression doesn't require promotion, so few
compiler writers bother to implement this special case.

Of course, The GNU C compiler probably checks. That monstrosity does
everything short of buying you a new processor to get your code as small and
efficient as possible.

-- 
Grandpa Charnock's Law:	 | C. Harald Koch  NTT Systems, Inc., Toronto, Ontario
You never really learn	 | chk@gpu.utcs.utoronto.ca	   (long-term address)
to swear until you learn | chk@zorac.dciem.dnd.ca	      (my current job)
to drive.		 | chk@chkent.UUCP		    (my AMIGA at home)

darin@nova.laic.uucp (Darin Johnson) (06/17/89)

>Speaking of Gnu code, here is another Manx bug:

Speaking of Manx bugs in 3.6a...  I don't have the example with
me (I can get it if need be) since I have taken a vacation from
that section of code so I can get a fresh perspective.

Anyway, I have a case statement in which the cases get jumpled up!
For example, "switch(DEF1)" will go to "case DEF2:".  I thought my
mind was playing tricks for awhile, but I generated the assembler
output, and sure enough, the jump table has 2 entries swapped out of
order.

Has anyone seen anything like this?  I have tried commenting out
the rest of the cases, but even with just 2 cases, it gets it wrong.
I really would hate having to put in a gob of IF's.
Darin Johnson (leadsv!laic!darin@pyramid.pyramid.com)
	We now return you to your regularly scheduled program.