diff mbox

[8/9] dwarf2cfi: Introduce dw_trace_info.

Message ID 1310684876-6244-9-git-send-email-rth@redhat.com
State New
Headers show

Commit Message

Richard Henderson July 14, 2011, 11:07 p.m. UTC
This patch only introduces the structure definition and adjusts
the existing routines to use the new cur_trace global to access
the variables that were moved into the structure.
---
 gcc/dwarf2cfi.c |  440 +++++++++++++++++++++++++++++++++----------------------
 1 files changed, 266 insertions(+), 174 deletions(-)
diff mbox

Patch

diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index 1d6413f..9aa1208 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -74,7 +74,98 @@  typedef struct GTY(()) dw_cfi_row_struct
   HOST_WIDE_INT args_size;
 } dw_cfi_row;
 
-
+/* The caller's ORIG_REG is saved in SAVED_IN_REG.  */
+typedef struct GTY(()) reg_saved_in_data_struct {
+  rtx orig_reg;
+  rtx saved_in_reg;
+} reg_saved_in_data;
+
+DEF_VEC_O (reg_saved_in_data);
+DEF_VEC_ALLOC_O (reg_saved_in_data, heap);
+
+/* Since we no longer have a proper CFG, we're going to create a facsimile
+   of one on the fly while processing the frame-related insns.
+
+   We create dw_trace structures for each instruction trace beginning at
+   at a label following a barrier (or beginning of the function), and
+   ending at a barrier (or the end of the function).
+
+   As we encounter control transfer insns, we propagate the "current"
+   row state across the edges to the starts of traces.  If an edge goes
+   to a label that is not the start of a trace, we ignore it.  This
+   assumes that previous compiler transformations were correct, and that
+   we will reach the same row state from any source.  (We can perform some
+   limited validation of this assumption, but without the full CFG we
+   cannot be sure of full validation coverage.  It is expensive, so we
+   only do so with checking enabled.)
+
+   All traces are members of the TRACE_INFO array, in the order in which
+   they appear in the instruction stream.
+
+   All labels are given an LUID that indexes the LABEL_INFO array.  If
+   the label is the start of a trace, the TRACE pointer will be non-NULL
+   and point into the TRACE_INFO array.  */
+
+typedef struct
+{
+  /* The label that begins the trace.  This will be NULL for the first
+     trace beginning at function entry.  */
+  rtx label;
+
+  /* The row state at the beginning and end of the trace.  */
+  dw_cfi_row *enter_row, *exit_row;
+
+  /* The following variables contain data used in interpreting frame related
+     expressions.  These are not part of the "real" row state as defined by
+     Dwarf, but it seems like they need to be propagated into a trace in case
+     frame related expressions have been sunk.  */
+  /* ??? This seems fragile.  These variables are fragments of a larger
+     expression.  If we do not keep the entire expression together, we risk
+     not being able to put it together properly.  Consider forcing targets
+     to generate self-contained expressions and dropping all of the magic
+     interpretation code in this file.  Or at least refusing to shrink wrap
+     any frame related insn that doesn't contain a complete expression.  */
+
+  /* The register used for saving registers to the stack, and its offset
+     from the CFA.  */
+  dw_cfa_location cfa_store;
+
+  /* A temporary register holding an integral value used in adjusting SP
+     or setting up the store_reg.  The "offset" field holds the integer
+     value, not an offset.  */
+  dw_cfa_location cfa_temp;
+
+  /* A set of registers saved in other registers.  This is the inverse of
+     the row->reg_save info, if the entry is a DW_CFA_register.  This is
+     implemented as a flat array because it normally contains zero or 1
+     entry, depending on the target.  IA-64 is the big spender here, using
+     a maximum of 5 entries.  */
+  VEC(reg_saved_in_data, heap) *regs_saved_in_regs;
+
+} dw_trace_info;
+
+DEF_VEC_O (dw_trace_info);
+DEF_VEC_ALLOC_O (dw_trace_info, heap);
+
+typedef struct
+{
+  dw_trace_info *trace;
+
+#ifdef ENABLE_CHECKING
+  dw_cfi_row *check_row;
+#endif
+} dw_label_info;
+
+DEF_VEC_O (dw_label_info);
+DEF_VEC_ALLOC_O (dw_label_info, heap);
+
+/* The variables making up the pseudo-cfg, as described above.  */
+#if 0
+static VEC (int, heap) *uid_luid;
+static VEC (dw_label_info, heap) *label_info;
+static VEC (dw_trace_info, heap) *trace_info;
+#endif
+
 /* A vector of call frame insns for the CIE.  */
 cfi_vec cie_cfi_vec;
 
