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:
Richard Henderson 2011-07-09 13:56:42 -07:00 committed by Richard Henderson
parent db42e39d81
commit 948d330ea9
5 changed files with 619 additions and 630 deletions

View file

@ -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,

View file

@ -453,6 +453,28 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) (REGNO)
#endif
/* The size of addresses as they appear in the Dwarf 2 data.
Some architectures use word addresses to refer to code locations,
but Dwarf 2 info always uses byte addresses. On such machines,
Dwarf 2 addresses need to be larger than the architecture's
pointers. */
#ifndef DWARF2_ADDR_SIZE
#define DWARF2_ADDR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
#endif
/* The size in bytes of a DWARF field indicating an offset or length
relative to a debug info section, specified to be 4 bytes in the
DWARF-2 specification. The SGI/MIPS ABI defines it to be the same
as PTR_SIZE. */
#ifndef DWARF_OFFSET_SIZE
#define DWARF_OFFSET_SIZE 4
#endif
/* The size in bytes of a DWARF 4 type signature. */
#ifndef DWARF_TYPE_SIGNATURE_SIZE
#define DWARF_TYPE_SIGNATURE_SIZE 8
#endif
/* Default sizes for base C types. If the sizes are different for
your target, you should override these values by defining the
appropriate symbols in your tm.h file. */

View file

@ -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. */

View file

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

View file

@ -228,11 +228,18 @@ extern struct dw_loc_descr_struct *mem_loc_descriptor
extern enum machine_mode get_address_mode (rtx mem);
extern dw_fde_ref dwarf2out_alloc_current_fde (void);
extern unsigned long size_of_locs (dw_loc_descr_ref);
extern void output_loc_sequence (dw_loc_descr_ref, int);
extern void output_loc_sequence_raw (dw_loc_descr_ref);
/* Interface from dwarf2cfi.c to dwarf2out.c. */
extern void lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc,
dw_cfa_location *remember);
extern bool cfa_equal_p (const dw_cfa_location *, const dw_cfa_location *);
extern void output_cfi (dw_cfi_ref, dw_fde_ref, int);
extern void output_cfis (cfi_vec, int, bool, dw_fde_ref, bool);
extern GTY(()) cfi_vec cie_cfi_vec;
/* Interface from dwarf2*.c to the rest of the compiler. */