Two fixes for -fsplit-stack on powerpc64.  I goofed on the block
scanned for uses of r12.  ENTRY_BLOCK_PTR_FOR_FN is the fake one.  The
next block is the first one having insns.

The second change emits an error if people use a global register
variable r29 with -fsplit-stack.  For example:
register struct important_stuff *quick_access __asm__ ("r29");

Such code does exist in the wild, but probably doesn't currently use
-fsplit-stack.

The problem is that r29 is saved by morestack then used to pass the
old stack pointer to the normal function prologue.  So on entry to a
function, r29 will be modified.  It would be possible to restore r29
from the morestack frame in order to let the function body see the
original r29, I wrote such a patch, but that trick isn't safe if
someone is using r29 in a signal handler.

I suppose we could restore r29 and downgrade the error to a warning
that using a global register asm r29 isn't safe in signal handlers
with -fsplit-stack.  What do you think, David?

        * config/rs6000/rs6000.c (split_stack_arg_pointer_used_p): Scan
        correct block for use of r12.
        (rs6000_expand_split_stack_prologue): Error on r29 asm global reg.

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 223857)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -23450,7 +23450,7 @@ split_stack_arg_pointer_used_p (void)
   /* Unfortunately we also need to do some code scanning, since
      r12 may have been substituted for the pseudo.  */
   rtx_insn *insn;
-  basic_block bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
+  basic_block bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
   FOR_BB_INSNS (bb, insn)
     if (NONDEBUG_INSN_P (insn))
       {
@@ -25942,6 +25942,13 @@ rs6000_expand_split_stack_prologue (void)
   if (!info->push_p)
     return;
 
+  if (global_regs[29])
+    {
+      error ("-fsplit-stack uses register r29");
+      inform (DECL_SOURCE_LOCATION (global_regs_decl[29]),
+             "conflicts with %qD", global_regs_decl[29]);
+    }
+
   allocate = info->total_size;
   if (allocate > (unsigned HOST_WIDE_INT) 1 << 31)
     {

-- 
Alan Modra
Australia Development Lab, IBM

Reply via email to