@@ -82,6 +173,8 @@  cfi_vec cie_cfi_vec;
    state provided by the CIE.  */
 static GTY(()) dw_cfi_row *cie_cfi_row;
 
+static GTY(()) reg_saved_in_data *cie_return_save;
+
 static GTY(()) unsigned long dwarf2out_cfi_label_num;
 
 /* The insn after which a new CFI note should be emitted.  */
@@ -90,6 +183,34 @@  static rtx add_cfi_insn;
 /* When non-null, add_cfi will add the CFI to this vector.  */
 static cfi_vec *add_cfi_vec;
 
+/* The current instruction trace.  */
+static dw_trace_info *cur_trace;
+
+/* The current, i.e. most recently generated, row of the CFI table.  */
+static dw_cfi_row *cur_row;
+
+/* The row state from a preceeding DW_CFA_remember_state.  */
+static dw_cfi_row *remember_row;
+
+/* We delay emitting a register save until either (a) we reach the end
+   of the prologue or (b) the register is clobbered.  This clusters
+   register saves so that there are fewer pc advances.  */
+
+typedef struct {
+  rtx reg;
+  rtx saved_reg;
+  HOST_WIDE_INT cfa_offset;
+} queued_reg_save;
+
+DEF_VEC_O (queued_reg_save);
+DEF_VEC_ALLOC_O (queued_reg_save, heap);
+
+static VEC(queued_reg_save, heap) *queued_reg_saves;
+
+/* The (really) current value for DW_CFA_GNU_args_size.  We delay actually
+   emitting this data, i.e. updating CUR_ROW, without async unwind.  */
+static HOST_WIDE_INT queued_args_size;
+
 /* True if remember_state should be emitted before following CFI directive.  */
 static bool emit_cfa_remember;
 
@@ -464,25 +585,6 @@  lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc, dw_cfa_location *remember)
     }
 }
 
-/* The current, i.e. most recently generated, row of the CFI table.  */
-static dw_cfi_row *cur_row;
-
-/* The row state from a preceeding DW_CFA_remember_state.  */
-static dw_cfi_row *remember_row;
-
-/* The register used for saving registers to the stack, and its offset
-   from the CFA.  */
-static dw_cfa_location cfa_store;
-
-/* A temporary register holding an integral value used in adjusting SP
-   or setting up the store_reg.  The "offset" field holds the integer
-   value, not an offset.  */
-static dw_cfa_location cfa_temp;
-
-/* The (really) current value for DW_CFA_GNU_args_size.  We delay actually
-   emitting this data, i.e. updating CUR_ROW, without async unwind.  */
-static HOST_WIDE_INT args_size;
-
 /* Determine if two dw_cfa_location structures define the same data.  */
 
 bool
