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]

[PATCH] Fix PR middle-end/11151


Hi,

This is the second part of the fix for this PR, which deals this time with 
__builtin_return (the first part dealt with __builtin_apply).

There is a problem with the current implementation of __builtin_return: after 
restoring the return value of the callee in hard registers, it calls 
expand_null_return.  But expand_null_return generates a jump to 
'return_label', which is the normal return label and is emitted (in 
expand_function_end) *before* the code that deals with the return value of 
the caller.  So the return value of the callee may be overwritten by that of 
the caller.

The proposed fix is to add a new expand_naked_return function, which 
generates a jump to 'naked_return_label' which is emitted after the code 
that deals with the return value of the caller.

Bootstrapped/regtested on i586-redhat-linux-gnu (mainline except Ada) and 
compiled/regtested on sparc-sun-solaris2.8.  This is sufficient because 
there are exactly 2 files in the GCC tree that use __builtin_return:

gcc/testsuite/gcc.dg/20020218-1.c
libobjc/sendmsg.c

Ok for mainline?


2003-11-28  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-11-28  Eric Botcazou  <ebotcazou@libertysurf.fr>

        * gcc.dg/builtin-return-1.c: New test.


-- 
Eric Botcazou
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.263
diff -u -p -r1.263 builtins.c
--- builtins.c	27 Nov 2003 05:20:09 -0000	1.263
+++ builtins.c	27 Nov 2003 15:12:17 -0000
@@ -1382,7 +1382,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: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.469
diff -u -p -r1.469 function.c
--- function.c	20 Nov 2003 22:42:01 -0000	1.469
+++ function.c	27 Nov 2003 15:13:31 -0000
@@ -452,6 +452,7 @@ free_after_compilation (struct function 
   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;
@@ -7125,6 +7126,11 @@ expand_function_end (void)
     if (clobber_after != after)
       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
Index: function.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.h,v
retrieving revision 1.103
diff -u -p -r1.103 function.h
--- function.h	25 Sep 2003 01:25:50 -0000	1.103
+++ function.h	27 Nov 2003 15:13:33 -0000
@@ -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;
@@ -563,6 +568,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: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.438
diff -u -p -r1.438 rtl.h
--- rtl.h	21 Nov 2003 06:52:23 -0000	1.438
+++ rtl.h	27 Nov 2003 15:13:43 -0000
@@ -2130,6 +2130,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: stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.336
diff -u -p -r1.336 stmt.c
--- stmt.c	20 Nov 2003 00:28:39 -0000	1.336
+++ stmt.c	27 Nov 2003 15:14:02 -0000
@@ -2882,6 +2882,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: config/sparc/sparc.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.md,v
retrieving revision 1.193
diff -u -p -r1.193 sparc.md
--- config/sparc/sparc.md	20 Oct 2003 10:07:35 -0000	1.193
+++ config/sparc/sparc.md	27 Nov 2003 15:15:02 -0000
@@ -7686,7 +7686,7 @@
   emit_insn (gen_rtx_USE (VOIDmode, valreg2));
 
   /* Construct the return.  */
-  expand_null_return ();
+  expand_naked_return ();
 
   DONE;
 })
/* 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 *)foo, __builtin_apply_args(), 64));
}

int main(void)
{
  if (bar(1) != 2)
    abort();

  return 0;
}

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