This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[csl-arm] TLS base corrupted before use
- From: Paul Brook <paul at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 30 Aug 2005 18:08:59 +0100
- Subject: [csl-arm] TLS base corrupted before use
The TLS base register can get corrupted before use when a thread local
variable is used in a function argument.
arm_load_tp uses r0 directly for the TLS base register. This value can then
get corrupted (eg. by setting up annother function argument) before it is
used. We need to use the r0 in the load_tp_soft insn otherwise sched1 can
move the insn somewhere inconvenient, and reload is unable to spill r0. This
is gcc.dg/tls/opt-5.c
The attached patch fixes this by copying the tls base into a pseudo. In most
cases this copy will be optimized away, giving the same code as before.
For example:
int __thread i;
void foo()
{
bar(0, i);
}
Before the patch wwe get:
ldr r3, .L2
mov r0, #0
ldr r1, [r0, r3]
bl bar
With the patch we get:
bl __aeabi_read_tp @ load_tp_soft
mov r2, r0
ldr r3, .L2
mov r0, #0
ldr r1, [r2, r3]
bl bar
Tested with cross to arm-none-eabi.
Applied to csl-arm-branch.
Paul
2005-08-30 Paul Brook <paul@codesourcery.com>
* config/arm/arm.c (arm_load_tp): Copy result to pseudo.
Index: gcc/config/arm/arm.c
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.303.2.88
diff -u -p -r1.303.2.88 arm.c
--- gcc/config/arm/arm.c 12 Aug 2005 15:31:02 -0000 1.303.2.88
+++ gcc/config/arm/arm.c 30 Aug 2005 16:57:24 -0000
@@ -3925,20 +3925,25 @@ get_tls_get_addr (void)
static rtx
arm_load_tp (rtx target)
{
+ if (!target)
+ target = gen_reg_rtx (SImode);
+
if (TARGET_HARD_TP)
{
/* Can return in any reg. */
- if (!target)
- target = gen_reg_rtx (SImode);
-
emit_insn (gen_load_tp_hard (target));
}
else
{
/* Always returned in R0 */
- target = gen_rtx_REG (SImode, 0);
-
- emit_insn (gen_load_tp_soft (target));
+ rtx tmp;
+
+ /* Use a hard reg to avoid aborts in reload. See gcc.dg/opt-5.c */
+ tmp = gen_rtx_REG (SImode, 0);
+ emit_insn (gen_load_tp_soft (tmp));
+ /* Copy the result into a pseudo, otherwise other uses of r0
+ (eg. setting up function arguments) may clobber the value. */
+ emit_move_insn (target, tmp);
}
return target;
}