@@ -621,8 +723,8 @@  def_cfa_1 (dw_cfa_location *new_cfa)
 {
   dw_cfi_ref cfi;
 
-  if (cfa_store.reg == new_cfa->reg && new_cfa->indirect == 0)
-    cfa_store.offset = new_cfa->offset;
+  if (cur_trace->cfa_store.reg == new_cfa->reg && new_cfa->indirect == 0)
+    cur_trace->cfa_store.offset = new_cfa->offset;
 
   cfi = def_cfa_0 (&cur_row->cfa, new_cfa);
   if (cfi)
@@ -972,8 +1074,16 @@  dwarf2out_stack_adjust (HOST_WIDE_INT offset)
   if (loc.reg == dw_stack_pointer_regnum)
     loc.offset += offset;
 
-  if (cfa_store.reg == dw_stack_pointer_regnum)
-    cfa_store.offset += offset;
+  if (cur_trace->cfa_store.reg == dw_stack_pointer_regnum)
+    cur_trace->cfa_store.offset += offset;
+
+#ifndef STACK_GROWS_DOWNWARD
+  offset = -offset;
+#endif
+
+  queued_args_size += offset;
+  if (queued_args_size < 0)
+    queued_args_size = 0;
 
   /* ??? The assumption seems to be that if A_O_A, the only CFA adjustments
      involving the stack pointer are inside the prologue and marked as
@@ -983,17 +1093,9 @@  dwarf2out_stack_adjust (HOST_WIDE_INT offset)
   if (ACCUMULATE_OUTGOING_ARGS)
     return;
 
-#ifndef STACK_GROWS_DOWNWARD
-  offset = -offset;
-#endif
-
-  args_size += offset;
-  if (args_size < 0)
-    args_size = 0;
-
   def_cfa_1 (&loc);
   if (flag_asynchronous_unwind_tables)
-    dwarf2out_args_size (args_size);
+    dwarf2out_args_size (queued_args_size);
 }
 
 /* Check INSN to see if it looks like a push or a stack adjustment, and
@@ -1035,7 +1137,8 @@  dwarf2out_notice_stack_adjust (rtx insn, bool after_p)
 	  if (GET_CODE (insn) == SET)
 	    insn = SET_SRC (insn);
 	  gcc_assert (GET_CODE (insn) == CALL);
-	  dwarf2out_args_size (INTVAL (XEXP (insn, 1)));
+	  gcc_assert (queued_args_size == INTVAL (XEXP (insn, 1)));
+	  dwarf2out_args_size (queued_args_size);
 	}
       return;
     }
@@ -1043,7 +1146,7 @@  dwarf2out_notice_stack_adjust (rtx insn, bool after_p)
   if (CALL_P (insn) && !after_p)
     {
       if (!flag_asynchronous_unwind_tables)
-	dwarf2out_args_size (args_size);
+	dwarf2out_args_size (queued_args_size);
       return;
     }
   else if (BARRIER_P (insn))
@@ -1061,13 +1164,13 @@  dwarf2out_notice_stack_adjust (rtx insn, bool after_p)
 	    offset = 0;
 	}
 
-      offset -= args_size;
+      offset -= queued_args_size;
 #ifndef STACK_GROWS_DOWNWARD
       offset = -offset;
 #endif
     }
   else if (GET_CODE (PATTERN (insn)) == SET)
-    offset = stack_adjust_offset (PATTERN (insn), args_size, 0);
+    offset = stack_adjust_offset (PATTERN (insn), queued_args_size, 0);
   else if (GET_CODE (PATTERN (insn)) == PARALLEL
 	   || GET_CODE (PATTERN (insn)) == SEQUENCE)
     {
@@ -1076,7 +1179,7 @@  dwarf2out_notice_stack_adjust (rtx insn, bool after_p)
       for (offset = 0, i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
 	if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
 	  offset += stack_adjust_offset (XVECEXP (PATTERN (insn), 0, i),
-					 args_size, offset);
+					 queued_args_size, offset);
     }
   else
     return;
@@ -1087,38 +1190,6 @@  dwarf2out_notice_stack_adjust (rtx insn, bool after_p)
   dwarf2out_stack_adjust (offset);
 }
 
-/* We delay emitting a register save until either (a) we reach the end
-   of the prologue or (b) the register is clobbered.  This clusters
-   register saves so that there are fewer pc advances.  */
-
-typedef struct {
-  rtx reg;
-  rtx saved_reg;
-  HOST_WIDE_INT cfa_offset;
-} queued_reg_save;
-
-DEF_VEC_O (queued_reg_save);
-DEF_VEC_ALLOC_O (queued_reg_save, heap);
-
-static VEC(queued_reg_save, heap) *queued_reg_saves;
-
-/* The caller's ORIG_REG is saved in SAVED_IN_REG.  */
-typedef struct GTY(()) reg_saved_in_data {
-  rtx orig_reg;
-  rtx saved_in_reg;
-} reg_saved_in_data;
-
-DEF_VEC_O (reg_saved_in_data);
-DEF_VEC_ALLOC_O (reg_saved_in_data, heap);
-
-/* A set of registers saved in other registers.  This is implemented as
-   a flat array because it normally contains zero or 1 entry, depending
-   on the target.  IA-64 is the big spender here, using a maximum of
-   5 entries.  */
-static VEC(reg_saved_in_data, heap) *regs_saved_in_regs;
-
-static GTY(()) reg_saved_in_data *cie_return_save;
-
 /* Short-hand inline for the very common D_F_R (REGNO (x)) operation.  */
 /* ??? This ought to go into dwarf2out.h, except that dwarf2out.h is
    used in places where rtl is prohibited.  */
@@ -1148,11 +1219,12 @@  record_reg_saved_in_reg (rtx dest, rtx src)
   reg_saved_in_data *elt;
   size_t i;
 
-  FOR_EACH_VEC_ELT (reg_saved_in_data, regs_saved_in_regs, i, elt)
+  FOR_EACH_VEC_ELT (reg_saved_in_data, cur_trace->regs_saved_in_regs, i, elt)
     if (compare_reg_or_pc (elt->orig_reg, src))
       {
 	if (dest == NULL)
-	  VEC_unordered_remove(reg_saved_in_data, regs_saved_in_regs, i);
+	  VEC_unordered_remove (reg_saved_in_data,
+			        cur_trace->regs_saved_in_regs, i);
 	else
 	  elt->saved_in_reg = dest;
 	return;
@@ -1161,7 +1233,8 @@  record_reg_saved_in_reg (rtx dest, rtx src)
   if (dest == NULL)
     return;
 
-  elt = VEC_safe_push(reg_saved_in_data, heap, regs_saved_in_regs, NULL);
+  elt = VEC_safe_push (reg_saved_in_data, heap,
+		       cur_trace->regs_saved_in_regs, NULL);
   elt->orig_reg = src;
   elt->saved_in_reg = dest;
 }
@@ -1236,7 +1309,8 @@  clobbers_queued_reg_save (const_rtx insn)
       if (modified_in_p (q->reg, insn))
 	return true;
 
-      FOR_EACH_VEC_ELT (reg_saved_in_data, regs_saved_in_regs, ir, rir)
+      FOR_EACH_VEC_ELT (reg_saved_in_data,
+			cur_trace->regs_saved_in_regs, ir, rir)
 	if (compare_reg_or_pc (q->reg, rir->orig_reg)
 	    && modified_in_p (rir->saved_in_reg, insn))
 	  return true;
@@ -1259,7 +1333,7 @@  reg_saved_in (rtx reg)
     if (q->saved_reg && regn == REGNO (q->saved_reg))
       return q->reg;
 
-  FOR_EACH_VEC_ELT (reg_saved_in_data, regs_saved_in_regs, i, rir)
+  FOR_EACH_VEC_ELT (reg_saved_in_data, cur_trace->regs_saved_in_regs, i, rir)
     if (regn == REGNO (rir->saved_in_reg))
       return rir->orig_reg;
 
@@ -1371,7 +1445,7 @@  dwarf2out_frame_debug_cfa_offset (rtx set)
       span = NULL;
       sregno = DWARF_FRAME_RETURN_COLUMN;
     }
