OSDN Git Service

dwarf2: Move CFI output routines to dwarf2cfi.c.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 9 Jul 2011 20:56:42 +0000 (20:56 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 9 Jul 2011 20:56:42 +0000 (20:56 +0000)
        * defaults.h (DWARF2_ADDR_SIZE, DWARF_OFFSET_SIZE,
        DWARF_TYPE_SIGNATURE_SIZE): Move from ...
        * dwarf2out.c: ... here.
        (output_all_cfis): Remove.
        (dwarf2out_switch_text_section): Use output_cfis directly.
        (size_of_locs): Export.
        (output_loc_sequence, output_loc_sequence_raw): Export.
        (div_data_align, need_data_align_sf_opcode, dwarf_cfi_name, output_cfi,
        output_cfi_directive, dwarf2out_emit_cfi, output_cfis, output_cfa_loc,
        output_cfa_loc_raw): Move to ...
        * dwarfcfi.c: ... here.
        * dwarf2out.h: Update decls.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@176107 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/defaults.h
gcc/dwarf2cfi.c
gcc/dwarf2out.c
gcc/dwarf2out.h

index b0290cd..436e037 100644 (file)
@@ -1,5 +1,20 @@
 2011-07-09  Richard Henderson  <rth@redhat.com>
 
+       * defaults.h (DWARF2_ADDR_SIZE, DWARF_OFFSET_SIZE,
+       DWARF_TYPE_SIGNATURE_SIZE): Move from ...
+       * dwarf2out.c: ... here.
+       (output_all_cfis): Remove.
+       (dwarf2out_switch_text_section): Use output_cfis directly.
+       (size_of_locs): Export.
+       (output_loc_sequence, output_loc_sequence_raw): Export.
+       (div_data_align, need_data_align_sf_opcode, dwarf_cfi_name, output_cfi,
+       output_cfi_directive, dwarf2out_emit_cfi, output_cfis, output_cfa_loc,
+       output_cfa_loc_raw): Move to ...
+       * dwarfcfi.c: ... here.
+       * dwarf2out.h: Update decls.
+
+2011-07-09  Richard Henderson  <rth@redhat.com>
+
        * defaults.h (DWARF_CIE_DATA_ALIGNMENT, DWARF_FRAME_RETURN_COLUMN,
        DWARF_FRAME_REGNUM, DWARF2_FRAME_REG_OUT): Move from ...
        * dwarf2cfi.c: ... here.
index 6bacb3c..70c63ce 100644 (file)
@@ -453,6 +453,28 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) (REGNO)
 #endif
 
+/* The size of addresses as they appear in the Dwarf 2 data.
+   Some architectures use word addresses to refer to code locations,
+   but Dwarf 2 info always uses byte addresses.  On such machines,
+   Dwarf 2 addresses need to be larger than the architecture's
+   pointers.  */
+#ifndef DWARF2_ADDR_SIZE
+#define DWARF2_ADDR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
+#endif
+
+/* The size in bytes of a DWARF field indicating an offset or length
+   relative to a debug info section, specified to be 4 bytes in the
+   DWARF-2 specification.  The SGI/MIPS ABI defines it to be the same
+   as PTR_SIZE.  */
+#ifndef DWARF_OFFSET_SIZE
+#define DWARF_OFFSET_SIZE 4
+#endif
+
+/* The size in bytes of a DWARF 4 type signature.  */
+#ifndef DWARF_TYPE_SIGNATURE_SIZE
+#define DWARF_TYPE_SIGNATURE_SIZE 8
+#endif
+
 /* Default sizes for base C types.  If the sizes are different for
    your target, you should override these values by defining the
    appropriate symbols in your tm.h file.  */
index 28f9b93..5b8420e 100644 (file)
@@ -2553,6 +2553,573 @@ execute_dwarf2_frame (void)
   return 0;
 }
 \f
