Re: IAR linker: too smart

Dirk Zabel wrote:
I am using the IAR toolchain for our Renesas M16C based project. The device uses a lot of configuration data which are stored within an eeprom. In order to define the placement, I have something like this:
#pragma dataseg="E2PROM_DATA"
#define extern /* empty */
#include "eeprom.h"
#pragma dataseg=default
/* EOF */
extern __no_init unsigned char MBUS_exist;
extern __no_init char E2_VERSION_TEXT[20];
extern __no_init unsigned char CAN_exists;
extern __no_init unsigned char MBUS_exists;
/* and so on. */
/* EOF */

Any code which uses the preprocessor to redefine a keyword like "extern" is incorrect code. It doesn't matter whether it works or not - it's still so bad that any experienced reviewer would reject it outright.

I tell the linker to place the E2PROM_DATA segment where the eeprom is mapped into the address space and can use the data from other c sources by including eeprom.h
The linker throws away all variables in eeprom.h which are not used anywhere in the projet (there is NO OPTIMIZATION selected!!). This is really bad, since I need a stable address mapping for all configuration data; there might be parameters which may be needed in later software versions; sometimes I build testversions which do not contain all parts. I allways need the variables at the same adresses.

I did already asked the IAR support, but did not get a usable answer (they told me to use volatile, but this does not change anything).

IAR support are not famed for being helpful - on the other hand, their tools are well known for making correct and efficient code. The compiler (and linker) is doing exactly the right thing - if you declare variables that are never used, then the compiler and/or linker is free to remove them - they have no effect on the running of your program. You might think that the declarations have an effect on the addressing in eeprom - but that is not true. The order you declare or define data has no defined effect on the order in memory. For many targets, compilers will re-order the data for better alignment or padding. So even if you manage to persuade the tools to keep the unused data, you are getting a false sense of security - a new compilation could re-arrange the data.

The easiest way to get the effect you are looking for is to define a single structure for all the eeprom-based data, and ensure that it is linked to one specific address (solution "a" below). If you want to access struct members without having to add "s." in front of them, you could use #defines to avoid it (although it is almost certainly best to correct the old code rather than add hacks around it).

Solution (b) would not work (as explained above). Solution (c) is perfectly reasonable (although more effort than (a)), and solution (d) is again possible, but lots of effort to do well.

I see the following approaches:
a) define a big struct which contains all variables and put that struct into E2PROM_DATA
b) put dummy references to all variables into my project
c) define the variables in some assembler source.
d) the IAR toolchain allows to put variables at numerically known addresses, I could place every variable at some pre-calculated address

a) I would have to change all code referring to (say) E2_VERSION_TEXT to s.E2_VERSION_TEXT (where s is the name of the struct variable). Since my project contains lot of old code, this is not very good.
b) ugly, blows up my project with "useless" code (the linker is quite "smart", you have to DO something with a variable or the code is optimized away).
c) ugly and dangerous, I have to keep the assembler definitions and c declarations in sync.
d) IMHO address calculations should be done by tools, not by programmes due to possible errors.

Has anyone some better idea?

Dirk Zabel