-  else 
+  else
     {
       span = targetm.dwarf_register_span (src);
       sregno = dwf_regno (src);
@@ -1727,7 +1801,8 @@  dwarf2out_frame_debug_expr (rtx expr)
 	    {
 	      /* Stack adjustment combining might combine some post-prologue
 		 stack adjustment into a prologue stack adjustment.  */
-	      HOST_WIDE_INT offset = stack_adjust_offset (elem, args_size, 0);
+	      HOST_WIDE_INT offset
+		= stack_adjust_offset (elem, queued_args_size, 0);
 
 	      if (offset != 0)
 		dwarf2out_stack_adjust (offset);
@@ -1768,8 +1843,8 @@  dwarf2out_frame_debug_expr (rtx expr)
 		 FP.  So we just rely on the backends to only set
 		 RTX_FRAME_RELATED_P on appropriate insns.  */
 	      cfa.reg = dwf_regno (dest);
-	      cfa_temp.reg = cfa.reg;
-	      cfa_temp.offset = cfa.offset;
+	      cur_trace->cfa_temp.reg = cfa.reg;
+	      cur_trace->cfa_temp.offset = cfa.offset;
 	    }
 	  else
 	    {
@@ -1806,8 +1881,9 @@  dwarf2out_frame_debug_expr (rtx expr)
 		  offset = INTVAL (XEXP (src, 1));
 		  break;
 		case REG:
-		  gcc_assert (dwf_regno (XEXP (src, 1)) == cfa_temp.reg);
-		  offset = cfa_temp.offset;
+		  gcc_assert (dwf_regno (XEXP (src, 1))
+			      == cur_trace->cfa_temp.reg);
+		  offset = cur_trace->cfa_temp.offset;
 		  break;
 		default:
 		  gcc_unreachable ();
@@ -1829,8 +1905,8 @@  dwarf2out_frame_debug_expr (rtx expr)
 		offset = -offset;
 	      if (cfa.reg == dw_stack_pointer_regnum)
 		cfa.offset += offset;
-	      if (cfa_store.reg == dw_stack_pointer_regnum)
-		cfa_store.offset += offset;
+	      if (cur_trace->cfa_store.reg == dw_stack_pointer_regnum)
+		cur_trace->cfa_store.offset += offset;
 	    }
 	  else if (dest == hard_frame_pointer_rtx)
 	    {
@@ -1863,28 +1939,29 @@  dwarf2out_frame_debug_expr (rtx expr)
 		  cfa.offset += offset;
 		  cfa.reg = dwf_regno (dest);
 		  /* Or used to save regs to the stack.  */
-		  cfa_temp.reg = cfa.reg;
-		  cfa_temp.offset = cfa.offset;
+		  cur_trace->cfa_temp.reg = cfa.reg;
+		  cur_trace->cfa_temp.offset = cfa.offset;
 		}
 
 	      /* Rule 5 */
 	      else if (REG_P (XEXP (src, 0))
-		       && dwf_regno (XEXP (src, 0)) == cfa_temp.reg
+		       && dwf_regno (XEXP (src, 0)) == cur_trace->cfa_temp.reg
 		       && XEXP (src, 1) == stack_pointer_rtx)
 		{
 		  /* Setting a scratch register that we will use instead
 		     of SP for saving registers to the stack.  */
 		  gcc_assert (cfa.reg == dw_stack_pointer_regnum);
-		  cfa_store.reg = dwf_regno (dest);
-		  cfa_store.offset = cfa.offset - cfa_temp.offset;
+		  cur_trace->cfa_store.reg = dwf_regno (dest);
+		  cur_trace->cfa_store.offset
+		    = cfa.offset - cur_trace->cfa_temp.offset;
 		}
 
 	      /* Rule 9 */
 	      else if (GET_CODE (src) == LO_SUM
 		       && CONST_INT_P (XEXP (src, 1)))
 		{
-		  cfa_temp.reg = dwf_regno (dest);
-		  cfa_temp.offset = INTVAL (XEXP (src, 1));
+		  cur_trace->cfa_temp.reg = dwf_regno (dest);
+		  cur_trace->cfa_temp.offset = INTVAL (XEXP (src, 1));
 		}
 	      else
 		gcc_unreachable ();
@@ -1893,18 +1970,18 @@  dwarf2out_frame_debug_expr (rtx expr)
 
 	  /* Rule 6 */
 	case CONST_INT:
-	  cfa_temp.reg = dwf_regno (dest);
-	  cfa_temp.offset = INTVAL (src);
+	  cur_trace->cfa_temp.reg = dwf_regno (dest);
+	  cur_trace->cfa_temp.offset = INTVAL (src);
 	  break;
 
 	  /* Rule 7 */
 	case IOR:
 	  gcc_assert (REG_P (XEXP (src, 0))
-		      && dwf_regno (XEXP (src, 0)) == cfa_temp.reg
+		      && dwf_regno (XEXP (src, 0)) == cur_trace->cfa_temp.reg
 		      && CONST_INT_P (XEXP (src, 1)));
 
-	  cfa_temp.reg = dwf_regno (dest);
-	  cfa_temp.offset |= INTVAL (XEXP (src, 1));
+	  cur_trace->cfa_temp.reg = dwf_regno (dest);
+	  cur_trace->cfa_temp.offset |= INTVAL (XEXP (src, 1));
 	  break;
 
 	  /* Skip over HIGH, assuming it will be followed by a LO_SUM,
@@ -1931,10 +2008,11 @@  dwarf2out_frame_debug_expr (rtx expr)
 		 Thus we must flush whatever we have queued first.  */
 	      dwarf2out_flush_queued_reg_saves ();
 
-              gcc_assert (cfa_store.reg == dwf_regno (XEXP (src, 0)));
+              gcc_assert (cur_trace->cfa_store.reg
+			  == dwf_regno (XEXP (src, 0)));
               fde->stack_realign = 1;
               fde->stack_realignment = INTVAL (XEXP (src, 1));
-              cfa_store.offset = 0;
+              cur_trace->cfa_store.offset = 0;
 
 	      if (cfa.reg != dw_stack_pointer_regnum
 		  && cfa.reg != dw_frame_pointer_regnum)
@@ -1965,16 +2043,16 @@  dwarf2out_frame_debug_expr (rtx expr)
 	  offset = -INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1));
 
 	  gcc_assert (REGNO (XEXP (XEXP (dest, 0), 0)) == STACK_POINTER_REGNUM
-		      && cfa_store.reg == dw_stack_pointer_regnum);
+		      && cur_trace->cfa_store.reg == dw_stack_pointer_regnum);
 
