diff mbox

[i386] Fix unwind/debug info for nested functions on 64-bit Windows

Message ID 2032936.hgCvkRqddN@polaris
State New
Headers show

Commit Message

Eric Botcazou Oct. 1, 2012, 8:11 a.m. UTC
Hi,

in the section of ix86_expand_prologue establishing the frame for Windows 
targets, there is:

      /* Note that SEH directives need to continue tracking the stack
	 pointer even after the frame pointer has been set up.  */
      if (m->fs.cfa_reg == stack_pointer_rtx || TARGET_SEH)
	{
	  if (m->fs.cfa_reg == stack_pointer_rtx)
	    m->fs.cfa_offset += allocate;

	  RTX_FRAME_RELATED_P (insn) = 1;
	  add_reg_note (insn, REG_FRAME_RELATED_EXPR,
			gen_rtx_SET (VOIDmode, stack_pointer_rtx,
				     plus_constant (Pmode, stack_pointer_rtx,
						    -allocate)));
	}

But there is also a few lines above:

      if (eax_live)
	{
	  emit_insn (gen_push (eax));
	  allocate -= UNITS_PER_WORD;
	}
      if (r10_live)
	{
	  r10 = gen_rtx_REG (Pmode, R10_REG);
	  emit_insn (gen_push (r10));
	  allocate -= UNITS_PER_WORD;
	}

and these 2 pushes aren't marked, which can result in wrong SEH unwind and 
DWARF debug info on 64-bit Windows (we have an example of each kind in Ada).

Tested on x86_64-suse-linux and with a 4.7-based SEH-enabled compiler for 64-
Bit Windows.  OK for mainline and 4.7 branch?


2012-10-01  Eric Botcazou  <ebotcazou@adacore.com>

	* config/i386/i386.c (ix86_expand_prologue): Emit frame info for the
	special register pushes before frame probing and allocation.
diff mbox

Patch

Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 191796)
+++ config/i386/i386.c	(working copy)
@@ -10671,7 +10671,7 @@  ix86_expand_prologue (void)
       rtx eax = gen_rtx_REG (Pmode, AX_REG);
       rtx r10 = NULL;
       rtx (*adjust_stack_insn)(rtx, rtx, rtx);
-
+      const bool sp_is_cfa_reg = (m->fs.cfa_reg == stack_pointer_rtx);
       bool eax_live = false;
       bool r10_live = false;
 
@@ -10680,16 +10680,31 @@  ix86_expand_prologue (void)
       if (!TARGET_64BIT_MS_ABI)
         eax_live = ix86_eax_live_at_start_p ();
 
+      /* Note that SEH directives need to continue tracking the stack
+	 pointer even after the frame pointer has been set up.  */
       if (eax_live)
 	{
-	  emit_insn (gen_push (eax));
+	  insn = emit_insn (gen_push (eax));
 	  allocate -= UNITS_PER_WORD;
+	  if (sp_is_cfa_reg || TARGET_SEH)
+	    {
+	      if (sp_is_cfa_reg)
+		m->fs.cfa_offset += UNITS_PER_WORD;
+	      RTX_FRAME_RELATED_P (insn) = 1;
+	    }
 	}
+
       if (r10_live)
 	{
 	  r10 = gen_rtx_REG (Pmode, R10_REG);
-	  emit_insn (gen_push (r10));
+	  insn = emit_insn (gen_push (r10));
 	  allocate -= UNITS_PER_WORD;
+	  if (sp_is_cfa_reg || TARGET_SEH)
+	    {
+	      if (sp_is_cfa_reg)
+		m->fs.cfa_offset += UNITS_PER_WORD;
+	      RTX_FRAME_RELATED_P (insn) = 1;
+	    }
 	}
 
       emit_move_insn (eax, GEN_INT (allocate));
@@ -10703,13 +10718,10 @@  ix86_expand_prologue (void)
       insn = emit_insn (adjust_stack_insn (stack_pointer_rtx,
 					   stack_pointer_rtx, eax));
 
-      /* Note that SEH directives need to continue tracking the stack
-	 pointer even after the frame pointer has been set up.  */
-      if (m->fs.cfa_reg == stack_pointer_rtx || TARGET_SEH)
+      if (sp_is_cfa_reg || TARGET_SEH)
 	{
-	  if (m->fs.cfa_reg == stack_pointer_rtx)
+	  if (sp_is_cfa_reg)
 	    m->fs.cfa_offset += allocate;
-
 	  RTX_FRAME_RELATED_P (insn) = 1;
 	  add_reg_note (insn, REG_FRAME_RELATED_EXPR,
 			gen_rtx_SET (VOIDmode, stack_pointer_rtx,