cgcc

Global register variables in gcc


Recently I was asked about global register variables in an interview.I messed up saying that any global variable will be stored in Data segment.But then i was asked about GCC.After interview i came to conclusion that gcc supports global register variables.

#include<stdio.h>

register int var asm("ebx");  //storing global variable in register explicitly

int main(void)
{
.......
}

Here is link https://gcc.gnu.org/onlinedocs/gcc/Global-Reg-Vars.html#Global-Reg-Vars

But now i am confused about its lifetime and scope and whether it will work as normal global variable or as register variable? Also is there any method or some command on gcc so that we will be sure that compiler will not simply ignore register keyword and will be stored in actual register?


Solution

  • As a number of people have pointed out, reserving a register globally is generally a bad idea. I believe the original intent here was (from the docs):

    This may be useful in programs such as programming language interpreters that have a couple of global variables that are accessed very often.

    Whether this is really useful, or just ends up making things worse can probably only be determined for specific cases. In your case (interview question), that isn't really important.

    The scope of a declaration like this is everything that sees the declaration, just as you would expect with any global declaration.

    However, implementation is a bit tricky. Again, quoting from the docs:

    Defining a global register variable in a certain register reserves that register entirely for this use, at least within the current compilation. The register is not allocated for any other purpose in the functions in the current compilation, and is not saved and restored by these functions.

    So, all code that is COMPILED using that declaration will reserve the register for that use. However, if you LINK to other code that was not compiled with this reservation, it will not be reserved for that purpose.

    The docs give an excellent example with qsort. If your code is compiled with this declaration, and then it calls qsort from the c runtime (which presumably isn't compiled with this declaration), and then qsort calls back into your code (for the compare function), the callback can't be sure that qsort doesn't stomp on the register before calling your compare function.

    How can this ever work if calling any library function can stomp on the register? Again from the docs:

    Choose a register that is normally saved and restored by function calls on your machine, so that library routines will not clobber it.

    Even at that:

    It is not safe to access the global register variables from signal handlers, or from more than one thread of control, because the system library routines may temporarily use the register for other things (unless you recompile them specially for the task at hand).

    As for the last part of your question:

    compiler will not simply ignore register keyword and will be stored in actual register

    I'm not sure what you mean. If (somehow) the compiler ignored the asm("ebx"), then it would NOT be stored in a register. The whole point of using this is to ensure that var is stored in the actual ebx register.