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