re PR middle-end/11151 (__builtin_return(__builtin_apply(...)) gives wrong result)
authorEric Botcazou <ebotcazou@libertysurf.fr>
Fri, 5 Dec 2003 06:46:35 +0000 (07:46 +0100)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 5 Dec 2003 06:46:35 +0000 (06:46 +0000)
PR middle-end/11151
* function.h (struct function): New field 'x_naked_return_label'.
* function.c (free_after_compilation): Set it to NULL.
(expand_function_end): Emit 'naked_return_label' if it exists.
* rtl.h (expand_naked_return): Declare.
* stmt.c (expand_naked_return): New function to generate a
jump to 'naked_return_label'.
* builtins.c (expand_builtin_return): Call expand_naked_return
instead of expand_null_return.
* config/sparc/sparc.md (untyped_return): Likewise.

From-SVN: r74312

gcc/ChangeLog
gcc/builtins.c
gcc/config/sparc/sparc.md
gcc/function.c
gcc/function.h
gcc/rtl.h
gcc/stmt.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtin-return-1.c [new file with mode: 0644]

index cb3b949354a84fca740d4921dac0f7733d91f5c5..efe009217e60e6ebd9f98a1b227bbcb25d75d847 100644 (file)
@@ -1,3 +1,16 @@
+2003-12-05  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       PR middle-end/11151
+       * function.h (struct function): New field 'x_naked_return_label'.
+       * function.c (free_after_compilation): Set it to NULL.
+       (expand_function_end): Emit 'naked_return_label' if it exists.
+       * rtl.h (expand_naked_return): Declare.
+       * stmt.c (expand_naked_return): New function to generate a
+       jump to 'naked_return_label'.
+       * builtins.c (expand_builtin_return): Call expand_naked_return
+       instead of expand_null_return.
+       * config/sparc/sparc.md (untyped_return): Likewise.
+
 2003-12-04  Andrew Pinski  <pinskia@physics.uc.edu>
 
        PR target/11322
index 5c9971acdb7fd85caec9c2f1328b25405832a887..ba6244636600728ea178f283cccfb0ed2bef84a4 100644 (file)
@@ -1389,7 +1389,7 @@ expand_builtin_return (rtx result)
 
   /* Return whatever values was restored by jumping directly to the end
      of the function.  */
-  expand_null_return ();
+  expand_naked_return ();
 }
 
 /* Used by expand_builtin_classify_type and fold_builtin_classify_type.  */
index 46bd35809a9d397c225a488f4d84524c56b3030b..147ea2558b3734eb41c91d6ce06f1f17e4223127 100644 (file)
   emit_insn (gen_rtx_USE (VOIDmode, valreg2));
 
   /* Construct the return.  */
-  expand_null_return ();
+  expand_naked_return ();
 
   DONE;
 })
index 79334af980d6fd82e5f4bf1442c6b41824c557cf..2a8f30b2fb4737177f582934001651c0cd3cfad3 100644 (file)
@@ -452,6 +452,7 @@ free_after_compilation (struct function *f)
   f->x_nonlocal_goto_stack_level = NULL;
   f->x_cleanup_label = NULL;
   f->x_return_label = NULL;
+  f->x_naked_return_label = NULL;
   f->computed_goto_common_label = NULL;
   f->computed_goto_common_reg = NULL;
   f->x_save_expr_regs = NULL;
@@ -7132,6 +7133,11 @@ expand_function_end (void)
       cfun->x_clobber_return_insn = after;
   }
 
+  /* Output the label for the naked return from the function, if one is
+     expected.  This is currently used only by __builtin_return.  */
+  if (naked_return_label)
+    emit_label (naked_return_label);
+
   /* ??? This should no longer be necessary since stupid is no longer with
      us, but there are some parts of the compiler (eg reload_combine, and
      sh mach_dep_reorg) that still try and compute their own lifetime info
index 3aad05a4eeaba6c5612dd4a0f6817f115cb3a999..89a1465ad0a8abaffa374a7d17f7ae55316b67fa 100644 (file)
@@ -270,6 +270,11 @@ struct function GTY(())
      on machines which require execution of the epilogue on all returns.  */
   rtx x_return_label;
 