+/* Convert a DWARF call frame info. operation to its string name */
+
+static const char *
+dwarf_cfi_name (unsigned int cfi_opc)
+{
+  switch (cfi_opc)
+    {
+    case DW_CFA_advance_loc:
+      return "DW_CFA_advance_loc";
+    case DW_CFA_offset:
+      return "DW_CFA_offset";
+    case DW_CFA_restore:
+      return "DW_CFA_restore";
+    case DW_CFA_nop:
+      return "DW_CFA_nop";
+    case DW_CFA_set_loc:
+      return "DW_CFA_set_loc";
+    case DW_CFA_advance_loc1:
+      return "DW_CFA_advance_loc1";
+    case DW_CFA_advance_loc2:
+      return "DW_CFA_advance_loc2";
+    case DW_CFA_advance_loc4:
+      return "DW_CFA_advance_loc4";
+    case DW_CFA_offset_extended:
+      return "DW_CFA_offset_extended";
+    case DW_CFA_restore_extended:
+      return "DW_CFA_restore_extended";
+    case DW_CFA_undefined:
+      return "DW_CFA_undefined";
+    case DW_CFA_same_value:
+      return "DW_CFA_same_value";
+    case DW_CFA_register:
+      return "DW_CFA_register";
+    case DW_CFA_remember_state:
+      return "DW_CFA_remember_state";
+    case DW_CFA_restore_state:
+      return "DW_CFA_restore_state";
+    case DW_CFA_def_cfa:
+      return "DW_CFA_def_cfa";
+    case DW_CFA_def_cfa_register:
+      return "DW_CFA_def_cfa_register";
+    case DW_CFA_def_cfa_offset:
+      return "DW_CFA_def_cfa_offset";
+
+    /* DWARF 3 */
+    case DW_CFA_def_cfa_expression:
+      return "DW_CFA_def_cfa_expression";
+    case DW_CFA_expression:
+      return "DW_CFA_expression";
+    case DW_CFA_offset_extended_sf:
+      return "DW_CFA_offset_extended_sf";
+    case DW_CFA_def_cfa_sf:
+      return "DW_CFA_def_cfa_sf";
+    case DW_CFA_def_cfa_offset_sf:
+      return "DW_CFA_def_cfa_offset_sf";
+
+    /* SGI/MIPS specific */
+    case DW_CFA_MIPS_advance_loc8:
+      return "DW_CFA_MIPS_advance_loc8";
+
+    /* GNU extensions */
+    case DW_CFA_GNU_window_save:
+      return "DW_CFA_GNU_window_save";
+    case DW_CFA_GNU_args_size:
+      return "DW_CFA_GNU_args_size";
+    case DW_CFA_GNU_negative_offset_extended:
+      return "DW_CFA_GNU_negative_offset_extended";
+
+    default:
+      return "DW_CFA_<unknown>";
+    }
+}
+
+/* This routine will generate the correct assembly data for a location
+   description based on a cfi entry with a complex address.  */
+
+static void
+output_cfa_loc (dw_cfi_ref cfi, int for_eh)
+{
+  dw_loc_descr_ref loc;
+  unsigned long size;
+
+  if (cfi->dw_cfi_opc == DW_CFA_expression)
+    {
+      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;
+    }
+  else
+    loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
+
+  /* Output the size of the block.  */
+  size = size_of_locs (loc);
+  dw2_asm_output_data_uleb128 (size, NULL);
+
+  /* Now output the operations themselves.  */
+  output_loc_sequence (loc, for_eh);
+}
+
+/* Similar, but used for .cfi_escape.  */
+
+static void
+output_cfa_loc_raw (dw_cfi_ref cfi)
+{
+  dw_loc_descr_ref loc;
+  unsigned long size;
+
+  if (cfi->dw_cfi_opc == DW_CFA_expression)
+    {
+      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;
+    }
+  else
+    loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
+
+  /* Output the size of the block.  */
+  size = size_of_locs (loc);
+  dw2_asm_output_data_uleb128_raw (size);
+  fputc (',', asm_out_file);
+
+  /* Now output the operations themselves.  */
+  output_loc_sequence_raw (loc);
+}
+
+/* Output a Call Frame Information opcode and its operand(s).  */
+
+void
+output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
+{
+  unsigned long r;
+  HOST_WIDE_INT off;
+
+  if (cfi->dw_cfi_opc == DW_CFA_advance_loc)
+    dw2_asm_output_data (1, (cfi->dw_cfi_opc
+                            | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f)),
+                        "DW_CFA_advance_loc " HOST_WIDE_INT_PRINT_HEX,
+                        ((unsigned HOST_WIDE_INT)
+                         cfi->dw_cfi_oprnd1.dw_cfi_offset));
+  else if (cfi->dw_cfi_opc == DW_CFA_offset)
+    {
+      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+      dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)),
+                          "DW_CFA_offset, column %#lx", r);
+      off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
+      dw2_asm_output_data_uleb128 (off, NULL);
+    }
+  else if (cfi->dw_cfi_opc == DW_CFA_restore)
+    {
+      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+      dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)),
+                          "DW_CFA_restore, column %#lx", r);
+    }
+  else
+    {
+      dw2_asm_output_data (1, cfi->dw_cfi_opc,
+                          "%s", dwarf_cfi_name (cfi->dw_cfi_opc));
+
+      switch (cfi->dw_cfi_opc)
+       {
+       case DW_CFA_set_loc:
+         if (for_eh)
+           dw2_asm_output_encoded_addr_rtx (
+               ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0),
+               gen_rtx_SYMBOL_REF (Pmode, cfi->dw_cfi_oprnd1.dw_cfi_addr),
+               false, NULL);
+         else
+           dw2_asm_output_addr (DWARF2_ADDR_SIZE,
+                                cfi->dw_cfi_oprnd1.dw_cfi_addr, NULL);
+         fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
+         break;
+
+       case DW_CFA_advance_loc1:
+         dw2_asm_output_delta (1, cfi->dw_cfi_oprnd1.dw_cfi_addr,
+                               fde->dw_fde_current_label, NULL);
+         fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
+         break;
+
+       case DW_CFA_advance_loc2:
+         dw2_asm_output_delta (2, cfi->dw_cfi_oprnd1.dw_cfi_addr,
+                               fde->dw_fde_current_label, NULL);
+         fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
+         break;
+
+       case DW_CFA_advance_loc4:
+         dw2_asm_output_delta (4, cfi->dw_cfi_oprnd1.dw_cfi_addr,
+                               fde->dw_fde_current_label, NULL);
+         fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
+         break;
+
+       case DW_CFA_MIPS_advance_loc8:
+         dw2_asm_output_delta (8, cfi->dw_cfi_oprnd1.dw_cfi_addr,
+                               fde->dw_fde_current_label, NULL);
+         fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
+         break;
+
+       case DW_CFA_offset_extended:
+         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+         dw2_asm_output_data_uleb128 (r, NULL);
+         off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
+         dw2_asm_output_data_uleb128 (off, NULL);
+         break;
+
+       case DW_CFA_def_cfa:
+         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+         dw2_asm_output_data_uleb128 (r, NULL);
+         dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
+         break;
+
+       case DW_CFA_offset_extended_sf:
+         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+         dw2_asm_output_data_uleb128 (r, NULL);
+         off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
+         dw2_asm_output_data_sleb128 (off, NULL);
+         break;
+
+       case DW_CFA_def_cfa_sf:
+         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+         dw2_asm_output_data_uleb128 (r, NULL);
+         off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
+         dw2_asm_output_data_sleb128 (off, NULL);
+         break;
+
+       case DW_CFA_restore_extended:
+       case DW_CFA_undefined:
+       case DW_CFA_same_value:
+       case DW_CFA_def_cfa_register:
+         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+         dw2_asm_output_data_uleb128 (r, NULL);
+         break;
+
+       case DW_CFA_register:
+         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+         dw2_asm_output_data_uleb128 (r, NULL);
+         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, for_eh);
+         dw2_asm_output_data_uleb128 (r, NULL);
+         break;
+
+       case DW_CFA_def_cfa_offset:
+       case DW_CFA_GNU_args_size:
+         dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
+         break;
+
+       case DW_CFA_def_cfa_offset_sf:
+         off = div_data_align (cfi->dw_cfi_oprnd1.dw_cfi_offset);
+         dw2_asm_output_data_sleb128 (off, NULL);
+         break;
+
+       case DW_CFA_GNU_window_save:
+         break;
+
+       case DW_CFA_def_cfa_expression:
+       case DW_CFA_expression:
+         output_cfa_loc (cfi, for_eh);
+         break;
+
+       case DW_CFA_GNU_negative_offset_extended:
+         /* Obsoleted by DW_CFA_offset_extended_sf.  */
+         gcc_unreachable ();
+
+       default:
+         break;
+       }
+    }
+}
+
+/* Similar, but do it via assembler directives instead.  */
+
+void
+output_cfi_directive (FILE *f, dw_cfi_ref cfi)
+{
+  unsigned long r, r2;
+
+  switch (cfi->dw_cfi_opc)
+    {
+    case DW_CFA_advance_loc:
+    case DW_CFA_advance_loc1:
+    case DW_CFA_advance_loc2:
+    case DW_CFA_advance_loc4:
+    case DW_CFA_MIPS_advance_loc8:
+    case DW_CFA_set_loc:
+      /* Should only be created in a code path not followed when emitting
+        via directives.  The assembler is going to take care of this for
+        us.  But this routines is also used for debugging dumps, so
+        print something.  */
+      gcc_assert (f != asm_out_file);
+      fprintf (f, "\t.cfi_advance_loc\n");
+      break;
+
+    case DW_CFA_offset:
+    case DW_CFA_offset_extended:
+    case DW_CFA_offset_extended_sf:
+      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
+      fprintf (f, "\t.cfi_offset %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
+              r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
+      break;
+
+    case DW_CFA_restore:
+    case DW_CFA_restore_extended:
+      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
+      fprintf (f, "\t.cfi_restore %lu\n", r);
+      break;
+
+    case DW_CFA_undefined:
+      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
+      fprintf (f, "\t.cfi_undefined %lu\n", r);
+      break;
+
+    case DW_CFA_same_value:
+      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
+      fprintf (f, "\t.cfi_same_value %lu\n", r);
+      break;
+
+    case DW_CFA_def_cfa:
+    case DW_CFA_def_cfa_sf:
+      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
+      fprintf (f, "\t.cfi_def_cfa %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
+              r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
+      break;
+
+    case DW_CFA_def_cfa_register:
+      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
+      fprintf (f, "\t.cfi_def_cfa_register %lu\n", r);
+      break;
+
+    case DW_CFA_register:
+      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
+      r2 = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, 1);
+      fprintf (f, "\t.cfi_register %lu, %lu\n", r, r2);
+      break;
+
+    case DW_CFA_def_cfa_offset:
+    case DW_CFA_def_cfa_offset_sf:
+      fprintf (f, "\t.cfi_def_cfa_offset "
+              HOST_WIDE_INT_PRINT_DEC"\n",
+              cfi->dw_cfi_oprnd1.dw_cfi_offset);
+      break;
+
+    case DW_CFA_remember_state:
+      fprintf (f, "\t.cfi_remember_state\n");
+      break;
+    case DW_CFA_restore_state:
+      fprintf (f, "\t.cfi_restore_state\n");
+      break;
+
+    case DW_CFA_GNU_args_size:
+      if (f == asm_out_file)
+       {
+         fprintf (f, "\t.cfi_escape %#x,", DW_CFA_GNU_args_size);
+         dw2_asm_output_data_uleb128_raw (cfi->dw_cfi_oprnd1.dw_cfi_offset);
+         if (flag_debug_asm)
+           fprintf (f, "\t%s args_size "HOST_WIDE_INT_PRINT_DEC,
+                    ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset);
+         fputc ('\n', f);
+       }
+      else
+       {
+         fprintf (f, "\t.cfi_GNU_args_size "HOST_WIDE_INT_PRINT_DEC "\n",
+                  cfi->dw_cfi_oprnd1.dw_cfi_offset);
+       }
+      break;
+
+    case DW_CFA_GNU_window_save:
+      fprintf (f, "\t.cfi_window_save\n");
+      break;
+
+    case DW_CFA_def_cfa_expression:
+      if (f != asm_out_file)
+       {
+         fprintf (f, "\t.cfi_def_cfa_expression ...\n");
+         break;
+       }
+      /* FALLTHRU */
+    case DW_CFA_expression:
+      if (f != asm_out_file)
+       {
+         fprintf (f, "\t.cfi_cfa_expression ...\n");
+         break;
+       }
+      fprintf (f, "\t.cfi_escape %#x,", cfi->dw_cfi_opc);
+      output_cfa_loc_raw (cfi);
+      fputc ('\n', f);
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+void
+dwarf2out_emit_cfi (dw_cfi_ref cfi)
+{
+  if (dwarf2out_do_cfi_asm ())
+    output_cfi_directive (asm_out_file, cfi);
+}
+
+/* Output CFIs from VEC, up to index UPTO, to bring current FDE to the
+   same state as after executing CFIs in CFI chain.  DO_CFI_ASM is
+   true if .cfi_* directives shall be emitted, false otherwise.  If it
+   is false, FDE and FOR_EH are the other arguments to pass to
+   output_cfi.  */
+
+void
+output_cfis (cfi_vec vec, int upto, bool do_cfi_asm,
+            dw_fde_ref fde, bool for_eh)
+{
+  int ix;
+  struct dw_cfi_struct cfi_buf;
+  dw_cfi_ref cfi2;
+  dw_cfi_ref cfi_args_size = NULL, cfi_cfa = NULL, cfi_cfa_offset = NULL;
+  VEC(dw_cfi_ref, heap) *regs = VEC_alloc (dw_cfi_ref, heap, 32);
+  unsigned int len, idx;
+
+  for (ix = 0; ix < upto + 1; ix++)
+    {
+      dw_cfi_ref cfi = ix < upto ? VEC_index (dw_cfi_ref, vec, ix) : NULL;
+      switch (cfi ? cfi->dw_cfi_opc : DW_CFA_nop)
+       {
+       case DW_CFA_advance_loc:
+       case DW_CFA_advance_loc1:
+       case DW_CFA_advance_loc2:
+       case DW_CFA_advance_loc4:
+       case DW_CFA_MIPS_advance_loc8:
+       case DW_CFA_set_loc:
+         /* All advances should be ignored.  */
+         break;
+       case DW_CFA_remember_state:
+         {
+           dw_cfi_ref args_size = cfi_args_size;
+
+           /* Skip everything between .cfi_remember_state and
+              .cfi_restore_state.  */
+           ix++;
+           if (ix == upto)
+             goto flush_all;
+
+           for (; ix < upto; ix++)
+             {
+               cfi2 = VEC_index (dw_cfi_ref, vec, ix);
+               if (cfi2->dw_cfi_opc == DW_CFA_restore_state)
+                 break;
+               else if (cfi2->dw_cfi_opc == DW_CFA_GNU_args_size)
+                 args_size = cfi2;
+               else
+                 gcc_assert (cfi2->dw_cfi_opc != DW_CFA_remember_state);
+             }
+
+           cfi_args_size = args_size;
+           break;
+         }
+       case DW_CFA_GNU_args_size:
+         cfi_args_size = cfi;
+         break;
+       case DW_CFA_GNU_window_save:
+         goto flush_all;
+       case DW_CFA_offset:
+       case DW_CFA_offset_extended:
+       case DW_CFA_offset_extended_sf:
+       case DW_CFA_restore:
+       case DW_CFA_restore_extended:
+       case DW_CFA_undefined:
+       case DW_CFA_same_value:
+       case DW_CFA_register:
+       case DW_CFA_val_offset:
+       case DW_CFA_val_offset_sf:
+       case DW_CFA_expression:
+       case DW_CFA_val_expression:
+       case DW_CFA_GNU_negative_offset_extended:
+         if (VEC_length (dw_cfi_ref, regs)
+             <= cfi->dw_cfi_oprnd1.dw_cfi_reg_num)
+           VEC_safe_grow_cleared (dw_cfi_ref, heap, regs,
+                                  cfi->dw_cfi_oprnd1.dw_cfi_reg_num + 1);
+         VEC_replace (dw_cfi_ref, regs, cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
+                      cfi);
+         break;
+       case DW_CFA_def_cfa:
+       case DW_CFA_def_cfa_sf:
+       case DW_CFA_def_cfa_expression:
+         cfi_cfa = cfi;
+         cfi_cfa_offset = cfi;
+         break;
+       case DW_CFA_def_cfa_register:
+         cfi_cfa = cfi;
+         break;
+       case DW_CFA_def_cfa_offset:
+       case DW_CFA_def_cfa_offset_sf:
+         cfi_cfa_offset = cfi;
+         break;
+       case DW_CFA_nop:
+         gcc_assert (cfi == NULL);
+       flush_all:
+         len = VEC_length (dw_cfi_ref, regs);
+         for (idx = 0; idx < len; idx++)
+           {
+             cfi2 = VEC_replace (dw_cfi_ref, regs, idx, NULL);
+             if (cfi2 != NULL
+                 && cfi2->dw_cfi_opc != DW_CFA_restore
+                 && cfi2->dw_cfi_opc != DW_CFA_restore_extended)
+               {
+                 if (do_cfi_asm)
+                   output_cfi_directive (asm_out_file, cfi2);
+                 else
+                   output_cfi (cfi2, fde, for_eh);
+               }
+           }
+         if (cfi_cfa && cfi_cfa_offset && cfi_cfa_offset != cfi_cfa)
+           {
+             gcc_assert (cfi_cfa->dw_cfi_opc != DW_CFA_def_cfa_expression);
+             cfi_buf = *cfi_cfa;
+             switch (cfi_cfa_offset->dw_cfi_opc)
+               {
+               case DW_CFA_def_cfa_offset:
+                 cfi_buf.dw_cfi_opc = DW_CFA_def_cfa;
+                 cfi_buf.dw_cfi_oprnd2 = cfi_cfa_offset->dw_cfi_oprnd1;
+                 break;
+               case DW_CFA_def_cfa_offset_sf:
+                 cfi_buf.dw_cfi_opc = DW_CFA_def_cfa_sf;
+                 cfi_buf.dw_cfi_oprnd2 = cfi_cfa_offset->dw_cfi_oprnd1;
+                 break;
+               case DW_CFA_def_cfa:
+               case DW_CFA_def_cfa_sf:
+                 cfi_buf.dw_cfi_opc = cfi_cfa_offset->dw_cfi_opc;
+                 cfi_buf.dw_cfi_oprnd2 = cfi_cfa_offset->dw_cfi_oprnd2;
+                 break;
+               default:
+                 gcc_unreachable ();
+               }
+             cfi_cfa = &cfi_buf;
+           }
+         else if (cfi_cfa_offset)
+           cfi_cfa = cfi_cfa_offset;
+         if (cfi_cfa)
+           {
+             if (do_cfi_asm)
+               output_cfi_directive (asm_out_file, cfi_cfa);
+             else
+               output_cfi (cfi_cfa, fde, for_eh);
+           }
+         cfi_cfa = NULL;
+         cfi_cfa_offset = NULL;
+         if (cfi_args_size
+             && cfi_args_size->dw_cfi_oprnd1.dw_cfi_offset)
+           {
+             if (do_cfi_asm)
+               output_cfi_directive (asm_out_file, cfi_args_size);
+             else
+               output_cfi (cfi_args_size, fde, for_eh);
+           }
+         cfi_args_size = NULL;
+         if (cfi == NULL)
+           {
+             VEC_free (dw_cfi_ref, heap, regs);
+             return;
+           }
+         else if (do_cfi_asm)
+           output_cfi_directive (asm_out_file, cfi);
+         else
+           output_cfi (cfi, fde, for_eh);
+         break;
+       default:
+         gcc_unreachable ();
+       }
+    }
+}
+\f
 
 /* Save the result of dwarf2out_do_frame across PCH.
    This variable is tri-state, with 0 unset, >0 true, <0 false.  */
index 4431655..6469506 100644 (file)
@@ -160,30 +160,6 @@ static GTY(()) section *debug_frame_section;
 /* Maximum size (in bytes) of an artificially generated label.  */
 #define MAX_ARTIFICIAL_LABEL_BYTES     30
 
-/* The size of addresses as they appear in the Dwarf 2 data.
-   Some architectures use word addresses to refer to code locations,
-   but Dwarf 2 info always uses byte addresses.  On such machines,
-   Dwarf 2 addresses need to be larger than the architecture's
-   pointers.  */
-#ifndef DWARF2_ADDR_SIZE
-#define DWARF2_ADDR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
-#endif
-
-/* The size in bytes of a DWARF field indicating an offset or length
-   relative to a debug info section, specified to be 4 bytes in the
-   DWARF-2 specification.  The SGI/MIPS ABI defines it to be the same
-   as PTR_SIZE.  */
-
-#ifndef DWARF_OFFSET_SIZE
-#define DWARF_OFFSET_SIZE 4
-#endif
-
-/* The size in bytes of a DWARF 4 type signature.  */
-
-#ifndef DWARF_TYPE_SIGNATURE_SIZE
-#define DWARF_TYPE_SIGNATURE_SIZE 8
-#endif
-
 /* According to the (draft) DWARF 3 specification, the initial length
    should either be 4 or 12 bytes.  When it's 12 bytes, the first 4
    bytes are 0xffffffff, followed by the length stored in the next 8
@@ -240,14 +216,9 @@ static GTY(()) section *cold_text_section;
 /* Forward declarations for functions defined in this file.  */
 
 static char *stripattributes (const char *);
-static void output_cfi (dw_cfi_ref, dw_fde_ref, int);
 static void output_call_frame_info (int);
 static void dwarf2out_note_section_used (void);
 
-/* Support for complex CFA locations.  */
-static void output_cfa_loc (dw_cfi_ref, int);
-static void output_cfa_loc_raw (dw_cfi_ref);
-
 /* Personality decl of current unit.  Used only when assembler does not support
    personality CFI.  */
 static GTY(()) rtx current_unit_personality;
@@ -391,98 +362,6 @@ stripattributes (const char *s)
   return stripped;
 }
 
-/* Divide OFF by DWARF_CIE_DATA_ALIGNMENT, asserting no remainder.  */
-
-static inline HOST_WIDE_INT
-div_data_align (HOST_WIDE_INT off)
-{
-  HOST_WIDE_INT r = off / DWARF_CIE_DATA_ALIGNMENT;
-  gcc_assert (r * DWARF_CIE_DATA_ALIGNMENT == off);
-  return r;
-}
-
-/* Return true if we need a signed version of a given opcode
-   (e.g. DW_CFA_offset_extended_sf vs DW_CFA_offset_extended).  */
-
-static inline bool
-need_data_align_sf_opcode (HOST_WIDE_INT off)
-{
-  return DWARF_CIE_DATA_ALIGNMENT < 0 ? off > 0 : off < 0;
-}
-
-/* Convert a DWARF call frame info. operation to its string name */
-
-static const char *
-dwarf_cfi_name (unsigned int cfi_opc)
-{
-  switch (cfi_opc)
-    {
-    case DW_CFA_advance_loc:
-      return "DW_CFA_advance_loc";
-    case DW_CFA_offset:
-      return "DW_CFA_offset";
-    case DW_CFA_restore:
-      return "DW_CFA_restore";
-    case DW_CFA_nop:
-      return "DW_CFA_nop";
-    case DW_CFA_set_loc:
-      return "DW_CFA_set_loc";
-    case DW_CFA_advance_loc1:
-      return "DW_CFA_advance_loc1";
-    case DW_CFA_advance_loc2:
-      return "DW_CFA_advance_loc2";
-    case DW_CFA_advance_loc4:
-      return "DW_CFA_advance_loc4";
-    case DW_CFA_offset_extended:
-      return "DW_CFA_offset_extended";
-    case DW_CFA_restore_extended:
-      return "DW_CFA_restore_extended";
-    case DW_CFA_undefined:
-      return "DW_CFA_undefined";
-    case DW_CFA_same_value:
-      return "DW_CFA_same_value";
-    case DW_CFA_register:
-      return "DW_CFA_register";
-    case DW_CFA_remember_state:
-      return "DW_CFA_remember_state";
-    case DW_CFA_restore_state:
-      return "DW_CFA_restore_state";
-    case DW_CFA_def_cfa:
-      return "DW_CFA_def_cfa";
-    case DW_CFA_def_cfa_register:
-      return "DW_CFA_def_cfa_register";
-    case DW_CFA_def_cfa_offset:
-      return "DW_CFA_def_cfa_offset";
-
-    /* DWARF 3 */
-    case DW_CFA_def_cfa_expression:
-      return "DW_CFA_def_cfa_expression";
-    case DW_CFA_expression:
-      return "DW_CFA_expression";
-    case DW_CFA_offset_extended_sf:
-      return "DW_CFA_offset_extended_sf";
-    case DW_CFA_def_cfa_sf:
-      return "DW_CFA_def_cfa_sf";
-    case DW_CFA_def_cfa_offset_sf:
-      return "DW_CFA_def_cfa_offset_sf";
-
-    /* SGI/MIPS specific */
-    case DW_CFA_MIPS_advance_loc8:
-      return "DW_CFA_MIPS_advance_loc8";
-
-    /* GNU extensions */
-    case DW_CFA_GNU_window_save:
-      return "DW_CFA_GNU_window_save";
-    case DW_CFA_GNU_args_size:
-      return "DW_CFA_GNU_args_size";
-    case DW_CFA_GNU_negative_offset_extended:
-      return "DW_CFA_GNU_negative_offset_extended";
-
-    default:
-      return "DW_CFA_<unknown>";
-    }
-}
-
 /* Switch [BACK] to eh_frame_section.  If we don't have an eh_frame_section,
    switch to the data section instead, and write out a synthetic start label
    for collect2 the first time around.  */
@@ -632,454 +511,6 @@ dw_cfi_oprnd2_desc (enum dwarf_call_frame_info cfi)
     }
 }
 
