public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [stack] PATCH: Handle __builtin_eh_return with stack realignment
@ 2008-04-14 23:28 H.J. Lu
  0 siblings, 0 replies; only message in thread
From: H.J. Lu @ 2008-04-14 23:28 UTC (permalink / raw)
  To: GCC Patches, Ye, Joey, Guo, Xuepeng

[-- Attachment #1: Type: text/plain, Size: 1432 bytes --]

Hi,

__builtin_eh_return is a very special case. If a function calls
__builtin_eh_return, ix86_expand_epilogue will be called
before ix86_expand_prologue.  Also __builtin_eh_return
doesn't use normal unwind info. I am checking this patch
into stack branch to handle it properly.


H.J.
----
2008-04-14  Xuepeng Guo  <xuepeng.guo@intel.com>
            Joey Ye  <joey.ye@intel.com>
            H.J. Lu  <hongjiu.lu@intel.com>

        * dwarf2out.c (struct dw_fde_struct): Rename is_stack_realign
        to stack_realign and is_drap_reg_saved to drap_reg_saved.  Add
        calls_eh_return.
        (add_cfi): Updated.
        (dwarf2out_frame_debug_expr): Likewise.
        (dwarf2out_begin_prologue): Initialize calls_eh_return.
        (reg_save_with_expression): Don't generate unwind information
        for restoring the stack pointer if __builtin_eh_return is called.

        * cfgexpand.c (handle_drap): Need drap if functon calls
        __builtin_eh_return.

        * config/i386/i386.c (find_drap_reg): Use DI_REG if function
        calls __builtin_eh_return.
        (ix86_internal_arg_pointer): Remove setting incoming stack
        boundary to preferred when __builtin_eh_return is called.
        (ix86_finalize_stack_realign_flags): New.
        (ix86_expand_prologue): Call ix86_finalize_stack_realign_flags.
        (ix86_expand_epilogue): Likewise.  Handle __builtin_eh_return
        with stack realignment.

[-- Attachment #2: eh.txt --]
[-- Type: text/plain, Size: 11669 bytes --]

Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(.../fsf/branches/stack)	(revision 2169)
+++ gcc/dwarf2out.c	(.../branches/stack-test)	(revision 2169)
@@ -249,11 +249,13 @@ typedef struct dw_fde_struct GTY(())
   unsigned nothrow : 1;
   unsigned uses_eh_lsda : 1;
   /* Whether we did stack realign in this call frame.*/
-  unsigned is_stack_realign : 1;
+  unsigned stack_realign : 1;
   /* Whether stack realign is drap. */
   unsigned is_drap : 1;
   /* Whether we saved this drap register. */
-  unsigned is_drap_reg_saved : 1;
+  unsigned drap_reg_saved : 1;
+  /* Whether called __builtin_eh_return */
+  unsigned calls_eh_return : 1;
 }
 dw_fde_node;
 
@@ -634,7 +636,7 @@ add_cfi (dw_cfi_ref *list_head, dw_cfi_r
   /* If stack is realigned, accessing the stored register via CFA+offset will
      be invalid. Here we will use a series of expressions in dwarf2 to simulate
      the stack realign and represent the location of the stored register. */
-  if (fde_table_in_use && (CUR_FDE.is_stack_realign || CUR_FDE.is_drap) 
+  if (fde_table_in_use && (CUR_FDE.stack_realign || CUR_FDE.is_drap) 
       && cfi->dw_cfi_opc == DW_CFA_offset)
     reg_save_with_expression (cfi);
 
@@ -1557,11 +1559,11 @@ static dw_cfa_location cfa_temp;
   
   Rule 16:
   (set sp (and: sp <const_int>))
-  effects: CUR_FDE.is_stack_realign = 1
+  effects: CUR_FDE.stack_realign = 1
            cfa_store.offset = 0
 
            if cfa_store.offset >= UNITS_PER_WORD
-             effects: CUR_FDE.is_drap_reg_saved = 1
+             effects: CUR_FDE.drap_reg_saved = 1
 
   Rule 17:
   (set (mem ({pre_inc, pre_dec} sp)) (mem (plus (cfa.reg) (const_int))))
@@ -1569,8 +1571,8 @@ static dw_cfa_location cfa_temp;
   
   Rule 18:
   (set (mem({pre_inc, pre_dec} sp)) fp)
-  constraints: CUR_FDE.is_stack_realign == 1
-  effects: CUR_FDE.is_stack_realign = 0
+  constraints: CUR_FDE.stack_realign == 1
+  effects: CUR_FDE.stack_realign = 0
            CUR_FDE.is_drap = 1
            CUR_FDE.drap_regnum = cfa.reg
 
@@ -1815,12 +1817,12 @@ dwarf2out_frame_debug_expr (rtx expr, co
              assume the stack is realigned and we extract the alignment. */
           if (XEXP (src, 0) == stack_pointer_rtx && fde_table_in_use)
             {
-              CUR_FDE.is_stack_realign = 1;
+              CUR_FDE.stack_realign = 1;
               CUR_FDE.stack_realignment = INTVAL (XEXP (src, 1));
               /* If we didn't push anything to stack before stack is realigned,
                   we assume the drap register isn't saved. */
               if (cfa_store.offset > UNITS_PER_WORD)
-                CUR_FDE.is_drap_reg_saved = 1;
+                CUR_FDE.drap_reg_saved = 1;
               cfa_store.offset = 0;
             }
           return;
@@ -1869,10 +1871,10 @@ dwarf2out_frame_debug_expr (rtx expr, co
           /* Rule 18 */
           /* If we push FP after stack is realigned, we assume this realignment
              is drap, we will recorde the drap register. */
-          if (fde_table_in_use && CUR_FDE.is_stack_realign
+          if (fde_table_in_use && CUR_FDE.stack_realign
               && REGNO (src) == HARD_FRAME_POINTER_REGNUM)
             {
-              CUR_FDE.is_stack_realign = 0;
+              CUR_FDE.stack_realign = 0;
               CUR_FDE.is_drap = 1;
               CUR_FDE.drap_regnum = DWARF_FRAME_REGNUM (cfa.reg);
             }            
@@ -2752,6 +2754,7 @@ dwarf2out_begin_prologue (unsigned int l
   fde->nothrow = TREE_NOTHROW (current_function_decl);
   fde->uses_eh_lsda = cfun->uses_eh_lsda;
   fde->all_throwers_are_sibcalls = cfun->all_throwers_are_sibcalls;
+  fde->calls_eh_return = cfun->calls_eh_return;
 
   args_size = old_args_size = 0;
 
@@ -15549,7 +15552,7 @@ reg_save_with_expression (dw_cfi_ref cfi
   int reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
   unsigned int dwarf_sp = (unsigned)DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
   
-  if (CUR_FDE.is_stack_realign)
+  if (CUR_FDE.stack_realign)
     {
       head = tmp = new_loc_descr (DW_OP_const4s, 2 * UNITS_PER_WORD, 0);
       tmp = tmp->dw_loc_next = new_loc_descr (DW_OP_minus, 0, 0);
@@ -15565,8 +15568,8 @@ reg_save_with_expression (dw_cfi_ref cfi
       cfi->dw_cfi_oprnd1.dw_cfi_loc = head;
     }
 
-  /* We need restore drap register through dereference. If we needn't to restore
-     the drap register we just ignore. */
+  /* We need restore drap register through dereference.  If we needn't
+     to restore the drap register, we just ignore it.  */
   if (CUR_FDE.is_drap && reg == CUR_FDE.drap_regnum)
     {
        
@@ -15575,7 +15578,7 @@ reg_save_with_expression (dw_cfi_ref cfi
       cfi->dw_cfi_opc = DW_CFA_expression;
       head = tmp = new_loc_descr (DW_OP_const4s, offset, 0);
       tmp = tmp->dw_loc_next = new_loc_descr (DW_OP_minus, 0, 0);
-      if (CUR_FDE.is_drap_reg_saved)
+      if (CUR_FDE.drap_reg_saved)
         {
           tmp = tmp->dw_loc_next = new_loc_descr (DW_OP_deref, 0, 0);
           tmp = tmp->dw_loc_next = new_loc_descr (DW_OP_const4s, 
@@ -15585,13 +15588,23 @@ reg_save_with_expression (dw_cfi_ref cfi
       cfi->dw_cfi_oprnd2.dw_cfi_reg_num = reg;
       cfi->dw_cfi_oprnd1.dw_cfi_loc = head;
 
-      /* We also need restore the sp. */
-      head = tmp = new_loc_descr (DW_OP_const4s, offset, 0);
-      tmp = tmp->dw_loc_next = new_loc_descr (DW_OP_minus, 0, 0);
-      cfi2->dw_cfi_opc = DW_CFA_expression;
-      cfi2->dw_cfi_oprnd2.dw_cfi_reg_num = dwarf_sp;
-      cfi2->dw_cfi_oprnd1.dw_cfi_loc = head;
-      cfi->dw_cfi_next = cfi2;
+      /* We also need to properly restore the caller's stack pointer.
+	 But if callee calls __builtin_eh_return, the calculation of
+	 offset from exception handling function (typically is
+	 _Unwind_RaiseException) to target function during unwinding
+	 will conflict with this mechanism.  It will simply set offset
+	 to zero.  So here if functions call __builtin_eh_return,
+	 there will be no unwind information for restoring the stack
+	 pointer.  */ 
+      if (!CUR_FDE.calls_eh_return)
+        {
+          head = tmp = new_loc_descr (DW_OP_const4s, offset, 0);
+          tmp = tmp->dw_loc_next = new_loc_descr (DW_OP_minus, 0, 0);
+          cfi2->dw_cfi_opc = DW_CFA_expression;
+          cfi2->dw_cfi_oprnd2.dw_cfi_reg_num = dwarf_sp;
+          cfi2->dw_cfi_oprnd1.dw_cfi_loc = head;
+          cfi->dw_cfi_next = cfi2;
+        }
     }  
 }
 #else
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c	(.../fsf/branches/stack)	(revision 2169)
+++ gcc/cfgexpand.c	(.../branches/stack-test)	(revision 2169)
@@ -1882,7 +1882,8 @@ handle_drap (void)
   
   if (current_function_calls_alloca
       || cfun->has_nonlocal_label
-      || current_function_has_nonlocal_goto)
+      || current_function_has_nonlocal_goto
+      || current_function_calls_eh_return)
     cfun->need_drap = true;
 
   /* Call targetm.calls.internal_arg_pointer again.  This time it will
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(.../fsf/branches/stack)	(revision 2169)
+++ gcc/config/i386/i386.c	(.../branches/stack-test)	(revision 2169)
@@ -6353,7 +6353,7 @@ find_drap_reg (void)
       && !DECL_NO_STATIC_CHAIN (cfun->decl))
     return DI_REG;
 
-  if (cfun->tail_call_emit)
+  if (cfun->tail_call_emit || current_function_calls_eh_return)
     return DI_REG;
 
   param_reg_num = ix86_function_regparm (TREE_TYPE (cfun->decl),
@@ -6383,12 +6383,6 @@ ix86_internal_arg_pointer (void)
        ? ix86_user_incoming_stack_boundary
        : ix86_default_incoming_stack_boundary);
 
-  /* Current stack realign doesn't support eh_return. Assume
-     function who calls eh_return is aligned. There will be sanity
-     check if stack realign happens together with eh_return later.  */
-  if (current_function_calls_eh_return)
-    ix86_incoming_stack_boundary = PREFERRED_STACK_BOUNDARY;
-
   /* Incoming stack alignment can be changed on individual functions
      via force_align_arg_pointer attribute.  We use the smallest
      incoming stack boundary.  */
@@ -6481,6 +6475,31 @@ ix86_dwarf_handle_frame_unspec (const ch
     }
 }
 
+/* Finalize stack_realign_really flag, which will guide prologue/epilogue
+   to be generated in correct form.  */
+static void 
+ix86_finalize_stack_realign_flags (void)
+{
+  /* Check if stack realign is really needed after reload, and 
+     stores result in cfun */
+  unsigned int stack_realign = (ix86_incoming_stack_boundary
+				< (current_function_is_leaf
+				   ? cfun->stack_alignment_used
+				   : cfun->stack_alignment_needed));
+
+  if (cfun->stack_realign_finalized)
+    {
+      /* After stack_realign_really is finalized, we can't no longer
+	 change it.  */
+      gcc_assert (cfun->stack_realign_really == stack_realign);
+    }
+  else
+    {
+      cfun->stack_realign_really = stack_realign;
+      cfun->stack_realign_finalized = true;
+    }
+}
+
 /* Expand the prologue into a bunch of separate insns.  */
 
 void
@@ -6492,18 +6511,11 @@ ix86_expand_prologue (void)
   HOST_WIDE_INT allocate;
   rtx (*gen_andsp) (rtx, rtx, rtx);
 
+  ix86_finalize_stack_realign_flags ();
+
   /* DRAP should not coexist with stack_realign_fp */
   gcc_assert (!(crtl->drap_reg && stack_realign_fp));
 
-  /* Check if stack realign is really needed after reload, and 
-     stores result in cfun */
-  cfun->stack_realign_really = (ix86_incoming_stack_boundary
-				< (current_function_is_leaf
-				   ? cfun->stack_alignment_used
-				   : cfun->stack_alignment_needed));
-
-  cfun->stack_realign_finalized = true;
-
   ix86_compute_frame_layout (&frame);
 
   /* Emit prologue code to adjust stack alignment and setup DRAP, in case
@@ -6752,13 +6764,17 @@ void
 ix86_expand_epilogue (int style)
 {
   int regno;
- /* When stack realign may happen, SP must be valid. */
-  int sp_valid = (!frame_pointer_needed
-		  || current_function_sp_is_unchanging
-		  || (stack_realign_fp && cfun->stack_realign_really));
+  int sp_valid;
   struct ix86_frame frame;
   HOST_WIDE_INT offset;
 
+  ix86_finalize_stack_realign_flags ();
+
+ /* When stack is realigned, SP must be valid.  */
+  sp_valid = (!frame_pointer_needed
+	      || current_function_sp_is_unchanging
+	      || (stack_realign_fp && cfun->stack_realign_really));
+
   ix86_compute_frame_layout (&frame);
 
   /* Calculate start of saved registers relative to ebp.  Special care
@@ -6812,13 +6828,18 @@ ix86_expand_epilogue (int style)
       if (style == 2)
 	{
 	  rtx tmp, sa = EH_RETURN_STACKADJ_RTX;
-
-	  if (cfun->stack_realign_really)
-	    {
-	      error("Stack realign has conflict with eh_return");
-	    }
 	  if (frame_pointer_needed)
 	    {
+              if (cfun->stack_realign_really)
+                {
+                  gcc_assert (!stack_realign_fp);
+                  gcc_assert (cfun->calls_eh_return);
+                  tmp = plus_constant (crtl->drap_reg,
+				       2 * (-UNITS_PER_WORD));
+                  tmp = gen_rtx_MEM (Pmode, tmp);
+                  emit_move_insn (crtl->drap_reg, tmp);
+                }
+
 	      tmp = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, sa);
 	      tmp = plus_constant (tmp, UNITS_PER_WORD);
 	      emit_insn (gen_rtx_SET (VOIDmode, sa, tmp));
@@ -6909,7 +6930,9 @@ ix86_expand_epilogue (int style)
 	}
     }
 
-  if (crtl->drap_reg && cfun->stack_realign_really)
+  if (style != 2
+      && crtl->drap_reg
+      && cfun->stack_realign_really)
     {
       int param_ptr_offset = (cfun->save_param_ptr_reg
 			      ? STACK_BOUNDARY / BITS_PER_UNIT : 0);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2008-04-14 21:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-04-14 23:28 [stack] PATCH: Handle __builtin_eh_return with stack realignment H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).