Subject: Re: stdcall lib functions with exception throwing callbacks vs Dwarf2 EH
From: Richard Henderson <[email-masked]>
To: Danny Smith <[email-masked]>
Cc: [email-masked], Cygwin <[email-masked]>, mingw-dvlpr <[email-masked]>
Date: Wed, 24 Nov 2004 10:44:27 -0800

I reproduced this specific failure on linux, and the following seems
to fix the problem.  Can you give it a go with whatever more complex
test case you have?

r~

	* dwarf2out.c (dwarf2out_stack_adjust): Add after_p argument.  Save
	args_size adjustments for calls even with cfa as stack pointer.
	Search calls for stack adjustments after the insn is issued.
	(dwarf2out_frame_debug): Add after_p argument; pass it on.
	* dwarf2out.h (dwarf2out_frame_debug): Update to match.
	* final.c (final_start_function, final_scan_insn): Likewise.

Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.559
diff -u -p -r1.559 dwarf2out.c
--- dwarf2out.c	24 Nov 2004 14:35:25 -0000	1.559
+++ dwarf2out.c	24 Nov 2004 18:38:47 -0000
@@ -363,7 +363,7 @@ static void initial_return_save (rtx);
 static HOST_WIDE_INT stack_adjust_offset (rtx);
 static void output_cfi (dw_cfi_ref, dw_fde_ref, int);
 static void output_call_frame_info (int);
-static void dwarf2out_stack_adjust (rtx);
+static void dwarf2out_stack_adjust (rtx, bool);
 static void flush_queued_reg_saves (void);
 static bool clobbers_queued_reg_save (rtx);
 static void dwarf2out_frame_debug_expr (rtx, const char *);
@@ -1051,7 +1051,7 @@ stack_adjust_offset (rtx pattern)
    much extra space it needs to pop off the stack.  */
 
 static void
