summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/defaults.h22
-rw-r--r--gcc/dwarf2cfi.c567
-rw-r--r--gcc/dwarf2out.c638
-rw-r--r--gcc/dwarf2out.h7
5 files changed, 619 insertions, 630 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b0290cdf6ef..436e037cb36 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 6bacb3c0139..70c63cecc31 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -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. */
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index 28f9b938a2a..5b8420e8f85 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -2553,6 +2553,573 @@ execute_dwarf2_frame (void)
return 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>";
+ }
+}
+
+/* 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 ();
+ }
+ }
+}
+
/* Save the result of dwarf2out_do_frame across PCH.
This variable is tri-state, with 0 unset, >0 true, <0 false. */
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 4431655af6a..64695060c3b 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -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. */
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 19bae4aaa3b..d41453bacea 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -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. */