This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Register constrained variable issue
- From: ZoltÃn KÃcsi <zoltan at bendor dot com dot au>
- To: gcc at gcc dot gnu dot org
- Date: Thu, 13 Oct 2011 18:26:02 +1100
- Subject: Register constrained variable issue
If one writes a bit of code like this:
int foo( void )
{
register int x asm( "Rn" );
asm volatile ( "INSN_A %0 \n\t" : "=r" (x) );
bar();
asm volatile ( "INSN_B %0,%0 \n\t" : "=r" (x) : "0" (x) );
return x;
}
and Rn is a register not saved over function calls, then gcc does not save it
but allows it to get clobbered by the calling of bar(). For example, if the
processor is ARM and Rn is r2 (on ARM r0-r3 and r12 can get clobbered by a
function call), then the following code is generated; if you don't know ARM
assembly, comments tell you what's going on:
foo:
stmfd sp!, {r3, lr} // Save the return address
INSN_A r2 // The insn generating r2's content
bl bar // Call bar(); it may destroy r2
INSN_B r2, r2 // *** Here a possibly clobbered r2 is used!
mov r0, r2 // Copy r2 to the return value register
ldmfd sp!, {r3, lr} // Restore the return address
bx lr // Return
Note that you don't need a real function call in your code, it is enough if
you do something which forces gcc to call a function in libgcc.a. On some ARM
targets a long long shift or an integer division or even just a switch {}
statement is enough to trigger a call to the support library.
Which basically means that one *must not* allocate a register not saved by
function calls because then they can get clobbered at any time.
It is not an ARM specific issue, either; other targets behave the same. The
compiler version is 4.5.3.
The info page regarding to specifying registers for variables does not say
that the register one chooses must be a register saved across calls. On the
other hand, it does say that register content might be destroyed when the
compiler knows that the data is not live any more; a statement which has a
vibe suggesting that the register content is preserved as long as the data is
live.
For global register variables the info page does actually warn about library
routines possibly clobbering registers and says that one should use a saved
and restored register. However, global and function local variables are very
different animals; global regs are reserved and not tracked by the data flow
analysis while local var regs are part of the data flow analysis, as stated
by the info page.
So I don't know if it is a bug (i.e. the compiler is supposed to protect local
reg vars) or just misleading/omitted information in the info page?
Thanks,
Zoltan