-/* Output a Call Frame Information opcode and its operand(s).  */
-
-static void
-output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
-{
-  unsigned long r;
-  HOST_WIDE_INT off;
-
-  if (cfi->dw_cfi_opc == DW_CFA_advance_loc)
-    dw2_asm_output_data (1, (cfi->dw_cfi_opc
-                            | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f)),
-                        "DW_CFA_advance_loc " HOST_WIDE_INT_PRINT_HEX,
-                        ((unsigned HOST_WIDE_INT)
-                         cfi->dw_cfi_oprnd1.dw_cfi_offset));
-  else if (cfi->dw_cfi_opc == DW_CFA_offset)
-    {
-      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
-      dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)),
-                          "DW_CFA_offset, column %#lx", r);
-      off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
-      dw2_asm_output_data_uleb128 (off, NULL);
-    }
-  else if (cfi->dw_cfi_opc == DW_CFA_restore)
-    {
-      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
-      dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)),
-                          "DW_CFA_restore, column %#lx", r);
-    }
-  else
-    {
-      dw2_asm_output_data (1, cfi->dw_cfi_opc,
-                          "%s", dwarf_cfi_name (cfi->dw_cfi_opc));
-
-      switch (cfi->dw_cfi_opc)
-       {
-       case DW_CFA_set_loc:
-         if (for_eh)
-           dw2_asm_output_encoded_addr_rtx (
-               ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0),
-               gen_rtx_SYMBOL_REF (Pmode, cfi->dw_cfi_oprnd1.dw_cfi_addr),
-               false, NULL);
-         else
-           dw2_asm_output_addr (DWARF2_ADDR_SIZE,
-                                cfi->dw_cfi_oprnd1.dw_cfi_addr, NULL);
-         fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
-         break;
-
-       case DW_CFA_advance_loc1:
-         dw2_asm_output_delta (1, cfi->dw_cfi_oprnd1.dw_cfi_addr,
-                               fde->dw_fde_current_label, NULL);
-         fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
-         break;
-
-       case DW_CFA_advance_loc2:
-         dw2_asm_output_delta (2, cfi->dw_cfi_oprnd1.dw_cfi_addr,
-                               fde->dw_fde_current_label, NULL);
-         fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
-         break;
-
-       case DW_CFA_advance_loc4:
-         dw2_asm_output_delta (4, cfi->dw_cfi_oprnd1.dw_cfi_addr,
-                               fde->dw_fde_current_label, NULL);
-         fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
-         break;
-
-       case DW_CFA_MIPS_advance_loc8:
-         dw2_asm_output_delta (8, cfi->dw_cfi_oprnd1.dw_cfi_addr,
-                               fde->dw_fde_current_label, NULL);
-         fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
-         break;
-
-       case DW_CFA_offset_extended:
-         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
-         dw2_asm_output_data_uleb128 (r, NULL);
-         off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
-         dw2_asm_output_data_uleb128 (off, NULL);
-         break;
-
-       case DW_CFA_def_cfa:
-         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
-         dw2_asm_output_data_uleb128 (r, NULL);
-         dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
-         break;
-
-       case DW_CFA_offset_extended_sf:
-         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
-         dw2_asm_output_data_uleb128 (r, NULL);
-         off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
-         dw2_asm_output_data_sleb128 (off, NULL);
-         break;
-
-       case DW_CFA_def_cfa_sf:
-         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
-         dw2_asm_output_data_uleb128 (r, NULL);
-         off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
-         dw2_asm_output_data_sleb128 (off, NULL);
-         break;
-
-       case DW_CFA_restore_extended:
-       case DW_CFA_undefined:
-       case DW_CFA_same_value:
-       case DW_CFA_def_cfa_register:
-         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
-         dw2_asm_output_data_uleb128 (r, NULL);
-         break;
-
-       case DW_CFA_register:
-         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
-         dw2_asm_output_data_uleb128 (r, NULL);
-         r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, for_eh);
-         dw2_asm_output_data_uleb128 (r, NULL);
-         break;
-
-       case DW_CFA_def_cfa_offset:
-       case DW_CFA_GNU_args_size:
-         dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
-         break;
-
-       case DW_CFA_def_cfa_offset_sf:
-         off = div_data_align (cfi->dw_cfi_oprnd1.dw_cfi_offset);
-         dw2_asm_output_data_sleb128 (off, NULL);
-         break;
-
-       case DW_CFA_GNU_window_save:
-         break;
-
-       case DW_CFA_def_cfa_expression:
-       case DW_CFA_expression:
-         output_cfa_loc (cfi, for_eh);
-         break;
-
-       case DW_CFA_GNU_negative_offset_extended:
-         /* Obsoleted by DW_CFA_offset_extended_sf.  */
-         gcc_unreachable ();
-
-       default:
-         break;
-       }
-    }
-}
-
-/* Similar, but do it via assembler directives instead.  */
-
-void
-output_cfi_directive (FILE *f, dw_cfi_ref cfi)
-{
-  unsigned long r, r2;
-
-  switch (cfi->dw_cfi_opc)
-    {
-    case DW_CFA_advance_loc:
-    case DW_CFA_advance_loc1:
-    case DW_CFA_advance_loc2:
-    case DW_CFA_advance_loc4:
-    case DW_CFA_MIPS_advance_loc8:
-    case DW_CFA_set_loc:
-      /* Should only be created in a code path not followed when emitting
-        via directives.  The assembler is going to take care of this for
-        us.  But this routines is also used for debugging dumps, so
-        print something.  */
-      gcc_assert (f != asm_out_file);
-      fprintf (f, "\t.cfi_advance_loc\n");
-      break;
-
-    case DW_CFA_offset:
-    case DW_CFA_offset_extended:
-    case DW_CFA_offset_extended_sf:
-      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
-      fprintf (f, "\t.cfi_offset %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
-              r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
-      break;
-
-    case DW_CFA_restore:
-    case DW_CFA_restore_extended:
-      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
-      fprintf (f, "\t.cfi_restore %lu\n", r);
-      break;
-
-    case DW_CFA_undefined:
-      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
-      fprintf (f, "\t.cfi_undefined %lu\n", r);
-      break;
-
-    case DW_CFA_same_value:
-      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
-      fprintf (f, "\t.cfi_same_value %lu\n", r);
-      break;
-
-    case DW_CFA_def_cfa:
-    case DW_CFA_def_cfa_sf:
-      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
-      fprintf (f, "\t.cfi_def_cfa %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
-              r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
-      break;
-
-    case DW_CFA_def_cfa_register:
-      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
-      fprintf (f, "\t.cfi_def_cfa_register %lu\n", r);
-      break;
-
-    case DW_CFA_register:
-      r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
-      r2 = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, 1);
-      fprintf (f, "\t.cfi_register %lu, %lu\n", r, r2);
-      break;
-
-    case DW_CFA_def_cfa_offset:
-    case DW_CFA_def_cfa_offset_sf:
-      fprintf (f, "\t.cfi_def_cfa_offset "
-              HOST_WIDE_INT_PRINT_DEC"\n",
-              cfi->dw_cfi_oprnd1.dw_cfi_offset);
-      break;
-
-    case DW_CFA_remember_state:
-      fprintf (f, "\t.cfi_remember_state\n");
-      break;
-    case DW_CFA_restore_state:
-      fprintf (f, "\t.cfi_restore_state\n");
-      break;
-
-    case DW_CFA_GNU_args_size:
-      if (f == asm_out_file)
-       {
-         fprintf (f, "\t.cfi_escape %#x,", DW_CFA_GNU_args_size);
-         dw2_asm_output_data_uleb128_raw (cfi->dw_cfi_oprnd1.dw_cfi_offset);
-         if (flag_debug_asm)
-           fprintf (f, "\t%s args_size "HOST_WIDE_INT_PRINT_DEC,
-                    ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset);
-         fputc ('\n', f);
-       }
-      else
-       {
-         fprintf (f, "\t.cfi_GNU_args_size "HOST_WIDE_INT_PRINT_DEC "\n",
-                  cfi->dw_cfi_oprnd1.dw_cfi_offset);
-       }
-      break;
-
-    case DW_CFA_GNU_window_save:
-      fprintf (f, "\t.cfi_window_save\n");
-      break;
-
-    case DW_CFA_def_cfa_expression:
-      if (f != asm_out_file)
-       {
-         fprintf (f, "\t.cfi_def_cfa_expression ...\n");
-         break;
-       }
-      /* FALLTHRU */
-    case DW_CFA_expression:
-      if (f != asm_out_file)
-       {
-         fprintf (f, "\t.cfi_cfa_expression ...\n");
-         break;
-       }
-      fprintf (f, "\t.cfi_escape %#x,", cfi->dw_cfi_opc);
-      output_cfa_loc_raw (cfi);
-      fputc ('\n', f);
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-}
-
-void
-dwarf2out_emit_cfi (dw_cfi_ref cfi)
-{
-  if (dwarf2out_do_cfi_asm ())
-    output_cfi_directive (asm_out_file, cfi);
-}
-
-/* Output CFIs from VEC, up to index UPTO, to bring current FDE to the
-   same state as after executing CFIs in CFI chain.  DO_CFI_ASM is
-   true if .cfi_* directives shall be emitted, false otherwise.  If it
-   is false, FDE and FOR_EH are the other arguments to pass to
-   output_cfi.  */
-
-static void
-output_cfis (cfi_vec vec, int upto, bool do_cfi_asm,
-            dw_fde_ref fde, bool for_eh)
-{
-  int ix;
-  struct dw_cfi_struct cfi_buf;
-  dw_cfi_ref cfi2;
-  dw_cfi_ref cfi_args_size = NULL, cfi_cfa = NULL, cfi_cfa_offset = NULL;
-  VEC(dw_cfi_ref, heap) *regs = VEC_alloc (dw_cfi_ref, heap, 32);
-  unsigned int len, idx;
-
-  for (ix = 0; ix < upto + 1; ix++)
-    {
-      dw_cfi_ref cfi = ix < upto ? VEC_index (dw_cfi_ref, vec, ix) : NULL;
-      switch (cfi ? cfi->dw_cfi_opc : DW_CFA_nop)
-       {
-       case DW_CFA_advance_loc:
-       case DW_CFA_advance_loc1:
-       case DW_CFA_advance_loc2:
-       case DW_CFA_advance_loc4:
-       case DW_CFA_MIPS_advance_loc8:
-       case DW_CFA_set_loc:
-         /* All advances should be ignored.  */
-         break;
-       case DW_CFA_remember_state:
-         {
-           dw_cfi_ref args_size = cfi_args_size;
-
-           /* Skip everything between .cfi_remember_state and
-              .cfi_restore_state.  */
-           ix++;
-           if (ix == upto)
-             goto flush_all;
-
-           for (; ix < upto; ix++)
-             {
-               cfi2 = VEC_index (dw_cfi_ref, vec, ix);
-               if (cfi2->dw_cfi_opc == DW_CFA_restore_state)
-                 break;
-               else if (cfi2->dw_cfi_opc == DW_CFA_GNU_args_size)
-                 args_size = cfi2;
-               else
-                 gcc_assert (cfi2->dw_cfi_opc != DW_CFA_remember_state);
-             }
-
-           cfi_args_size = args_size;
-           break;
-         }
-       case DW_CFA_GNU_args_size:
-         cfi_args_size = cfi;
-         break;
-       case DW_CFA_GNU_window_save:
-         goto flush_all;
-       case DW_CFA_offset:
-       case DW_CFA_offset_extended:
-       case DW_CFA_offset_extended_sf:
-       case DW_CFA_restore:
-       case DW_CFA_restore_extended:
-       case DW_CFA_undefined:
-       case DW_CFA_same_value:
-       case DW_CFA_register:
-       case DW_CFA_val_offset:
-       case DW_CFA_val_offset_sf:
-       case DW_CFA_expression:
-       case DW_CFA_val_expression:
-       case DW_CFA_GNU_negative_offset_extended:
-         if (VEC_length (dw_cfi_ref, regs)
-             <= cfi->dw_cfi_oprnd1.dw_cfi_reg_num)
-           VEC_safe_grow_cleared (dw_cfi_ref, heap, regs,
-                                  cfi->dw_cfi_oprnd1.dw_cfi_reg_num + 1);
-         VEC_replace (dw_cfi_ref, regs, cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
-                      cfi);
-         break;
-       case DW_CFA_def_cfa:
-       case DW_CFA_def_cfa_sf:
-       case DW_CFA_def_cfa_expression:
-         cfi_cfa = cfi;
-         cfi_cfa_offset = cfi;
-         break;
-       case DW_CFA_def_cfa_register:
-         cfi_cfa = cfi;
-         break;
-       case DW_CFA_def_cfa_offset:
-       case DW_CFA_def_cfa_offset_sf:
-         cfi_cfa_offset = cfi;
-         break;
-       case DW_CFA_nop:
-         gcc_assert (cfi == NULL);
-       flush_all:
-         len = VEC_length (dw_cfi_ref, regs);
-         for (idx = 0; idx < len; idx++)
-           {
-             cfi2 = VEC_replace (dw_cfi_ref, regs, idx, NULL);
-             if (cfi2 != NULL
-                 && cfi2->dw_cfi_opc != DW_CFA_restore
-                 && cfi2->dw_cfi_opc != DW_CFA_restore_extended)
-               {
-                 if (do_cfi_asm)
-                   output_cfi_directive (asm_out_file, cfi2);
-                 else
-                   output_cfi (cfi2, fde, for_eh);
-               }
-           }
-         if (cfi_cfa && cfi_cfa_offset && cfi_cfa_offset != cfi_cfa)
-           {
-             gcc_assert (cfi_cfa->dw_cfi_opc != DW_CFA_def_cfa_expression);
-             cfi_buf = *cfi_cfa;
-             switch (cfi_cfa_offset->dw_cfi_opc)
-               {
-               case DW_CFA_def_cfa_offset:
-                 cfi_buf.dw_cfi_opc = DW_CFA_def_cfa;
-                 cfi_buf.dw_cfi_oprnd2 = cfi_cfa_offset->dw_cfi_oprnd1;
-                 break;
-               case DW_CFA_def_cfa_offset_sf:
-                 cfi_buf.dw_cfi_opc = DW_CFA_def_cfa_sf;
-                 cfi_buf.dw_cfi_oprnd2 = cfi_cfa_offset->dw_cfi_oprnd1;
-                 break;
-               case DW_CFA_def_cfa:
-               case DW_CFA_def_cfa_sf:
-                 cfi_buf.dw_cfi_opc = cfi_cfa_offset->dw_cfi_opc;
-                 cfi_buf.dw_cfi_oprnd2 = cfi_cfa_offset->dw_cfi_oprnd2;
-                 break;
-               default:
-                 gcc_unreachable ();
-               }
-             cfi_cfa = &cfi_buf;
-           }
-         else if (cfi_cfa_offset)
-           cfi_cfa = cfi_cfa_offset;
-         if (cfi_cfa)
-           {
-             if (do_cfi_asm)
-               output_cfi_directive (asm_out_file, cfi_cfa);
-             else
-               output_cfi (cfi_cfa, fde, for_eh);
-           }
-         cfi_cfa = NULL;
-         cfi_cfa_offset = NULL;
-         if (cfi_args_size
-             && cfi_args_size->dw_cfi_oprnd1.dw_cfi_offset)
-           {
-             if (do_cfi_asm)
-               output_cfi_directive (asm_out_file, cfi_args_size);
-             else
-               output_cfi (cfi_args_size, fde, for_eh);
-           }
-         cfi_args_size = NULL;
-         if (cfi == NULL)
-           {
-             VEC_free (dw_cfi_ref, heap, regs);
-             return;
-           }
-         else if (do_cfi_asm)
-           output_cfi_directive (asm_out_file, cfi);
-         else
-           output_cfi (cfi, fde, for_eh);
-         break;
-       default:
-         gcc_unreachable ();
-       }
-    }
-}
-
-/* Like output_cfis, but emit all CFIs in the vector.  */
-static void
-output_all_cfis (cfi_vec vec, bool do_cfi_asm,
-                dw_fde_ref fde, bool for_eh)
-{
-  output_cfis (vec, VEC_length (dw_cfi_ref, vec), do_cfi_asm, fde, for_eh);
-}
-
 /* Output one FDE.  */
 
 static void
@@ -1752,14 +1183,17 @@ dwarf2out_switch_text_section (void)
     = (sect == text_section
        || (cold_text_section && sect == cold_text_section));
 
+  fde->dw_fde_switch_cfi_index = VEC_length (dw_cfi_ref, fde->dw_fde_cfi);
+
   if (dwarf2out_do_cfi_asm ())
     {
       dwarf2out_do_cfi_startproc (true);
       /* As this is a different FDE, insert all current CFI instructions
         again.  */
-      output_all_cfis (fde->dw_fde_cfi, true, fde, true);
+      output_cfis (fde->dw_fde_cfi, fde->dw_fde_switch_cfi_index,
+                  true, fde, true);
     }
-  fde->dw_fde_switch_cfi_index = VEC_length (dw_cfi_ref, fde->dw_fde_cfi);
+
   var_location_switch_text_section ();
 
   set_cur_line_info_table (sect);
@@ -2258,7 +1692,6 @@ loc_list_plus_const (dw_loc_list_ref list_head, HOST_WIDE_INT offset)
 #define DWARF_REF_SIZE \
   (dwarf_version == 2 ? DWARF2_ADDR_SIZE : DWARF_OFFSET_SIZE)
 
-static unsigned long size_of_locs (dw_loc_descr_ref);
 static unsigned long int get_base_type_offset (dw_die_ref);
 
 /* Return the size of a location descriptor.  */
@@ -2442,7 +1875,7 @@ size_of_loc_descr (dw_loc_descr_ref loc)
 
 /* Return the size of a series of location descriptors.  */
 
-static unsigned long
+unsigned long
 size_of_locs (dw_loc_descr_ref loc)
 {
   dw_loc_descr_ref l;
@@ -2471,7 +1904,6 @@ size_of_locs (dw_loc_descr_ref loc)
 static HOST_WIDE_INT extract_int (const unsigned char *, unsigned);
 static void get_ref_die_offset_label (char *, dw_die_ref);
 static unsigned long int get_ref_die_offset (dw_die_ref);
-static void output_loc_sequence (dw_loc_descr_ref, int);
 
 /* Output location description stack opcode's operands (if any).
    The for_eh_or_skip parameter controls whether register numbers are
@@ -2841,7 +2273,7 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
    info).  This should be suppressed for the cases that have not been converted
    (i.e. symbolic debug info), by setting the parameter < 0.  See PR47324.  */
 
-static void
+void
 output_loc_sequence (dw_loc_descr_ref loc, int for_eh_or_skip)
 {
   for (; loc != NULL; loc = loc->dw_loc_next)
@@ -3020,7 +2452,7 @@ output_loc_operands_raw (dw_loc_descr_ref loc)
     }
 }
 
-static void
+void
 output_loc_sequence_raw (dw_loc_descr_ref loc)
 {
   while (1)
@@ -3053,60 +2485,6 @@ output_loc_sequence_raw (dw_loc_descr_ref loc)
     }
 }
 
-/* This routine will generate the correct assembly data for a location
-   description based on a cfi entry with a complex address.  */
-
-static void
-output_cfa_loc (dw_cfi_ref cfi, int for_eh)
-{
-  dw_loc_descr_ref loc;
-  unsigned long size;
-
-  if (cfi->dw_cfi_opc == DW_CFA_expression)
-    {
-      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;
-    }
-  else
-    loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
-
-  /* Output the size of the block.  */
-  size = size_of_locs (loc);
-  dw2_asm_output_data_uleb128 (size, NULL);
-
-  /* Now output the operations themselves.  */
-  output_loc_sequence (loc, for_eh);
-}
-
-/* Similar, but used for .cfi_escape.  */
-
-static void
-output_cfa_loc_raw (dw_cfi_ref cfi)
-{
-  dw_loc_descr_ref loc;
-  unsigned long size;
-
-  if (cfi->dw_cfi_opc == DW_CFA_expression)
-    {
-      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;
-    }
-  else
-    loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
-
-  /* Output the size of the block.  */
-  size = size_of_locs (loc);
-  dw2_asm_output_data_uleb128_raw (size);
-  fputc (',', asm_out_file);
-
-  /* Now output the operations themselves.  */
-  output_loc_sequence_raw (loc);
-}
-
 /* This function builds a dwarf location descriptor sequence from a
    dw_cfa_location, adding the given OFFSET to the result of the
    expression.  */
index 19bae4a..d41453b 100644 (file)
@@ -228,11 +228,18 @@ extern struct dw_loc_descr_struct *mem_loc_descriptor
 extern enum machine_mode get_address_mode (rtx mem);
 extern dw_fde_ref dwarf2out_alloc_current_fde (void);
 
+extern unsigned long size_of_locs (dw_loc_descr_ref);
+extern void output_loc_sequence (dw_loc_descr_ref, int);
+extern void output_loc_sequence_raw (dw_loc_descr_ref);
+
 /* Interface from dwarf2cfi.c to dwarf2out.c.  */
 extern void lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc,
                          dw_cfa_location *remember);
 extern bool cfa_equal_p (const dw_cfa_location *, const dw_cfa_location *);
 
+extern void output_cfi (dw_cfi_ref, dw_fde_ref, int);
+extern void output_cfis (cfi_vec, int, bool, dw_fde_ref, bool);
+
 extern GTY(()) cfi_vec cie_cfi_vec;
 
 /* Interface from dwarf2*.c to the rest of the compiler.  */