-	  cfa_store.offset += offset;
+	  cur_trace->cfa_store.offset += offset;
 	  if (cfa.reg == dw_stack_pointer_regnum)
-	    cfa.offset = cfa_store.offset;
+	    cfa.offset = cur_trace->cfa_store.offset;
 
 	  if (GET_CODE (XEXP (dest, 0)) == POST_MODIFY)
-	    offset -= cfa_store.offset;
+	    offset -= cur_trace->cfa_store.offset;
 	  else
-	    offset = -cfa_store.offset;
+	    offset = -cur_trace->cfa_store.offset;
 	  break;
 
 	  /* Rule 11 */
@@ -1987,9 +2065,9 @@  dwarf2out_frame_debug_expr (rtx expr)
 
 	  gcc_assert ((REGNO (XEXP (XEXP (dest, 0), 0))
 		       == STACK_POINTER_REGNUM)
-		      && cfa_store.reg == dw_stack_pointer_regnum);
+		      && cur_trace->cfa_store.reg == dw_stack_pointer_regnum);
 
-	  cfa_store.offset += offset;
+	  cur_trace->cfa_store.offset += offset;
 
           /* Rule 18: If stack is aligned, we will use FP as a
 	     reference to represent the address of the stored
@@ -1999,16 +2077,16 @@  dwarf2out_frame_debug_expr (rtx expr)
               && src == hard_frame_pointer_rtx)
 	    {
 	      gcc_assert (cfa.reg != dw_frame_pointer_regnum);
-	      cfa_store.offset = 0;
+	      cur_trace->cfa_store.offset = 0;
 	    }
 
 	  if (cfa.reg == dw_stack_pointer_regnum)
-	    cfa.offset = cfa_store.offset;
+	    cfa.offset = cur_trace->cfa_store.offset;
 
 	  if (GET_CODE (XEXP (dest, 0)) == POST_DEC)
-	    offset += -cfa_store.offset;
+	    offset += -cur_trace->cfa_store.offset;
 	  else
-	    offset = -cfa_store.offset;
+	    offset = -cur_trace->cfa_store.offset;
 	  break;
 
 	  /* Rule 12 */
