From 6e3077c6087cfcf64d814641adc019a2a85c763e Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 5 Dec 2003 07:46:35 +0100 Subject: [PATCH] re PR middle-end/11151 (__builtin_return(__builtin_apply(...)) gives wrong result) 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 | 13 +++++++++++++ gcc/builtins.c | 2 +- gcc/config/sparc/sparc.md | 2 +- gcc/function.c | 6 ++++++ gcc/function.h | 6 ++++++ gcc/rtl.h | 1 + gcc/stmt.c | 20 +++++++++++++++++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/builtin-return-1.c | 26 +++++++++++++++++++++++++ 9 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/builtin-return-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cb3b949354a..efe009217e6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2003-12-05 Eric Botcazou + + 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 PR target/11322 diff --git a/gcc/builtins.c b/gcc/builtins.c index 5c9971acdb7..ba624463660 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 46bd35809a9..147ea2558b3 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 79334af980d..2a8f30b2fb4 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 3aad05a4eea..89a1465ad0a 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 800282a815e..d6e9b9c81e1 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 a7c910437f1..324789da312 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 ff1d874ce2c..49abc91de9b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-12-05 Eric Botcazou + + * gcc.dg/builtin-return-1.c: New test. + 2003-12-04 Stuart Menefy J"orn Rennecke 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 00000000000..d22891589dd --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-return-1.c @@ -0,0 +1,26 @@ +/* PR middle-end/11151 */ +/* Originator: Andrew Church */ +/* { 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; +} -- 2.30.2