-dwarf2out_stack_adjust (rtx insn)
+dwarf2out_stack_adjust (rtx insn, bool after_p)
 {
   HOST_WIDE_INT offset;
   const char *label;
@@ -1064,26 +1064,31 @@ dwarf2out_stack_adjust (rtx insn)
   if (prologue_epilogue_contains (insn) || sibcall_epilogue_contains (insn))
     return;
 
-  if (!flag_asynchronous_unwind_tables && CALL_P (insn))
+  /* If only calls can throw, and we have a frame pointer,
+     save up adjustments until we see the CALL_INSN.  */
+  if (!flag_asynchronous_unwind_tables && cfa.reg != STACK_POINTER_REGNUM)
     {
-      /* Extract the size of the args from the CALL rtx itself.  */
-      insn = PATTERN (insn);
-      if (GET_CODE (insn) == PARALLEL)
-	insn = XVECEXP (insn, 0, 0);
-      if (GET_CODE (insn) == SET)
-	insn = SET_SRC (insn);
-      gcc_assert (GET_CODE (insn) == CALL);
-
-      dwarf2out_args_size ("", INTVAL (XEXP (insn, 1)));
+      if (CALL_P (insn) && !after_p)
+	{
+	  /* Extract the size of the args from the CALL rtx itself.  */
+	  insn = PATTERN (insn);
+	  if (GET_CODE (insn) == PARALLEL)
+	    insn = XVECEXP (insn, 0, 0);
+	  if (GET_CODE (insn) == SET)
+	    insn = SET_SRC (insn);
+	  gcc_assert (GET_CODE (insn) == CALL);
+	  dwarf2out_args_size ("", INTVAL (XEXP (insn, 1)));
+	}
       return;
     }
 
-  /* If only calls can throw, and we have a frame pointer,
-     save up adjustments until we see the CALL_INSN.  */
-  else if (!flag_asynchronous_unwind_tables && cfa.reg != STACK_POINTER_REGNUM)
-    return;
-
-  if (BARRIER_P (insn))
+  if (CALL_P (insn) && !after_p)
+    {
+      if (!flag_asynchronous_unwind_tables)
+	dwarf2out_args_size ("", args_size);
+      return;
+    }
+  else if (BARRIER_P (insn))
     {
       /* When we see a BARRIER, we know to reset args_size to 0.  Usually
 	 the compiler will have already emitted a stack adjustment, but
@@ -1124,7 +1129,8 @@ dwarf2out_stack_adjust (rtx insn)
 
   label = dwarf2out_cfi_label ();
   def_cfa_1 (label, &cfa);
-  dwarf2out_args_size (label, args_size);
+  if (flag_asynchronous_unwind_tables)
+    dwarf2out_args_size (label, args_size);
 }
 
 #endif
@@ -1772,10 +1778,13 @@ dwarf2out_frame_debug_expr (rtx expr, co
 
 /* Record call frame debugging information for INSN, which either
    sets SP or FP (adjusting how we calculate the frame address) or saves a
-   register to the stack.  If INSN is NULL_RTX, initialize our state.  */
+   register to the stack.  If INSN is NULL_RTX, initialize our state.
+
+   If AFTER_P is false, we're being called before the insn is emitted,
+   otherwise after.  Call instructions get invoked twice.  */
 
 void
-dwarf2out_frame_debug (rtx insn)
+dwarf2out_frame_debug (rtx insn, bool after_p)
 {
   const char *label;
   rtx src;
@@ -1812,8 +1821,7 @@ dwarf2out_frame_debug (rtx insn)
   if (! RTX_FRAME_RELATED_P (insn))
     {
       if (!ACCUMULATE_OUTGOING_ARGS)
-	dwarf2out_stack_adjust (insn);
-
+	dwarf2out_stack_adjust (insn, after_p);
       return;
     }
 
Index: dwarf2out.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.h,v
retrieving revision 1.21
diff -u -p -r1.21 dwarf2out.h
--- dwarf2out.h	29 Jun 2003 15:19:13 -0000	1.21
+++ dwarf2out.h	24 Nov 2004 18:38:47 -0000
@@ -20,7 +20,7 @@ Software Foundation, 59 Temple Place - S
 02111-1307, USA.  */
 
 extern void dwarf2out_decl (tree);
-extern void dwarf2out_frame_debug (rtx);
+extern void dwarf2out_frame_debug (rtx, bool);
 
 extern void debug_dwarf (void);
 struct die_struct;
Index: final.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/final.c,v
retrieving revision 1.343
diff -u -p -r1.343 final.c
--- final.c	23 Nov 2004 23:10:18 -0000	1.343
+++ final.c	24 Nov 2004 18:38:47 -0000
@@ -1366,7 +1366,7 @@ final_start_function (rtx first ATTRIBUT
 
 #if defined (DWARF2_UNWIND_INFO) && defined (HAVE_prologue)
   if (dwarf2out_do_frame ())
-    dwarf2out_frame_debug (NULL_RTX);
+    dwarf2out_frame_debug (NULL_RTX, false);
 #endif
 
   /* If debugging, assign block numbers to all of the blocks in this
@@ -1848,7 +1848,7 @@ final_scan_insn (rtx insn, FILE *file, i
     case BARRIER:
 #if defined (DWARF2_UNWIND_INFO)
       if (dwarf2out_do_frame ())
-	dwarf2out_frame_debug (insn);
+	dwarf2out_frame_debug (insn, false);
 #endif
       break;
 
@@ -2168,7 +2168,7 @@ final_scan_insn (rtx insn, FILE *file, i
 #if defined (DWARF2_UNWIND_INFO)
 	    if (dwarf2out_do_frame ())
 	      for (i = 1; i < XVECLEN (body, 0); i++)
-		dwarf2out_frame_debug (XVECEXP (body, 0, i));
+		dwarf2out_frame_debug (XVECEXP (body, 0, i), false);
 #endif
 
 	    /* The first insn in this SEQUENCE might be a JUMP_INSN that will
@@ -2460,7 +2460,7 @@ final_scan_insn (rtx insn, FILE *file, i
 
 #if defined (DWARF2_UNWIND_INFO)
 	if (CALL_P (insn) && dwarf2out_do_frame ())
-	  dwarf2out_frame_debug (insn);
+	  dwarf2out_frame_debug (insn, false);
 #endif
 
 	/* Find the proper template for this insn.  */
@@ -2527,13 +2527,12 @@ final_scan_insn (rtx insn, FILE *file, i
 	   the unwind info.   We've already done this for delay slots
 	   and call instructions.  */
 #if defined (DWARF2_UNWIND_INFO)
-	if (NONJUMP_INSN_P (insn)
+	if (final_sequence == 0
 #if !defined (HAVE_prologue)
 	    && !ACCUMULATE_OUTGOING_ARGS
 #endif
-	    && final_sequence == 0
 	    && dwarf2out_do_frame ())
-	  dwarf2out_frame_debug (insn);
+	  dwarf2out_frame_debug (insn, true);
 #endif
 
 	current_output_insn = debug_insn = 0;

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/