re PR debug/66668 (FAIL: gcc.dg/debug/dwarf2/stacked-qualified-types-3.c scan-assembler-times DIE \\([^\n]*\\) DW_TAG_(?:const|volatile|atomic|restrict)_type 8)

PR debug/66668
	* dwarf2out.c (add_child_die_after): New function.
	(dwarf_qual_info_t): New type.
	(dwarf_qual_info): New variable.
	(qualified_die_p): New function.
	(modified_type_die): For -fdebug-types-section, ensure
	canonical order of qualifiers.  Put qualified DIEs adjacent
	to the corresponding non-qualified type DIE and search there
	for existing qualified DIEs.

From-SVN: r232719
This commit is contained in:
Jakub Jelinek 2016-01-22 10:40:54 +01:00 committed by Jakub Jelinek
parent e1cf192b12
commit faafb83368
2 changed files with 148 additions and 12 deletions

View File

@ -1,3 +1,15 @@
2016-01-22 Jakub Jelinek <jakub@redhat.com>
PR debug/66668
* dwarf2out.c (add_child_die_after): New function.
(dwarf_qual_info_t): New type.
(dwarf_qual_info): New variable.
(qualified_die_p): New function.
(modified_type_die): For -fdebug-types-section, ensure
canonical order of qualifiers. Put qualified DIEs adjacent
to the corresponding non-qualified type DIE and search there
for existing qualified DIEs.
2016-01-22 Eric Botcazou <ebotcazou@adacore.com>
* doc/extend.texi (scalar_storage_order type attribute): Document

View File

