Commit 57e16c96 by Richard Henderson Committed by Richard Henderson

dwarf2cfi: Implement change_cfi_row.

Add a generic function to adjust cfi state from one row to another.
Use this to implement text section switching.  This will also be
usable for arbitrary changes around a cfg for shrink-wrapping.

        * dwarf2cfi.c (add_cfi_args_size): Split out from...
        (dwarf2out_args_size): ... here.
        (add_cfi_restore): Split out from ...
        (dwarf2out_frame_debug_cfa_restore): ... here.
        (def_cfa_0): Split out from ...
        (def_cfa_1): ... here.
        (cfi_oprnd_equal_p, cfi_equal_p): New.
        (change_cfi_row): New.
        (add_cfis_to_fde): Set fde->dw_fde_switch_cfi_index.
        (create_cfi_notes): Use change_cfi_row at SWITCH_TEXT note.
        (output_cfis): Remove.
        * dwarf2out.c (output_fde): Simplify output_cfi loop.
        (dwarf2out_switch_text_section): Don't call output_cfis.
        (dw_val_equal_p, loc_descr_equal_p_1, loc_descr_equal_p): New.
        * dwarf2out.h: Update decls.
        (enum dw_val_class): Add dw_val_class_none.

From-SVN: r176700
parent f1a0e830
2011-07-23 Richard Henderson <rth@redhat.com> 2011-07-23 Richard Henderson <rth@redhat.com>
* dwarf2cfi.c (add_cfi_args_size): Split out from...
(dwarf2out_args_size): ... here.
(add_cfi_restore): Split out from ...
(dwarf2out_frame_debug_cfa_restore): ... here.
(def_cfa_0): Split out from ...
(def_cfa_1): ... here.
(cfi_oprnd_equal_p, cfi_equal_p): New.
(change_cfi_row): New.
(add_cfis_to_fde): Set fde->dw_fde_switch_cfi_index.
(create_cfi_notes): Use change_cfi_row at SWITCH_TEXT note.
(output_cfis): Remove.
* dwarf2out.c (output_fde): Simplify output_cfi loop.
(dwarf2out_switch_text_section): Don't call output_cfis.
(dw_val_equal_p, loc_descr_equal_p_1, loc_descr_equal_p): New.
* dwarf2out.h: Update decls.
(enum dw_val_class): Add dw_val_class_none.
2011-07-23 Richard Henderson <rth@redhat.com>
* dwarf2cfi.c (update_row_reg_save): New. * dwarf2cfi.c (update_row_reg_save): New.
(dwarf2out_frame_debug_cfa_expression): Use it. (dwarf2out_frame_debug_cfa_expression): Use it.
(dwarf2out_frame_debug_cfa_restore): Likewise. (dwarf2out_frame_debug_cfa_restore): Likewise.
......
...@@ -519,11 +519,9 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second, ...@@ -519,11 +519,9 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second,
char *section_start_label, int fde_encoding, char *augmentation, char *section_start_label, int fde_encoding, char *augmentation,
bool any_lsda_needed, int lsda_encoding) bool any_lsda_needed, int lsda_encoding)
{ {
int ix;
const char *begin, *end; const char *begin, *end;
static unsigned int j; static unsigned int j;
char l1[20], l2[20]; char l1[20], l2[20];
dw_cfi_ref cfi;
targetm.asm_out.emit_unwind_label (asm_out_file, fde->decl, for_eh, targetm.asm_out.emit_unwind_label (asm_out_file, fde->decl, for_eh,
/* empty */ 0); /* empty */ 0);
...@@ -603,36 +601,24 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second, ...@@ -603,36 +601,24 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second,
dw2_asm_output_data_uleb128 (0, "Augmentation size"); dw2_asm_output_data_uleb128 (0, "Augmentation size");
} }
/* Loop through the Call Frame Instructions associated with /* Loop through the Call Frame Instructions associated with this FDE. */
this FDE. */
fde->dw_fde_current_label = begin; fde->dw_fde_current_label = begin;
if (fde->dw_fde_second_begin == NULL) {
FOR_EACH_VEC_ELT (dw_cfi_ref, fde->dw_fde_cfi, ix, cfi) size_t from, until, i;
output_cfi (cfi, fde, for_eh);
else if (!second)
{
if (fde->dw_fde_switch_cfi_index > 0)
FOR_EACH_VEC_ELT (dw_cfi_ref, fde->dw_fde_cfi, ix, cfi)
{
if (ix == fde->dw_fde_switch_cfi_index)
break;
output_cfi (cfi, fde, for_eh);
}
}
else
{
int i, from = 0;
int until = VEC_length (dw_cfi_ref, fde->dw_fde_cfi);
if (fde->dw_fde_switch_cfi_index > 0) from = 0;
{ until = VEC_length (dw_cfi_ref, fde->dw_fde_cfi);
from = fde->dw_fde_switch_cfi_index;
output_cfis (fde->dw_fde_cfi, from, false, fde, for_eh); if (fde->dw_fde_second_begin == NULL)
} ;
for (i = from; i < until; i++) else if (!second)
output_cfi (VEC_index (dw_cfi_ref, fde->dw_fde_cfi, i), until = fde->dw_fde_switch_cfi_index;
fde, for_eh); else
} from = fde->dw_fde_switch_cfi_index;
for (i = from; i < until; i++)
output_cfi (VEC_index (dw_cfi_ref, fde->dw_fde_cfi, i), fde, for_eh);
}
/* If we are to emit a ref/link from function bodies to their frame tables, /* If we are to emit a ref/link from function bodies to their frame tables,
do it now. This is typically performed to make sure that tables do it now. This is typically performed to make sure that tables
...@@ -1184,16 +1170,8 @@ dwarf2out_switch_text_section (void) ...@@ -1184,16 +1170,8 @@ dwarf2out_switch_text_section (void)
= (sect == text_section = (sect == text_section
|| (cold_text_section && sect == cold_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 ()) if (dwarf2out_do_cfi_asm ())
{ dwarf2out_do_cfi_startproc (true);
dwarf2out_do_cfi_startproc (true);
/* As this is a different FDE, insert all current CFI instructions
again. */
output_cfis (fde->dw_fde_cfi, fde->dw_fde_switch_cfi_index,
true, fde, true);
}
var_location_switch_text_section (); var_location_switch_text_section ();
...@@ -1639,6 +1617,109 @@ add_loc_descr (dw_loc_descr_ref *list_head, dw_loc_descr_ref descr) ...@@ -1639,6 +1617,109 @@ add_loc_descr (dw_loc_descr_ref *list_head, dw_loc_descr_ref descr)
*d = descr; *d = descr;
} }
/* Compare two location operands for exact equality. */
static bool
dw_val_equal_p (dw_val_node *a, dw_val_node *b)
{
if (a->val_class != b->val_class)
return false;
switch (a->val_class)
{
case dw_val_class_none:
return true;
case dw_val_class_addr:
return rtx_equal_p (a->v.val_addr, b->v.val_addr);
case dw_val_class_offset:
case dw_val_class_unsigned_const:
case dw_val_class_const:
case dw_val_class_range_list:
case dw_val_class_lineptr:
case dw_val_class_macptr:
/* These are all HOST_WIDE_INT, signed or unsigned. */
return a->v.val_unsigned == b->v.val_unsigned;
case dw_val_class_loc:
return a->v.val_loc == b->v.val_loc;
case dw_val_class_loc_list:
return a->v.val_loc_list == b->v.val_loc_list;
case dw_val_class_die_ref:
return a->v.val_die_ref.die == b->v.val_die_ref.die;
case dw_val_class_fde_ref:
return a->v.val_fde_index == b->v.val_fde_index;
case dw_val_class_lbl_id:
return strcmp (a->v.val_lbl_id, b->v.val_lbl_id) == 0;
case dw_val_class_str:
return a->v.val_str == b->v.val_str;
case dw_val_class_flag:
return a->v.val_flag == b->v.val_flag;
case dw_val_class_file:
return a->v.val_file == b->v.val_file;
case dw_val_class_decl_ref:
return a->v.val_decl_ref == b->v.val_decl_ref;
case dw_val_class_const_double:
return (a->v.val_double.high == b->v.val_double.high
&& a->v.val_double.low == b->v.val_double.low);
case dw_val_class_vec:
{
size_t a_len = a->v.val_vec.elt_size * a->v.val_vec.length;
size_t b_len = b->v.val_vec.elt_size * b->v.val_vec.length;
return (a_len == b_len
&& !memcmp (a->v.val_vec.array, b->v.val_vec.array, a_len));
}
case dw_val_class_data8:
return memcmp (a->v.val_data8, b->v.val_data8, 8) == 0;
case dw_val_class_vms_delta:
return (!strcmp (a->v.val_vms_delta.lbl1, b->v.val_vms_delta.lbl1)
&& !strcmp (a->v.val_vms_delta.lbl1, b->v.val_vms_delta.lbl1));
}
gcc_unreachable ();
}
/* Compare two location atoms for exact equality. */
static bool
loc_descr_equal_p_1 (dw_loc_descr_ref a, dw_loc_descr_ref b)
{
if (a->dw_loc_opc != b->dw_loc_opc)
return false;
/* ??? This is only ever set for DW_OP_constNu, for N equal to the
address size, but since we always allocate cleared storage it
should be zero for other types of locations. */
if (a->dtprel != b->dtprel)
return false;
return (dw_val_equal_p (&a->dw_loc_oprnd1, &b->dw_loc_oprnd1)
&& dw_val_equal_p (&a->dw_loc_oprnd2, &b->dw_loc_oprnd2));
}
/* Compare two complete location expressions for exact equality. */
bool
loc_descr_equal_p (dw_loc_descr_ref a, dw_loc_descr_ref b)
{
while (1)
{
if (a == b)
return true;
if (a == NULL || b == NULL)
return false;
if (!loc_descr_equal_p_1 (a, b))
return false;
a = a->dw_loc_next;
b = b->dw_loc_next;
}
}
/* Add a constant OFFSET to a location expression. */ /* Add a constant OFFSET to a location expression. */
static void static void
......
...@@ -134,6 +134,7 @@ typedef struct GTY(()) cfa_loc { ...@@ -134,6 +134,7 @@ typedef struct GTY(()) cfa_loc {
enum dw_val_class enum dw_val_class
{ {
dw_val_class_none,
dw_val_class_addr, dw_val_class_addr,
dw_val_class_offset, dw_val_class_offset,
dw_val_class_loc, dw_val_class_loc,
...@@ -226,6 +227,7 @@ extern struct dw_loc_descr_struct *build_cfa_aligned_loc ...@@ -226,6 +227,7 @@ extern struct dw_loc_descr_struct *build_cfa_aligned_loc
extern struct dw_loc_descr_struct *mem_loc_descriptor extern struct dw_loc_descr_struct *mem_loc_descriptor
(rtx, enum machine_mode mode, enum machine_mode mem_mode, (rtx, enum machine_mode mode, enum machine_mode mem_mode,
enum var_init_status); enum var_init_status);
extern bool loc_descr_equal_p (dw_loc_descr_ref, dw_loc_descr_ref);
extern enum machine_mode get_address_mode (rtx mem); extern enum machine_mode get_address_mode (rtx mem);
extern dw_fde_ref dwarf2out_alloc_current_fde (void); extern dw_fde_ref dwarf2out_alloc_current_fde (void);
...@@ -239,7 +241,6 @@ extern void lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc, ...@@ -239,7 +241,6 @@ extern void lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc,
extern bool cfa_equal_p (const dw_cfa_location *, const dw_cfa_location *); 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_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; extern GTY(()) cfi_vec cie_cfi_vec;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment