This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
gcc-2.95.2 breaks SPARC V8 and V9 ABI
- To: gcc at gcc dot gnu dot org, gcc-bugs at gcc dot gnu dot org
- Subject: gcc-2.95.2 breaks SPARC V8 and V9 ABI
- From: "M.E. O'Neill" <oneill at cs dot sfu dot ca>
- Date: Thu, 2 Mar 2000 15:13:30 -0800
Currently gcc-2.95.2 (and earlier gcc versions) violate the SPARC
System V ABI. The violation is subtle enough that most people aren't
bitten by it, and so it has remained, largely unexamined and uncorrected,
for several years (perhaps since gcc's very beginnings).
The violations I'm concerned with relate to incorrect use of the SPARC's
global registers, and in particular the registers that are ``reserved
for applications''. For the most part (i.e., 32-bit code), the compiler
itself gets things right -- it's the way the library code (e.g., libgcc.a
and gmon.o) are built that violates the ABI because it dares to use
these registers, when the ABI clearly states:
Software outside the control of the application (including
[system libraries]) should not modify [application] registers
at any time.
The fix is very easy: make sure that when gcc builds these libraries
on SPARC, it compiles them with -mno-app-regs. I've been fixing it by
hand on my installs of gcc for a while now, but I figure a proper patch
would only be a couple of minutes work for someone who knew the right
place to put it (which isn't me -- I hand edit several spots in the
Makefiles).
BTW, I don't think there's any need to get extravagant and have one
version of libgcc where these registers are used and one where they
aren't. In my experience, the fix seems to exact zero cost on generated
code -- since SPARCs are not particularly register-starved, avoiding
these few registers in libgcc doesn't make any noticeable difference.
There may also be another ABI violation when generating application code
using ``-v9 -m64'' to generate SPARC V9 64-bit code. According to the
ABI, if the application uses the global registers %g2 and %g3 for any
purpose, it must declare that it does so using a symbol table definition.
I don't think gcc does this (but I can't check that myself because -m64
on my gcc tells me ``-m64 is not supported by this configuration'').
The roles of the SPARC global registers in the SPARC ABI are specified
follows (if you're familiar with gcc/config/sparc/sparc.h, this should
look pretty familiar):
SPARC V8 ABI (3rd Edition)
g0 Always zero
g1 Temporary, smashed across function calls
g2-g4 Up to gcc to choose use (as temporary, call saved, or fixed)
if compiling application code, but can't touch if compiling
system libraries.
g5-g7 System registers, must not touch
SPARC V9 64-bit ABI (SCD 2.4.1) [non-embedded]
g0 Always zero
g1 Temporary, smashed across function calls (may be smashed just by
the `call' instruction itself if the call is to an external
function (one that goes through PLT))
g2-g3 Up to gcc to choose use (as temporary, call saved, or fixed)
if compiling application code, but can't touch if compiling
system libraries.
g4 Temporary, smashed across function calls
g5 Temporary, smashed across function calls (may be smashed just by
the `call' instruction itself if the call is to an external
function (one that goes through PLT))
g6-g7 System registers, must not touch
When we fix this bug, we should also update the ``gcc extensions''
documentation describing use of global registers, since it reads:
| On the Sparc, there are reports that g3 ... g7 are suitable registers,
| but certain library functions, such as `getwd', as well as the
| subroutines for division and remainder, modify g3 and g4. g1 and
| g2 are local temporaries.
(Incidentally, quite a number of people [e.g., the authors of the Cilk
parallel language that relies heavily on gcc] have taken this bad advice
and used registers like g5 as a global register. This is a highly
dangerous proposition since there is no guarantee on either V8 or V9
that g5 will be preserved -- and in V8, it is a violation of the ABI to
write to this register. Unfortunately, with a stock gcc the lower-numbered
global registers they *should* be using are smashed by code in the gcc
libraries).
I've enclosed quotes from and references to relevant ABI definitions.
Comments, patches, etc. welcome...
M.E.O.
Reference Material
==================
SPARC V8 / 32-bit
-----------------
For SPARC V8, the System V Application Binary Interface, SPARC Processor
Supplement, Third Edition (<http://www.sparc.com/standards/psABI3rd.ps.Z>)
defines the ABI. It summarizes the global registers in Figure 3-15:
| Name Usage
| %g7 / %r7 global 7 (reserved for system)
| %g6 / %r6 global 6 (reserved for system)
| %g5 / %r5 global 5 (reserved for system)
| %g4 / %r4 global 4 (reserved for application)
| %g3 / %r3 global 3 (reserved for application)
| %g2 / %r2 global 2 (reserved for application)
| %g1 / %r1 global 1 (**)
| %g0 / %r0 0
|
| NOTE. Registers marked * above are assumed to be preserved across a
| function call. Registers marked ** above are assumed to be
| destroyed (volatile) across a function call.
Since g2-g4 are not marked with * or ** and are reserved for the
application, it is unspecified whether they should be preserved across
calls or not.
Later (on page 3-13) the specification goes into more detail and states
that how these registers are used is up to the compilation system (in
our case gcc), but also states that that system libraries cannot use
application registers:
| %g0 and %g1 Global integer registers 0 and 1 have no specified role in the
| standard calling sequence.
| %g2,%g3,%g4 Global integer registers 2, 3, and 4 are reserved for the
| application software. System software (including the libraries
| described in Chapter 6) preserves these registers values for
| the application. Their use is intended to be controlled by the
| compilation system and must be consistent throughout the
| application.
| %g5,%g6,%g7 Global integer registers 5, 6, and 7 are reserved for system
| software. Because system software provides the low-level
| operating system interface, including signal handling, an
| application cannot change the registers and safely preserve
| the system values, even by saving and restoring them across
| function calls. Therefore, application software must not
| change these registers values.
SPARC V9 / 64-bit
-----------------
For SPARC V9 code, the ABI definition is found in the SPARC Compliance
Definition 2.4.1 (<http://www.sparc.com/standards/SCD.2.4.1.ps.Z>). The
relevant section is on page 3P-10, and reads:
| %g0 Global register 0 has no specified role in the standard
| calling sequence.
| %g1,%g4,%g5 Global registers 1, 4, and 5 have no specified role in the
| standard calling sequence. They are assumed volatile across
| function calls. In addition, registers %g1 and %g5 are
| volatile between caller and callee if the call is to an
| external function (goes through PLT).
| %g2, %g3 Global registers 2 and 3 are reserved for the application
| software. Software outside the control of the application
| (including the libraries described in Chapter 6) should not
| modify these registers at any time. Software that uses these
| registers must indicate how it has used them; see Symbol Table
| in Chapter 4 for details. (Note: in a multi-threaded
| environment, these registers are thread-local. System libraries
| that implement thread-switching must save and restore these
| registers on a thread switch.)
| %g6 and %g7 Global registers 6 and 7 are reserved for system software.
The SCD's 64-bit API (on pages 4P-3 to 4P-4) also demands that if %g2
and %g3 *are* used by any object file, the object file *must* use a
symbol declaration of type STT_SPARC_REGISTER. The definition states:
| Absence of [a symbol table] entry for a particular global register
| means that the particular global register is not used at all by the
| object. An object that uses one or more of the application-reserved
| global registers but does not indicate this with an appropriate
| symbol-table entry does not conform to the 64-bit ABI.