Why are switch statement tables in section .rodata which gets copied to RAM with avr-gcc?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Why are switch statement tables in section .rodata which gets copied to RAM with avr-gcc?

Peter Sommerlad (C++)
Hi,

as a newbie to AVR programming, I am porting Arduino Core code to modern
C++17. I wanted to get rid of ugly large lookup tables that in PROGMEM
that require separate assembly macro magic to access by normal C++ code.

My naïve assumption was that the compiler-generated tables for switch
statement would end up in flash memory, because they are immutable.

It turns out, that avr-gcc or the linker for the Arduino processor that
I have access to, generate code to copy .rodata to .data in RAM. This is
bad, and may have been the reason for these PROGMEM tables.

For some of the smaller processors the smaller switch statements would
not end up using the table lookup, but especially the ATmega2560 has
dense large number of cases.

Any ideas to circumvent it with standard code?

I am using avr-gcc 9.3.0

Regards
Peter.

--
Peter Sommerlad

Better Software: Consulting, Training, Reviews
Modern, Safe & Agile C++

[hidden email]
+41 79 432 23 32

Reply | Threaded
Open this post in threaded view
|

Re: Why are switch statement tables in section .rodata which gets copied to RAM with avr-gcc?

Matthijs Kooijman
Hi Peter,

> It turns out, that avr-gcc or the linker for the Arduino processor that I
> have access to, generate code to copy .rodata to .data in RAM. This is bad,
> and may have been the reason for these PROGMEM tables.
.rodata is copied to RAM, because flash and RAM are not in the same
address space on AVR. This means that, without special treatment, a
pointer to read-only data will be dereferenced the same as a pointer to
read-write data, reading from RAM, so the compiler has no choice but to
copy rodata to RAM.

To circumvent that, data can be marked with PROGMEM, to instruct the
compiler to leave it it flash, but then it is up to the programmer to
distinguish such pointers and use pgm_read_... functions to read them
from flash instead of RAM.

Having said that: Compiler-generated switch tables (just like
vtables, btw), *could* very well be kept in flash by putting them in an
appropriate section and generating the right code for loading data from
them, but I suspect this simply was not implemented (since this is a
rather specialcase for avr, on most other platforms putting data in
.rodata is sufficient to keep it in flash).

Does this answer your question?

Gr.

Matthijs

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Why are switch statement tables in section .rodata which gets copied to RAM with avr-gcc?

Georg-Johann Lay-2
In reply to this post by Peter Sommerlad (C++)
Am 31.03.20 um 15:50 schrieb Peter Sommerlad (C++):
> Hi,
>
> as a newbie to AVR programming, I am porting Arduino Core code to modern
> C++17. I wanted to get rid of ugly large lookup tables that in PROGMEM
> that require separate assembly macro magic to access by normal C++ code.
>
> My naïve assumption was that the compiler-generated tables for switch
> statement would end up in flash memory, because they are immutable.

A respective patch was effectively rejected, cf.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49857#c17

and the links to the gcc-patches mailing list.  The patch was a no-op
for other targets but required 5 lines of code in the middle-end so
the avr back-end could hook in.  The maintainers didn't understand that
it could not be solved by putting the stuff in an other section and that
it is not possible to unroll generic accesses in the aftermath.

> It turns out, that avr-gcc or the linker for the Arduino processor that
> I have access to, generate code to copy .rodata to .data in RAM. This is
> bad, and may have been the reason for these PROGMEM tables.
>
> For some of the smaller processors the smaller switch statements would
> not end up using the table lookup, but especially the ATmega2560 has
> dense large number of cases.

You can switch it off altogether like with -fno-tree-switch-conversion.

Johann

> Any ideas to circumvent it with standard code?
>
> I am using avr-gcc 9.3.0

Better use v8; it generates better code.

>
> Regards
> Peter.