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
This commit is contained in:
parent
db42e39d81
commit
948d330ea9
5 changed files with 619 additions and 630 deletions
|
@ -1,3 +1,18 @@
|
|||
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,
|
||||
|
|
|
@ -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. */
|
||||
|
|
567
gcc/dwarf2cfi.c
567
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. */
|
||||
|
|
638
gcc/dwarf2out.c
638
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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Add table
Reference in a new issue