@@ -2029,12 +2107,12 @@  dwarf2out_frame_debug_expr (rtx expr)
 
 	    if (cfa.reg == regno)
 	      offset -= cfa.offset;
-	    else if (cfa_store.reg == regno)
-	      offset -= cfa_store.offset;
+	    else if (cur_trace->cfa_store.reg == regno)
+	      offset -= cur_trace->cfa_store.offset;
 	    else
 	      {
-		gcc_assert (cfa_temp.reg == regno);
-		offset -= cfa_temp.offset;
+		gcc_assert (cur_trace->cfa_temp.reg == regno);
+		offset -= cur_trace->cfa_temp.offset;
 	      }
 	  }
 	  break;
@@ -2047,21 +2125,22 @@  dwarf2out_frame_debug_expr (rtx expr)
 
 	    if (cfa.reg == regno)
 	      offset = -cfa.offset;
-	    else if (cfa_store.reg == regno)
-	      offset = -cfa_store.offset;
+	    else if (cur_trace->cfa_store.reg == regno)
+	      offset = -cur_trace->cfa_store.offset;
 	    else
 	      {
-		gcc_assert (cfa_temp.reg == regno);
-		offset = -cfa_temp.offset;
+		gcc_assert (cur_trace->cfa_temp.reg == regno);
+		offset = -cur_trace->cfa_temp.offset;
 	      }
 	  }
 	  break;
 
 	  /* Rule 14 */
 	case POST_INC:
