cmd/9g: don't use R13

R13 is the C TLS pointer.  Once we're calling to and from C code, if
we clobber R13 in our code, sigtramp won't know whether to get the
current g from REGG or from C TLS.  The simplest solution is for Go
code to preserve the C TLS pointer.  This is equivalent to what other
platforms do, except that on other platforms the TLS pointer is in a
special register.

Change-Id: I076e9cb83fd78843eb68cb07c748c4705c9a4c82
Reviewed-on: https://go-review.googlesource.com/2007
Reviewed-by: Minux Ma <minux@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
Austin Clements 2014-12-16 13:52:09 -05:00
parent db923390a0
commit bbd2127909
3 changed files with 11 additions and 3 deletions

View file

@ -262,8 +262,15 @@ afunclit(Addr *a, Node *n)
static int resvd[] =
{
REGZERO,
REGSP, // reserved for SP, XXX: not reserved in 9c.
30, // for g
REGSP, // reserved for SP
// We need to preserve the C ABI TLS pointer because sigtramp
// may happen during C code and needs to access the g. C
// clobbers REGG, so if Go were to clobber REGTLS, sigtramp
// won't know which convention to use. By preserving REGTLS,
// we can just retrieve g from TLS when we aren't sure.
REGTLS,
// TODO(austin): Consolidate REGTLS and REGG?
REGG,
REGTMP, // REGTMP
FREGCVI+NREG,
FREGZERO+NREG,

View file

@ -185,7 +185,7 @@ regopt(Prog *firstp)
}
// Exclude registers with fixed functions
regbits = (1<<D_R0)|RtoB(REGSP)|RtoB(REGG);
regbits = (1<<D_R0)|RtoB(REGSP)|RtoB(REGG)|RtoB(REGTLS);
// Also exclude floating point registers with fixed constants
regbits |= FtoB(D_F0+27)|FtoB(D_F0+28)|FtoB(D_F0+29)|FtoB(D_F0+30)|FtoB(D_F0+31);
externs = zbits;

View file

@ -48,6 +48,7 @@ enum
REGRT2 = 4, /* reserved for runtime, duffcopy */
REGMIN = 7, /* register variables allocated from here to REGMAX */
REGENV = 11, /* environment for closures */
REGTLS = 13, /* C ABI TLS base pointer */
REGMAX = 27,
REGEXT = 30, /* external registers allocated from here down */
REGG = 30, /* G */