summaryrefslogtreecommitdiff
path: root/gcc/dwarf2out.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r--gcc/dwarf2out.c176
1 files changed, 111 insertions, 65 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 0b5a68a1517..a0714c45d26 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -1732,17 +1732,56 @@ struct GTY(()) queued_reg_save {
static GTY(()) struct queued_reg_save *queued_reg_saves;
/* The caller's ORIG_REG is saved in SAVED_IN_REG. */
-struct GTY(()) reg_saved_in_data {
+typedef struct GTY(()) reg_saved_in_data {
rtx orig_reg;
rtx saved_in_reg;
-};
+} reg_saved_in_data;
+
+DEF_VEC_O (reg_saved_in_data);
+DEF_VEC_ALLOC_O (reg_saved_in_data, gc);
+
+/* A set of registers saved in other registers. This is implemented as
+ a flat array because it normally contains zero or 1 entry, depending
+ on the target. IA-64 is the big spender here, using a maximum of
+ 5 entries. */
+static GTY(()) VEC(reg_saved_in_data, gc) *regs_saved_in_regs;
+
+/* Compare X and Y for equivalence. The inputs may be REGs or PC_RTX. */
+
+static bool
+compare_reg_or_pc (rtx x, rtx y)
+{
+ if (REG_P (x) && REG_P (y))
+ return REGNO (x) == REGNO (y);
+ return x == y;
+}
+
+/* Record SRC as being saved in DEST. DEST may be null to delete an
+ existing entry. SRC may be a register or PC_RTX. */
+
+static void
+record_reg_saved_in_reg (rtx dest, rtx src)
+{
+ reg_saved_in_data *elt;
+ size_t i;
+
+ FOR_EACH_VEC_ELT (reg_saved_in_data, regs_saved_in_regs, i, elt)
+ if (compare_reg_or_pc (elt->orig_reg, src))
+ {
+ if (dest == NULL)
+ VEC_unordered_remove(reg_saved_in_data, regs_saved_in_regs, i);
+ else
+ elt->saved_in_reg = dest;
+ return;
+ }
-/* A list of registers saved in other registers.
- The list intentionally has a small maximum capacity of 4; if your
- port needs more than that, you might consider implementing a
- more efficient data structure. */
-static GTY(()) struct reg_saved_in_data regs_saved_in_regs[4];
-static GTY(()) size_t num_regs_saved_in_regs;
+ if (dest == NULL)
+ return;
+
+ elt = VEC_safe_push(reg_saved_in_data, gc, regs_saved_in_regs, NULL);
+ elt->orig_reg = src;
+ elt->saved_in_reg = dest;
+}
static const char *last_reg_save_label;
@@ -1784,22 +1823,9 @@ dwarf2out_flush_queued_reg_saves (void)
for (q = queued_reg_saves; q; q = q->next)
{
- size_t i;
unsigned int reg, sreg;
- for (i = 0; i < num_regs_saved_in_regs; i++)
- if (REGNO (regs_saved_in_regs[i].orig_reg) == REGNO (q->reg))
- break;
- if (q->saved_reg && i == num_regs_saved_in_regs)
- {
- gcc_assert (i != ARRAY_SIZE (regs_saved_in_regs));
- num_regs_saved_in_regs++;
- }
- if (i != num_regs_saved_in_regs)
- {
- regs_saved_in_regs[i].orig_reg = q->reg;
- regs_saved_in_regs[i].saved_in_reg = q->saved_reg;
- }
+ record_reg_saved_in_reg (q->saved_reg, q->reg);
reg = DWARF_FRAME_REGNUM (REGNO (q->reg));
if (q->saved_reg)
@@ -1826,11 +1852,14 @@ clobbers_queued_reg_save (const_rtx insn)
for (q = queued_reg_saves; q; q = q->next)
{
size_t i;
+ reg_saved_in_data *rir;
+
if (modified_in_p (q->reg, insn))
return true;
- for (i = 0; i < num_regs_saved_in_regs; i++)
- if (REGNO (q->reg) == REGNO (regs_saved_in_regs[i].orig_reg)
- && modified_in_p (regs_saved_in_regs[i].saved_in_reg, insn))
+
+ FOR_EACH_VEC_ELT (reg_saved_in_data, regs_saved_in_regs, i, rir)
+ if (compare_reg_or_pc (q->reg, rir->orig_reg)
+ && modified_in_p (rir->saved_in_reg, insn))
return true;
}
@@ -1842,19 +1871,9 @@ clobbers_queued_reg_save (const_rtx insn)
void
dwarf2out_reg_save_reg (const char *label, rtx reg, rtx sreg)
{
- size_t i;
unsigned int regno, sregno;
- for (i = 0; i < num_regs_saved_in_regs; i++)
- if (REGNO (regs_saved_in_regs[i].orig_reg) == REGNO (reg))
- break;
- if (i == num_regs_saved_in_regs)
- {
- gcc_assert (i != ARRAY_SIZE (regs_saved_in_regs));
- num_regs_saved_in_regs++;
- }
- regs_saved_in_regs[i].orig_reg = reg;
- regs_saved_in_regs[i].saved_in_reg = sreg;
+ record_reg_saved_in_reg (sreg, reg);
regno = DWARF_FRAME_REGNUM (REGNO (reg));
sregno = DWARF_FRAME_REGNUM (REGNO (sreg));
@@ -1867,17 +1886,17 @@ static rtx
reg_saved_in (rtx reg)
{
unsigned int regn = REGNO (reg);
- size_t i;
struct queued_reg_save *q;
+ reg_saved_in_data *rir;
+ size_t i;
for (q = queued_reg_saves; q; q = q->next)
if (q->saved_reg && regn == REGNO (q->saved_reg))
return q->reg;
- for (i = 0; i < num_regs_saved_in_regs; i++)
- if (regs_saved_in_regs[i].saved_in_reg
- && regn == REGNO (regs_saved_in_regs[i].saved_in_reg))
- return regs_saved_in_regs[i].orig_reg;
+ FOR_EACH_VEC_ELT (reg_saved_in_data, regs_saved_in_regs, i, rir)
+ if (regn == REGNO (rir->saved_in_reg))
+ return rir->orig_reg;
return NULL_RTX;
}
@@ -1963,6 +1982,7 @@ dwarf2out_frame_debug_cfa_offset (rtx set, const char *label)
{
HOST_WIDE_INT offset;
rtx src, addr, span;
+ unsigned int sregno;
src = XEXP (set, 1);
addr = XEXP (set, 0);
@@ -1984,12 +2004,21 @@ dwarf2out_frame_debug_cfa_offset (rtx set, const char *label)
gcc_unreachable ();
}
- span = targetm.dwarf_register_span (src);
+ if (src == pc_rtx)
+ {
+ span = NULL;
+ sregno = DWARF_FRAME_RETURN_COLUMN;
+ }
+ else
+ {
+ span = targetm.dwarf_register_span (src);
+ sregno = DWARF_FRAME_REGNUM (REGNO (src));
+ }
/* ??? We'd like to use queue_reg_save, but we need to come up with
a different flushing heuristic for epilogues. */
if (!span)
- reg_save (label, DWARF_FRAME_REGNUM (REGNO (src)), INVALID_REGNUM, offset);
+ reg_save (label, sregno, INVALID_REGNUM, offset);
else
{
/* We have a PARALLEL describing where the contents of SRC live.
@@ -2005,8 +2034,8 @@ dwarf2out_frame_debug_cfa_offset (rtx set, const char *label)
{
rtx elem = XVECEXP (span, 0, par_index);
- reg_save (label, DWARF_FRAME_REGNUM (REGNO (elem)),
- INVALID_REGNUM, span_offset);
+ sregno = DWARF_FRAME_REGNUM (REGNO (src));
+ reg_save (label, sregno, INVALID_REGNUM, span_offset);
span_offset += GET_MODE_SIZE (GET_MODE (elem));
}
}
@@ -2026,7 +2055,10 @@ dwarf2out_frame_debug_cfa_register (rtx set, const char *label)
if (src == pc_rtx)
sregno = DWARF_FRAME_RETURN_COLUMN;
else
- sregno = DWARF_FRAME_REGNUM (REGNO (src));
+ {
+ record_reg_saved_in_reg (dest, src);
+ sregno = DWARF_FRAME_REGNUM (REGNO (src));
+ }
dregno = DWARF_FRAME_REGNUM (REGNO (dest));
@@ -2800,6 +2832,7 @@ dwarf2out_frame_debug (rtx insn, bool after_p)
const char *label;
rtx note, n;
bool handled_one = false;
+ bool need_flush = false;
if (!NONJUMP_INSN_P (insn) || clobbers_queued_reg_save (insn))
dwarf2out_flush_queued_reg_saves ();
@@ -2822,7 +2855,7 @@ dwarf2out_frame_debug (rtx insn, bool after_p)
{
case REG_FRAME_RELATED_EXPR:
insn = XEXP (note, 0);
- goto found;
+ goto do_frame_expr;
case REG_CFA_DEF_CFA:
dwarf2out_frame_debug_def_cfa (XEXP (note, 0), label);
@@ -2902,24 +2935,36 @@ dwarf2out_frame_debug (rtx insn, bool after_p)
handled_one = true;
break;
+ case REG_CFA_FLUSH_QUEUE:
+ /* The actual flush happens below. */
+ need_flush = true;
+ handled_one = true;
+ break;
+
default:
break;
}
+
if (handled_one)
{
- if (any_cfis_emitted)
- dwarf2out_flush_queued_reg_saves ();
- return;
+ /* Minimize the number of advances by emitting the entire queue
+ once anything is emitted. */
+ need_flush |= any_cfis_emitted;
}
+ else
+ {
+ insn = PATTERN (insn);
+ do_frame_expr:
+ dwarf2out_frame_debug_expr (insn, label);
- insn = PATTERN (insn);
- found:
- dwarf2out_frame_debug_expr (insn, label);
+ /* Check again. A parallel can save and update the same register.
+ We could probably check just once, here, but this is safer than
+ removing the check at the start of the function. */
+ if (any_cfis_emitted || clobbers_queued_reg_save (insn))
+ need_flush = true;
+ }
- /* Check again. A parallel can save and update the same register.
- We could probably check just once, here, but this is safer than
- removing the check above. */
- if (any_cfis_emitted || clobbers_queued_reg_save (insn))
+ if (need_flush)
dwarf2out_flush_queued_reg_saves ();
}
@@ -2928,8 +2973,6 @@ dwarf2out_frame_debug (rtx insn, bool after_p)
void
dwarf2out_frame_debug_init (void)
{
- size_t i;
-
/* Flush any queued register saves. */
dwarf2out_flush_queued_reg_saves ();
@@ -2943,12 +2986,7 @@ dwarf2out_frame_debug_init (void)
cfa_temp.reg = -1;
cfa_temp.offset = 0;
- for (i = 0; i < num_regs_saved_in_regs; i++)
- {
- regs_saved_in_regs[i].orig_reg = NULL_RTX;
- regs_saved_in_regs[i].saved_in_reg = NULL_RTX;
- }
- num_regs_saved_in_regs = 0;
+ regs_saved_in_regs = NULL;
if (barrier_args_size)
{
@@ -13151,6 +13189,8 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
name = DECL_NAME (name);
add_name_attribute (mod_type_die, IDENTIFIER_POINTER (name));
add_gnat_descriptive_type_attribute (mod_type_die, type, context_die);
+ if (TYPE_ARTIFICIAL (type))
+ add_AT_flag (mod_type_die, DW_AT_artificial, 1);
}
/* This probably indicates a bug. */
else if (mod_type_die && mod_type_die->die_tag == DW_TAG_base_type)
@@ -19406,6 +19446,8 @@ gen_array_type_die (tree type, dw_die_ref context_die)
array_die = new_die (DW_TAG_array_type, scope_die, type);
add_name_attribute (array_die, type_tag (type));
add_gnat_descriptive_type_attribute (array_die, type, context_die);
+ if (TYPE_ARTIFICIAL (type))
+ add_AT_flag (array_die, DW_AT_artificial, 1);
equate_type_number_to_die (type, array_die);
if (TREE_CODE (type) == VECTOR_TYPE)
@@ -19709,6 +19751,8 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die)
equate_type_number_to_die (type, type_die);
add_name_attribute (type_die, type_tag (type));
add_gnat_descriptive_type_attribute (type_die, type, context_die);
+ if (TYPE_ARTIFICIAL (type))
+ add_AT_flag (type_die, DW_AT_artificial, 1);
if (dwarf_version >= 4 || !dwarf_strict)
{
if (ENUM_IS_SCOPED (type))
@@ -21566,6 +21610,8 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
{
add_name_attribute (type_die, type_tag (type));
add_gnat_descriptive_type_attribute (type_die, type, context_die);
+ if (TYPE_ARTIFICIAL (type))
+ add_AT_flag (type_die, DW_AT_artificial, 1);
}
}
else