-	  gcc_assert (cfa_temp.reg == dwf_regno (XEXP (XEXP (dest, 0), 0)));
-	  offset = -cfa_temp.offset;
-	  cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest));
+	  gcc_assert (cur_trace->cfa_temp.reg
+		      == dwf_regno (XEXP (XEXP (dest, 0), 0)));
+	  offset = -cur_trace->cfa_temp.offset;
+	  cur_trace->cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest));
 	  break;
 
 	default:
@@ -2453,7 +2532,7 @@  add_cfis_to_fde (void)
 }
 
 /* Scan the function and create the initial set of CFI notes.  */
- 
+
 static void
 create_cfi_notes (void)
 {
@@ -2692,6 +2771,60 @@  initial_return_save (rtx rtl)
     }
 }
 
+static void
+create_cie_data (void)
+{
+  dw_cfa_location loc;
+  dw_trace_info cie_trace;
+
+  dw_stack_pointer_regnum = DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
+  dw_frame_pointer_regnum = DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM);
+
+  memset (&cie_trace, 0, sizeof(cie_trace));
+  cur_trace = &cie_trace;
+
+  add_cfi_vec = &cie_cfi_vec;
+  cie_cfi_row = cur_row = new_cfi_row ();
+
+  /* On entry, the Canonical Frame Address is at SP.  */
+  memset(&loc, 0, sizeof (loc));
+  loc.reg = dw_stack_pointer_regnum;
+  loc.offset = INCOMING_FRAME_SP_OFFSET;
+  def_cfa_1 (&loc);
+
+  if (targetm.debug_unwind_info () == UI_DWARF2
+      || targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
+    {
+      initial_return_save (INCOMING_RETURN_ADDR_RTX);
+
+      /* For a few targets, we have the return address incoming into a
+	 register, but choose a different return column.  This will result
+	 in a DW_CFA_register for the return, and an entry in
+	 regs_saved_in_regs to match.  If the target later stores that
+	 return address register to the stack, we want to be able to emit
+	 the DW_CFA_offset against the return column, not the intermediate
+	 save register.  Save the contents of regs_saved_in_regs so that
+	 we can re-initialize it at the start of each function.  */
+      switch (VEC_length (reg_saved_in_data, cie_trace.regs_saved_in_regs))
+	{
+	case 0:
+	  break;
+	case 1:
+	  cie_return_save = ggc_alloc_reg_saved_in_data ();
+	  *cie_return_save = *VEC_index (reg_saved_in_data,
+					 cie_trace.regs_saved_in_regs, 0);
+	  VEC_free (reg_saved_in_data, heap, cie_trace.regs_saved_in_regs);
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+    }
+
+  add_cfi_vec = NULL;
+  cur_row = NULL;
+  cur_trace = NULL;
+}
+
 /* Annotate the function with NOTE_INSN_CFI notes to record the CFI
    state at each location within the function.  These notes will be
    emitted during pass_final.  */
@@ -2699,68 +2832,26 @@  initial_return_save (rtx rtl)
 static unsigned int
 execute_dwarf2_frame (void)
 {
+  dw_trace_info dummy_trace;
+
   gcc_checking_assert (queued_reg_saves == NULL);
-  gcc_checking_assert (regs_saved_in_regs == NULL);
 
   /* The first time we're called, compute the incoming frame state.  */
   if (cie_cfi_vec == NULL)
-    {
-      dw_cfa_location loc;
-
-      dw_stack_pointer_regnum = DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
-      dw_frame_pointer_regnum = DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM);
-
-      add_cfi_vec = &cie_cfi_vec;
-      cie_cfi_row = cur_row = new_cfi_row ();
-
-      /* On entry, the Canonical Frame Address is at SP.  */
-      memset(&loc, 0, sizeof (loc));
-      loc.reg = dw_stack_pointer_regnum;
-      loc.offset = INCOMING_FRAME_SP_OFFSET;
-      def_cfa_1 (&loc);
-
-      if (targetm.debug_unwind_info () == UI_DWARF2
-          || targetm_common.except_unwind_info (&global_options) == UI_DWARF2)
-	{
-	  initial_return_save (INCOMING_RETURN_ADDR_RTX);
-
-	  /* For a few targets, we have the return address incoming into a
-	     register, but choose a different return column.  This will result
-	     in a DW_CFA_register for the return, and an entry in
-	     regs_saved_in_regs to match.  If the target later stores that
-	     return address register to the stack, we want to be able to emit
-	     the DW_CFA_offset against the return column, not the intermediate
-	     save register.  Save the contents of regs_saved_in_regs so that
-	     we can re-initialize it at the start of each function.  */
-	  switch (VEC_length (reg_saved_in_data, regs_saved_in_regs))
-	    {
-	    case 0:
-	      break;
-	    case 1:
-	      cie_return_save = ggc_alloc_reg_saved_in_data ();
-	      *cie_return_save = *VEC_index (reg_saved_in_data,
-					     regs_saved_in_regs, 0);
-	      VEC_pop (reg_saved_in_data, regs_saved_in_regs);
-	      break;
-	    default:
-	      gcc_unreachable ();
-	    }
-	}
+    create_cie_data ();
 
-      add_cfi_vec = NULL;
-    }
+  memset (&dummy_trace, 0, sizeof(dummy_trace));
+  cur_trace = &dummy_trace;
 
   /* Set up state for generating call frame debug info.  */
   cur_row = copy_cfi_row (cie_cfi_row);
   if (cie_return_save)
     VEC_safe_push (reg_saved_in_data, heap,
-		   regs_saved_in_regs, cie_return_save);
-
-  cfa_store = cur_row->cfa;
-  args_size = 0;
+		   cur_trace->regs_saved_in_regs, cie_return_save);
 
