avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-gcc-list] avr-gcc 4.3.3 : enum definition/use order has side effect


From: Bernard Fouché
Subject: [avr-gcc-list] avr-gcc 4.3.3 : enum definition/use order has side effects on -fshort-enums
Date: Wed, 15 Jun 2011 11:37:32 +0200
User-agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2.17) Gecko/20110414 Lightning/1.0b2 Thunderbird/3.1.10

Hi List.

When using -fshort-enums, the definition of the enumeration relative to the place where the enumeration is referenced gives different memory allocation sizes for the enum. When linking different objects, one may have a program using different width for the same variable.

Here is an example:

address@hidden tmp]$ cat enum.c
cat enum.c
#ifdef BEFORE
enum xyz xyz;
#endif

enum xyz {
  XYZ_1,
  XYZ_2
};

#ifdef AFTER
enum xyz xyz;
#endif
address@hidden tmp]$ avr-gcc -DBEFORE -Os -fshort-enums enum.c -c -o before.o ; avr-gcc -DAFTER -Os -fshort-enums enum.c -c -o after.o ;
avr-gcc -DBEFORE -Os -fshort-enums enum.c -c -o before.o ; avr-gcc -DAFTER -Os -fshort-enums enum.c -c -o after.o ;
address@hidden tmp]$ avr-nm before.o
avr-nm before.o
00000034 a __CCP__
0000003e a __SP_H__
0000003d a __SP_L__
0000003f a __SREG__
         U __do_clear_bss
00000000 a __tmp_reg__
00000001 a __zero_reg__
00000002 C xyz
address@hidden tmp]$ avr-nm after.o
avr-nm after.o
00000034 a __CCP__
0000003e a __SP_H__
0000003d a __SP_L__
0000003f a __SREG__
         U __do_clear_bss
00000000 a __tmp_reg__
00000001 a __zero_reg__
00000001 C xyz
address@hidden tmp]$


In the first case, the enumeration is referenced before the enumeration definition: 'xyz' is sizeof(int) bytes wide, while in the second case, the enumeration is first defined and 'xyz' is one byte wide since the compiler can see that the enumerated values fit in one byte.

I have no version of avr-gcc at hand to test this on more recent releases of avr-gcc (I'd like to know what happens with '-lto'). The optimization level does not change anything (I tested -Os, -O0, -O1, -O2, -O3).

Then I tried:

address@hidden tmp]$ cat enum.c
#ifdef BEFORE
enum xyz xyz;
#endif

enum xyz {
  XYZ_1,
  XYZ_2
};

#ifdef AFTER
extern enum xyz xyz;
int main(int argc, char **argv)
{
  xyz=XYZ_2;
  f(xyz);
}
#else
void f(enum xyz x)
{
  if(x==XYZ_1)
    xyz=XYZ_2;
  else
    xyz=XYZ_1;
}
#endif
address@hidden tmp]$ avr-gcc -DBEFORE -Os -fshort-enums enum.c -c -o before.o ; avr-gcc -DAFTER -Os -fshort-enums enum.c -c -o after.o ; avr-gcc -fshort-enums before.o after.o -o prg.elf
address@hidden tmp]$ avr-objdump -d prg.elf
...snip...

0000003c <f>:
  3c: 89 2b             or    r24, r25
  3e: 39 f4             brne  .+14        ; 0x4e <__SREG__+0xf>
 
40: 81 e0             ldi   r24, 0x01   ; 1
  42: 90 e0             ldi   r25, 0x00   ; 0
 
44: 90 93 61 00       sts   0x0061, r25
  48: 80 93 60 00       sts   0x0060, r24
  4c: 08 95             ret
  4e: 10 92 61 00       sts   0x0061, r1
  52: 10 92 60 00       sts   0x0060, r1
 
56: 08 95             ret

00000058 <main>:
  58: 81 e0             ldi   r24, 0x01   ; 1
 
5a: 80 93 60 00       sts   0x0060, r24
  5e: 81 e0             ldi   r24, 0x01   ; 1
  60: 90 e0             ldi   r25, 0x00   ; 0
  62: ec df             rcall .-40        ; 0x3c <f>
  64: 08 95             ret

...snip...
 
f() considers that 'xyz' is 2 bytes wide, while main() accesses it as a single byte. I dunno if this is considered to be a bug but if not then some documentation about this seems necessary.

    Bernard


reply via email to

[Prev in Thread] Current Thread [Next in Thread]