Gcc/10.2.0/gcc/Global-Register-Variables

From Get docs

6.47.5.1 Defining Global Register Variables

You can define a global register variable and associate it with a specified register like this:

register int *foo asm ("r12");

Here 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 const and 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:

  • If the register is a call-saved register, call ABI is affected: the register will not be restored in function epilogue sequences after the variable has been assigned. Therefore, functions cannot safely return to callers that assume standard ABI.
  • Conversely, if the register is a call-clobbered register, making calls to functions that use standard ABI may lose contents of the variable. Such calls may be created by the compiler even if none are evident in the original program, for example when libgcc functions are used to make up for unavailable instructions.
  • Accesses to the variable may be optimized as usual and the register remains available for allocation and use in any computations, provided that observable values of the variable are not affected.
  • If the variable is referenced in inline assembly, the type of access must be provided to the compiler via constraints (see Constraints). Accesses from basic asms are not supported.

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.

Declaring the variable

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.

Using the variable

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 qsort’s 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 longjmp does.