-  memset (&cfa_temp, 0, sizeof(cfa_temp));
-  cfa_temp.reg = INVALID_REGNUM;
+  cur_trace->cfa_store = cur_row->cfa;
+  cur_trace->cfa_temp.reg = INVALID_REGNUM;
+  queued_args_size = 0;
 
   dwarf2out_alloc_current_fde ();
 
@@ -2771,11 +2862,12 @@  execute_dwarf2_frame (void)
   /* Reset all function-specific information, particularly for GC.  */
   XDELETEVEC (barrier_args_size);
   barrier_args_size = NULL;
-  VEC_free (reg_saved_in_data, heap, regs_saved_in_regs);
+  VEC_free (reg_saved_in_data, heap, cur_trace->regs_saved_in_regs);
   VEC_free (queued_reg_save, heap, queued_reg_saves);
 
   free_cfi_row (cur_row);
   cur_row = NULL;
+  cur_trace = NULL;
 
   return 0;
 }
@@ -2864,7 +2956,7 @@  output_cfa_loc (dw_cfi_ref cfi, int for_eh)
 
   if (cfi->dw_cfi_opc == DW_CFA_expression)
     {
-      unsigned r = 
+      unsigned r =
 	DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
       dw2_asm_output_data (1, r, NULL);
       loc = cfi->dw_cfi_oprnd2.dw_cfi_loc;
@@ -2890,7 +2982,7 @@  output_cfa_loc_raw (dw_cfi_ref cfi)
 
   if (cfi->dw_cfi_opc == DW_CFA_expression)
     {
-      unsigned r = 
+      unsigned r =
 	DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
       fprintf (asm_out_file, "%#x,", r);
       loc = cfi->dw_cfi_oprnd2.dw_cfi_loc;