This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[ARM] Fix register r3 wrongly used to save ip in nested APCS frame


Hi,

in case the ip register needs to be saved before establishing an APCS frame, 
i.e. when it is used as the static chain register, the prologue tries various 
tricks in the following order:

	       1. The last argument register r3.
	       2. A slot on the stack above the frame.  (This only
	          works if the function is not a varargs function).
	       3. Register r3 again, after pushing the argument registers
	          onto the stack.

#3 doesn't really work since its implementation reads:

	    {
	      /* Store the args on the stack.  */
	      if (cfun->machine->uses_anonymous_args)
		insn = emit_multi_reg_push
		  ((0xf0 >> (args_to_push / 4)) & 0xf);
	      else
		insn = emit_insn
		  (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
			       GEN_INT (- args_to_push)));

	      RTX_FRAME_RELATED_P (insn) = 1;

	      saved_pretend_args = 1;
	      fp_offset = args_to_push;
	      args_to_push = 0;

	      /* Now reuse r3 to preserve IP.  */
	      emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx);
	    }

It works only if cfun->machine->uses_anonymous_args is true, because in this 
case r3 is pushed onto the stack as part of the multi-reg push.  Otherwise, 
the contents of r3 are simply overwritten by the last line.

Fixed by saving ip on the stack in this latter case, using one of the slots to 
be used by the pushed arguments.  This eliminates the last ACATS failures on 
ARM/VxWorks.  OK for the mainline?


2013-09-05  Eric Botcazou  <ebotcazou@adacore.com>

	* config/arm/arm.c (arm_expand_prologue): In a nested APCS frame with
	arguments to push onto the stack and no varargs, save ip into a stack
	slot if r3 isn't available on entry.


-- 
Eric Botcazou
Index: config/arm/arm.c
===================================================================
--- config/arm/arm.c	(revision 202160)
+++ config/arm/arm.c	(working copy)
@@ -18209,11 +18209,13 @@ arm_expand_prologue (void)
 	     whilst the frame is being created.  We try the following
 	     places in order:
 
-	       1. The last argument register r3.
-	       2. A slot on the stack above the frame.  (This only
-	          works if the function is not a varargs function).
+	       1. The last argument register r3 if it is available.
+	       2. A slot on the stack above the frame if there are no
+		  arguments to push onto the stack.
 	       3. Register r3 again, after pushing the argument registers
-	          onto the stack.
+	          onto the stack, if this is a varargs function.
+	       4. A slot on the stack created for the arguments to push,
+		  if this isn't a varargs function.
 
 	     Note - we only need to tell the dwarf2 backend about the SP
 	     adjustment in the second variant; the static chain register
@@ -18244,21 +18246,25 @@ arm_expand_prologue (void)
 	    {
 	      /* Store the args on the stack.  */
 	      if (cfun->machine->uses_anonymous_args)
-		insn = emit_multi_reg_push
-		  ((0xf0 >> (args_to_push / 4)) & 0xf);
+		{
+		  insn
+		    = emit_multi_reg_push ((0xf0 >> (args_to_push / 4)) & 0xf);
+		  emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx);
+		  saved_pretend_args = 1;
+		}
 	      else
-		insn = emit_insn
-		  (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-			       GEN_INT (- args_to_push)));
+		{
+		  rtx x = plus_constant (Pmode, stack_pointer_rtx,
+					 args_to_push - 4);
+		  insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
+						stack_pointer_rtx,
+						GEN_INT (- args_to_push)));
+		  emit_set_insn (gen_frame_mem (SImode, x), ip_rtx);
+		}
 
 	      RTX_FRAME_RELATED_P (insn) = 1;
-
-	      saved_pretend_args = 1;
 	      fp_offset = args_to_push;
 	      args_to_push = 0;
-
-	      /* Now reuse r3 to preserve IP.  */
-	      emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx);
 	    }
 	}
 
@@ -18363,7 +18369,7 @@ arm_expand_prologue (void)
 	      /* Recover the static chain register.  */
 	      if (!arm_r3_live_at_start_p () || saved_pretend_args)
 		insn = gen_rtx_REG (SImode, 3);
-	      else /* if (crtl->args.pretend_args_size == 0) */
+	      else
 		{
 		  insn = plus_constant (Pmode, hard_frame_pointer_rtx, 4);
 		  insn = gen_frame_mem (SImode, insn);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]