+  /* Label that will go on the end of function epilogue.
+     Jumping to this label serves as a "naked return" instruction
+     on machines which require execution of the epilogue on all returns.  */
+  rtx x_naked_return_label;
+
   /* Label and register for unswitching computed gotos.  */
   rtx computed_goto_common_label;
   rtx computed_goto_common_reg;
@@ -566,6 +571,7 @@ extern int trampolines_created;
 #define parm_reg_stack_loc (cfun->x_parm_reg_stack_loc)
 #define cleanup_label (cfun->x_cleanup_label)
 #define return_label (cfun->x_return_label)
+#define naked_return_label (cfun->x_naked_return_label)
 #define save_expr_regs (cfun->x_save_expr_regs)
 #define stack_slot_list (cfun->x_stack_slot_list)
 #define parm_birth_insn (cfun->x_parm_birth_insn)
index 800282a815eaabd0cb0bc67c06a9f8e12ff40136..d6e9b9c81e14bfd6851f1c2d9142c68a914ca702 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2133,6 +2133,7 @@ extern void purge_hard_subreg_sets (rtx);
 /* In stmt.c */
 extern void set_file_and_line_for_stmt (location_t);
 extern void expand_null_return (void);
+extern void expand_naked_return (void);
 extern void emit_jump (rtx);
 extern int preserve_subexpressions_p (void);
 
index a7c910437f1bfb80b4a9ed3f238ac87b382f3e53..324789da312c6515653fa68ba0dd2e9e655aa8ba 100644 (file)
@@ -2885,6 +2885,26 @@ expand_null_return (void)
   expand_null_return_1 (last_insn);
 }
 
+/* Generate RTL to return directly from the current function.
+   (That is, we bypass any return value.)  */
+
+void
+expand_naked_return (void)
+{
+  rtx last_insn, end_label;
+
+  last_insn = get_last_insn ();
+  end_label = naked_return_label;
+
+  clear_pending_stack_adjust ();
+  do_pending_stack_adjust ();
+  clear_last_expr ();
+
+  if (end_label == 0)
+    end_label = naked_return_label = gen_label_rtx ();
+  expand_goto_internal (NULL_TREE, end_label, last_insn);
+}
+
 /* Try to guess whether the value of return means error code.  */
 static enum br_predictor
 return_prediction (rtx val)
index ff1d874ce2c35d97704b90d15bb249e5cdf3fd97..49abc91de9b40d21b2574f0f977f47696f902e39 100644 (file)
@@ -1,3 +1,7 @@
+2003-12-05  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * gcc.dg/builtin-return-1.c: New test.
+
 2003-12-04  Stuart Menefy <stuart.menefy@st.com>
            J"orn Rennecke <joern.rennecke@superh.com>
 
diff --git a/gcc/testsuite/gcc.dg/builtin-return-1.c b/gcc/testsuite/gcc.dg/builtin-return-1.c
new file mode 100644 (file)
index 0000000..d228915
--- /dev/null
@@ -0,0 +1,26 @@
+/* PR middle-end/11151 */
+/* Originator: Andrew Church <gcczilla@achurch.org> */
+/* { dg-do run } */
+
+/* This used to fail on SPARC because the (undefined) return
+   value of 'bar' was overwriting that of 'foo'.  */
+
+extern void abort(void);
+
+int foo(int n)
+{
+  return n+1;
+}
+
+int bar(int n)
+{
+  __builtin_return(__builtin_apply((void (*)(void))foo, __builtin_apply_args(), 64));
+}
+
+int main(void)
+{
+  if (bar(1) != 2)
+    abort();
+
+  return 0;
+}