- avr-gcc -Os: __flash disregarded for some struct array accesses
- At -Os, avr-gcc generates a plain ld (RAM load) instead of lpm (flash load) for the first field of a const __flash-qualified struct array element, while correctly emitting lpm for the second field of the same element. The struct's first field ends up reading garbage off RAM space instead of the intended flash-resident constant.
- Reproduced with:
- - avr-gcc (Gentoo 15.2.1_p20260214 p5) 15.2.1
- - avr-gcc 13.2.1
- - git revision b6825a7ce698b65657e952e437ab9edd655fe5a5 (2026-07-06)
- Not reproduced with -O0, -O1, -O2, only -Os.
- Bug not present in a 2020 build (unknown avr-gcc version).
- Minimal reproduction
- #include <avr/io.h>
- struct pair { unsigned char data; unsigned char cmd; };
- const __flash struct pair table[] = { {0x11, 1}, {0x33, 0}, {0x55,1} };
- void write_data(unsigned char d);
- void write_cmd(unsigned char c);
- void test(void){
- unsigned char i;
- for(i=0; i<3; i++){
- if(table[i].cmd) write_data(table[i].data); else write_cmd(table[i].data);
- }
- }
- Build:
- avr-gcc -Os -mmcu=atmega8 -I/usr/avr/include -S -o test.s test.c
- Relevant output (-Os):
- test:
- push r28
- push r29
- ldi r28,lo8(table)
- ldi r29,hi8(table)
- .L4:
- movw r30,r28
- ld r24,Z+ ; <-- BUG: reads table[i].data from DATA SPACE (SRAM), not flash
- lpm r25,Z ; correct: reads table[i].cmd from flash
- cpi r25,lo8(0)
- breq .L2
- rcall write_data ; called with garbage r24 (SRAM byte at address `table`), not 0x11/0x33/0x55
- .L3:
- adiw r28,2
- ldi r24,hi8(table+6)
- cpi r28,lo8(table+6)
- cpc r29,r24
- brne .L4
- pop r29
- pop r28
- ret
- .L2:
- rcall write_cmd
- rjmp .L3
- A single, non-looping access to the same kind of struct correctly uses lpm at every optimization level tested, so this may be specific to the loop/pointer-increment shape above, not __flash struct access in general:
- struct pair { unsigned char a; unsigned char b; };
- const __flash struct pair table[] = { {0x11, 0x22}, {0x33, 0x44} };
- unsigned char out;
- void test(unsigned char i){
- out = table[i].a; // correctly compiles to lpm at -Os
- }
- Workaround: replace const __flash with PROGMEM, use pgm_read_* for access.
Bez tytułu
z Aqua Kitten, 4 tygodnie temu, napisane w Plain Text, wyświetlone 62 razy.
URL https://pastebin.k4be.pl/view/2f7f901a
Udostępnij
Pobierz wklejkę lub Pokaż surowy tekst
— Rozwiń pełna szerokość przeglądarki