You can define a global register variable and associate it with a specified register like this:
register int *foo asm ("r12");
r12 is the name of the register that should be used. Note that this is the same syntax used for defining local register variables, but for a global variable the declaration appears outside a function. The
register keyword is required, and cannot be combined with
static. The register name must be a valid register name for the target platform.
Do not use type qualifiers such as
volatile, as the outcome may be contrary to expectations. In particular, using the
volatile qualifier does not fully prevent the compiler from optimizing accesses to the register.
Registers are a scarce resource on most systems and allowing the compiler to manage their usage usually results in the best code. However, under special circumstances it can make sense to reserve some globally. For example this may be useful in programs such as programming language interpreters that have a couple of global variables that are accessed very often.
After defining a global register variable, for the current compilation unit:
Note that these points only apply to code that is compiled with the definition. The behavior of code that is merely linked in (for example code from libraries) is not affected.
If you want to recompile source files that do not actually use your global register variable so they do not use the specified register for any other purpose, you need not actually add the global register declaration to their source code. It suffices to specify the compiler option -ffixed-reg (see Code Gen Options) to reserve the register.
Global register variables cannot have initial values, because an executable file has no means to supply initial contents for a register.
When selecting a register, choose one that is normally saved and restored by function calls on your machine. This ensures that code which is unaware of this reservation (such as library routines) will restore it before returning.
On machines with register windows, be sure to choose a global register that is not affected magically by the function call mechanism.
When calling routines that are not aware of the reservation, be cautious if those routines call back into code which uses them. As an example, if you call the system library version of
qsort, it may clobber your registers during execution, but (if you have selected appropriate registers) it will restore them before returning. However it will not restore them before calling
qsorts comparison function. As a result, global values will not reliably be available to the comparison function unless the
qsort function itself is rebuilt.
Similarly, it is not safe to access the global register variables from signal handlers or from more than one thread of control. Unless you recompile them specially for the task at hand, the system library routines may temporarily use the register for other things. Furthermore, since the register is not reserved exclusively for the variable, accessing it from handlers of asynchronous signals may observe unrelated temporary values residing in the register.
On most machines,
longjmp restores to each global register variable the value it had at the time of the
setjmp. On some machines, however,
longjmp does not change the value of global register variables. To be portable, the function that called
setjmp should make other arrangements to save the values of the global register variables, and to restore them in a
longjmp. This way, the same thing happens regardless of what