diff mbox

[nios2] stack limit checking improvements

Message ID 55A56388.6040101@codesourcery.com
State New
Headers show

Commit Message

Sandra Loosemore July 14, 2015, 7:31 p.m. UTC
In preparation for some other changes to the Nios II prologue code that 
are in my queue, I've checked in the attached patch to the stack limit 
checking logic.  With this patch, the check generation code now takes an 
offset so that the check can be emitted before the SP adjustment; this 
allows cases where multiple stack adjustments are emitted to do only a 
single stack limit check.

While I was at it, I also added support for -fstack-limit-symbol as well 
as -fstack-limit-register.

-Sandra
diff mbox

Patch

Index: gcc/testsuite/gcc.target/nios2/nios2-stack-check-1.c
===================================================================
--- gcc/testsuite/gcc.target/nios2/nios2-stack-check-1.c	(revision 225722)
+++ gcc/testsuite/gcc.target/nios2/nios2-stack-check-1.c	(working copy)
@@ -1,7 +1,8 @@ 
 /* { dg-do compile } */
 /* { dg-options "-fstack-limit-register=et" } */
-/* { dg-final { scan-assembler "bgeu\\tsp, et" } } */
-/* { dg-final { scan-assembler "trap\\t3" } } */
+/* { dg-final { scan-assembler "bgeu\\tsp, " } } */
+/* { dg-final { scan-assembler "trap\\t3|trap.n\\t3" } } */
+
 /* check stack checking */
 void test()
 {
Index: gcc/testsuite/gcc.target/nios2/nios2-stack-check-2.c
===================================================================
--- gcc/testsuite/gcc.target/nios2/nios2-stack-check-2.c	(revision 225722)
+++ gcc/testsuite/gcc.target/nios2/nios2-stack-check-2.c	(working copy)
@@ -1,7 +1,7 @@ 
 /* { dg-do compile } */
 /* { dg-options " " } */
-/* { dg-final { scan-assembler-not "bgeu\\tsp, et" } } */
-/* { dg-final { scan-assembler-not "break\\t3" } } */
+/* { dg-final { scan-assembler-not "trap\\t3|trap.n\\t3" } } */
+
 /* check stack checking */
 void test()
 {
Index: gcc/testsuite/gcc.target/nios2/nios2-stack-check-3.c
===================================================================
--- gcc/testsuite/gcc.target/nios2/nios2-stack-check-3.c	(revision 0)
+++ gcc/testsuite/gcc.target/nios2/nios2-stack-check-3.c	(revision 0)
@@ -0,0 +1,12 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fstack-limit-symbol=__stackend -fno-pic" } */
+/* { dg-final { scan-assembler "movhi\\t.*, %hiadj\\(__stackend.*\\)" } } */
+/* { dg-final { scan-assembler "addi\\t.*, .*, %lo\\(__stackend.*\\)" } } */
+/* { dg-final { scan-assembler "bgeu\\tsp, " } } */
+/* { dg-final { scan-assembler "trap\\t3|trap.n\\t3" } } */
+
+/* check stack checking */
+void test()
+{
+  int a, b, c;
+}
Index: gcc/config/nios2/nios2.c
===================================================================
--- gcc/config/nios2/nios2.c	(revision 225722)
+++ gcc/config/nios2/nios2.c	(working copy)
@@ -456,20 +456,47 @@  restore_reg (int regno, unsigned offset)
   RTX_FRAME_RELATED_P (insn) = 1;
 }
 
-/* Emit conditional trap for checking stack limit.  */
+/* Temp regno used inside prologue/epilogue.  */
+#define TEMP_REG_NUM 8
+
+/* Emit conditional trap for checking stack limit.  SIZE is the number of
+   additional bytes required.  
+
+   GDB prologue analysis depends on this generating a direct comparison
+   to the SP register, so the adjustment to add SIZE needs to be done on
+   the other operand to the comparison.  Use TEMP_REG_NUM as a temporary,
+   if necessary.  */
 static void
-nios2_emit_stack_limit_check (void)
+nios2_emit_stack_limit_check (int size)
 {
-  if (REG_P (stack_limit_rtx))
-    emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode, stack_pointer_rtx,
-					  stack_limit_rtx),
-			     stack_pointer_rtx, stack_limit_rtx, GEN_INT (3)));
+  rtx sum;
+
+  if (GET_CODE (stack_limit_rtx) == SYMBOL_REF)
+    {
+      /* This generates a %hiadj/%lo pair with the constant size
+	 add handled by the relocations.  */
+      sum = gen_rtx_REG (Pmode, TEMP_REG_NUM);
+      emit_move_insn (sum, plus_constant (Pmode, stack_limit_rtx, size));
+    }
+  else if (!REG_P (stack_limit_rtx))
+    sorry ("Unknown form for stack limit expression");
+  else if (size == 0)
+    sum = stack_limit_rtx;
+  else if (SMALL_INT (size))
+    {
+      sum = gen_rtx_REG (Pmode, TEMP_REG_NUM);
+      emit_move_insn (sum, plus_constant (Pmode, stack_limit_rtx, size));
+    }
   else
-    sorry ("only register based stack limit is supported");
-}
+    {
+      sum = gen_rtx_REG (Pmode, TEMP_REG_NUM);
+      emit_move_insn (sum, gen_int_mode (size, Pmode));
+      emit_insn (gen_add2_insn (sum, stack_limit_rtx));
+    }
 
-/* Temp regno used inside prologue/epilogue.  */
-#define TEMP_REG_NUM 8
+  emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode, stack_pointer_rtx, sum),
+			   stack_pointer_rtx, sum, GEN_INT (3)));
+}
 
 static rtx_insn *
 nios2_emit_add_constant (rtx reg, HOST_WIDE_INT immed)
@@ -511,6 +538,8 @@  nios2_expand_prologue (void)
       RTX_FRAME_RELATED_P (insn) = 1;
       save_regs_base = 0;
       sp_offset = -cfun->machine->save_regs_offset;
+      if (crtl->limit_stack)
+	nios2_emit_stack_limit_check (cfun->machine->save_regs_offset);
     }
   else if (total_frame_size)
     {
@@ -520,13 +549,12 @@  nios2_expand_prologue (void)
       RTX_FRAME_RELATED_P (insn) = 1;
       save_regs_base = cfun->machine->save_regs_offset;
       sp_offset = 0;
+      if (crtl->limit_stack)
+	nios2_emit_stack_limit_check (0);
     }
   else
     save_regs_base = sp_offset = 0;
 
-  if (crtl->limit_stack)
-    nios2_emit_stack_limit_check ();
-
   save_offset = save_regs_base + cfun->machine->save_reg_size;
 
   for (regno = LAST_GP_REG; regno > 0; regno--)
@@ -561,9 +589,6 @@  nios2_expand_prologue (void)
 	  add_reg_note (insn, REG_FRAME_RELATED_EXPR, sp_adjust);
 	}
       RTX_FRAME_RELATED_P (insn) = 1;
-
-      if (crtl->limit_stack)
-	nios2_emit_stack_limit_check ();
     }
 
   /* Load the PIC register if needed.  */
@@ -1029,6 +1054,9 @@  nios2_option_override (void)
   /* Check for unsupported options.  */
   if (flag_pic && !TARGET_LINUX_ABI)
     sorry ("position-independent code requires the Linux ABI");
+  if (flag_pic && stack_limit_rtx
+      && GET_CODE (stack_limit_rtx) == SYMBOL_REF)
+    sorry ("PIC support for -fstack-limit-symbol");
 
   /* Function to allocate machine-dependent function status.  */
   init_machine_status = &nios2_init_machine_status;