From: Richard Henderson Date: Sat, 9 Jul 2011 20:56:42 +0000 (-0700) Subject: dwarf2: Move CFI output routines to dwarf2cfi.c. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=948d330ea91565b5327304c63ec36e85c1355f9f;p=gcc.git dwarf2: Move CFI output routines to dwarf2cfi.c. * 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. From-SVN: r176107 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b0290cdf6ef..436e037cb36 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2011-07-09 Richard Henderson + + * 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 * defaults.h (DWARF_CIE_DATA_ALIGNMENT, DWARF_FRAME_RETURN_COLUMN, 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_"; + } +} + +/* 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_"; - } -} - /* 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. */