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:

[bernard@linuxbf2 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
[bernard@linuxbf2 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 ;
[bernard@linuxbf2 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
[bernard@linuxbf2 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
[bernard@linuxbf2 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:

[bernard@linuxbf2 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
[bernard@linuxbf2 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
[bernard@linuxbf2 tmp]$ avr-objdump -d prg.elf
...snip...

0000003c <f>:
3c:89 2borr24, r25
3e:39 f4brne.+14; 0x4e <__SREG__+0xf>
40:81 e0ldir24, 0x01; 1
42:90 e0ldir25, 0x00; 0
44:90 93 61 00 sts0x0061, r25
48:80 93 60 00 sts0x0060, r24
4c:08 95ret
4e:10 92 61 00 sts0x0061, r1
52:10 92 60 00 sts0x0060, r1
56:08 95ret

00000058 <main>:
58:81 e0ldir24, 0x01; 1
5a:80 93 60 00 sts0x0060, r24
5e:81 e0ldir24, 0x01; 1
60:90 e0ldir25, 0x00; 0
62:ec dfrcall.-40; 0x3c <f>
64:08 95ret

...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

_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list

Reply via email to