aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/builtins.c2
-rw-r--r--gcc/config/sparc/sparc.md2
-rw-r--r--gcc/function.c6
-rw-r--r--gcc/function.h6
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/stmt.c20
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/builtin-return-1.c26
9 files changed, 78 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index cb3b949..efe0092 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 5c9971a..ba62446 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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. */
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 46bd358..147ea25 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -7686,7 +7686,7 @@
emit_insn (gen_rtx_USE (VOIDmode, valreg2));
/* Construct the return. */
- expand_null_return ();
+ expand_naked_return ();
DONE;
})
diff --git a/gcc/function.c b/gcc/function.c
index 79334af..2a8f30b 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -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
diff --git a/gcc/function.h b/gcc/function.h
index 3aad05a..89a1465 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -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)
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 800282a..d6e9b9c 100644
--- 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);
diff --git a/gcc/stmt.c b/gcc/stmt.c
index a7c9104..324789d 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ff1d874..49abc91 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..d228915
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-return-1.c
@@ -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;
+}