@ -4970,6 +4970,25 @@ add_child_die (dw_die_ref die, dw_die_ref child_die)
die->die_child = child_die;
}
/* Like add_child_die, but put CHILD_DIE after AFTER_DIE. */
static void
add_child_die_after (dw_die_ref die, dw_die_ref child_die,
dw_die_ref after_die)
{
gcc_assert (die
&& child_die
&& after_die
&& die->die_child
&& die != child_die);
child_die->die_parent = die;
child_die->die_sib = after_die->die_sib;
after_die->die_sib = child_die;
if (die->die_child == after_die)
die->die_child = child_die;
}
/* Unassociate CHILD from its parent, and make its parent be
NEW_PARENT. */
@ -11149,6 +11168,45 @@ get_nearest_type_subqualifiers (tree type, int type_quals, int qual_mask)
return best_qual;
}
struct dwarf_qual_info_t { int q; enum dwarf_tag t; };
static const dwarf_qual_info_t dwarf_qual_info[] =
{
{ TYPE_QUAL_CONST, DW_TAG_const_type },
{ TYPE_QUAL_VOLATILE, DW_TAG_volatile_type },
{ TYPE_QUAL_RESTRICT, DW_TAG_restrict_type },
{ TYPE_QUAL_ATOMIC, DW_TAG_atomic_type }
};
static const unsigned int dwarf_qual_info_size
= sizeof (dwarf_qual_info) / sizeof (dwarf_qual_info[0]);
/* If DIE is a qualified DIE of some base DIE with the same parent,
return the base DIE, otherwise return NULL. Set MASK to the
qualifiers added compared to the returned DIE. */
static dw_die_ref
qualified_die_p (dw_die_ref die, int *mask, unsigned int depth)
{
unsigned int i;
for (i = 0; i < dwarf_qual_info_size; i++)
if (die->die_tag == dwarf_qual_info[i].t)
break;
if (i == dwarf_qual_info_size)
return NULL;
if (vec_safe_length (die->die_attr) != 1)
return NULL;
dw_die_ref type = get_AT_ref (die, DW_AT_type);
if (type == NULL || type->die_parent != die->die_parent)
return NULL;
*mask |= dwarf_qual_info[i].q;
if (depth)
{
dw_die_ref ret = qualified_die_p (type, mask, depth - 1);
if (ret)
return ret;
}
return type;
}
/* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging
entry that chains the modifiers specified by CV_QUALS in front of the
given type. REVERSE is true if the type is to be interpreted in the
@ -11255,31 +11313,97 @@ modified_type_die (tree type, int cv_quals, bool reverse,
if (cv_quals)
{
struct qual_info { int q; enum dwarf_tag t; };
static const struct qual_info qual_info[] =
{
{ TYPE_QUAL_ATOMIC, DW_TAG_atomic_type },
{ TYPE_QUAL_RESTRICT, DW_TAG_restrict_type },
{ TYPE_QUAL_VOLATILE, DW_TAG_volatile_type },
{ TYPE_QUAL_CONST, DW_TAG_const_type },
};
int sub_quals;
int sub_quals = 0, first_quals = 0;
unsigned i;
dw_die_ref first = NULL, last = NULL;
/* Determine a lesser qualified type that most closely matches
this one. Then generate DW_TAG_* entries for the remaining
qualifiers. */
sub_quals = get_nearest_type_subqualifiers (type, cv_quals,
cv_qual_mask);
mod_type_die = modified_type_die (type, sub_quals, reverse, context_die);
for (i = 0; i < sizeof (qual_info) / sizeof (qual_info[0]); i++)
if (qual_info[i].q & cv_quals & ~sub_quals)
if (sub_quals && use_debug_types)
{
dw_die_ref d = new_die (qual_info[i].t, mod_scope, type);
bool needed = false;
/* If emitting type units, make sure the order of qualifiers
is canonical. Thus, start from unqualified type if
an earlier qualifier is missing in sub_quals, but some later
one is present there. */
for (i = 0; i < dwarf_qual_info_size; i++)
if (dwarf_qual_info[i].q & cv_quals & ~sub_quals)
needed = true;
else if (needed && (dwarf_qual_info[i].q & cv_quals))
{
sub_quals = 0;
break;
}
}
mod_type_die = modified_type_die (type, sub_quals, reverse, context_die);
if (mod_scope && mod_type_die && mod_type_die->die_parent == mod_scope)
{
/* As not all intermediate qualified DIEs have corresponding
tree types, ensure that qualified DIEs in the same scope
as their DW_AT_type are emitted after their DW_AT_type,
only with other qualified DIEs for the same type possibly
in between them. Determine the range of such qualified
DIEs now (first being the base type, last being corresponding
last qualified DIE for it). */
unsigned int count = 0;
first = qualified_die_p (mod_type_die, &first_quals,
dwarf_qual_info_size);
if (first == NULL)
first = mod_type_die;
gcc_assert ((first_quals & ~sub_quals) == 0);
for (count = 0, last = first;
count < (1U << dwarf_qual_info_size);
count++, last = last->die_sib)
{
int quals = 0;
if (last == mod_scope->die_child)
break;
if (qualified_die_p (last->die_sib, &quals, dwarf_qual_info_size)
!= first)
break;
}
}
for (i = 0; i < dwarf_qual_info_size; i++)
if (dwarf_qual_info[i].q & cv_quals & ~sub_quals)
{
dw_die_ref d;
if (first && first != last)
{
for (d = first->die_sib; ; d = d->die_sib)
{
int quals = 0;
qualified_die_p (d, &quals, dwarf_qual_info_size);
if (quals == (first_quals | dwarf_qual_info[i].q))
break;
if (d == last)
{
d = NULL;
break;
}
}
if (d)
{
mod_type_die = d;
continue;
}
}
if (first)
{
d = ggc_cleared_alloc<die_node> ();
d->die_tag = dwarf_qual_info[i].t;
add_child_die_after (mod_scope, d, last);
last = d;
}
else
d = new_die (dwarf_qual_info[i].t, mod_scope, type);
if (mod_type_die)
add_AT_die_ref (d, DW_AT_type, mod_type_die);
mod_type_die = d;
first_quals |= dwarf_qual_info[i].q;
}
}
else if (code == POINTER_TYPE || code == REFERENCE_TYPE)