This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Avoid code duplication in loc list handling in dwarf2out
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: gcc-patches at gcc dot gnu dot org, jakub at redhat dot com, jason at redhat dot com, rguenther at suse dot de
- Date: Fri, 18 Sep 2009 14:55:26 +0200
- Subject: Avoid code duplication in loc list handling in dwarf2out
Hi,
this patch removes code duplication in between
add_location_or_const_value_attribute and loc_list_from_tree. It also adds return
values to these functions to return true when expansion suceeded. I need it for further
patch handling the DEBUG_EXPR expressions.
This also fixes bug in loc_by_reference being called on possibly DW_OP_piece
that is already fixed in loc_list_from_tree.
Bootstrapped/regtested x86_64-linux and tested it has no effect on generated
dwarf for GCC modules.
OK?
Honza
* dwarf2out.c (add_const_value_attribute): Return true if successful.
(add_location_or_const_value_attribute): Rewrite using loc_list_from_tree.
(tree_add_const_value_attribute): Return true if successful.
(tree_add_const_value_attribute_for_decl): Likewise.
Index: dwarf2out.c
===================================================================
*** dwarf2out.c (revision 151837)
--- dwarf2out.c (working copy)
*************** static HOST_WIDE_INT field_byte_offset (
*** 5961,5974 ****
static void add_AT_location_description (dw_die_ref, enum dwarf_attribute,
dw_loc_list_ref);
static void add_data_member_location_attribute (dw_die_ref, tree);
! static void add_const_value_attribute (dw_die_ref, rtx);
static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
static void insert_float (const_rtx, unsigned char *);
static rtx rtl_for_decl_location (tree);
! static void add_location_or_const_value_attribute (dw_die_ref, tree,
enum dwarf_attribute);
! static void tree_add_const_value_attribute (dw_die_ref, tree);
! static void tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
static void add_name_attribute (dw_die_ref, const char *);
static void add_comp_dir_attribute (dw_die_ref);
static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
--- 5961,5974 ----
static void add_AT_location_description (dw_die_ref, enum dwarf_attribute,
dw_loc_list_ref);
static void add_data_member_location_attribute (dw_die_ref, tree);
! static bool add_const_value_attribute (dw_die_ref, rtx);
static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
static void insert_float (const_rtx, unsigned char *);
static rtx rtl_for_decl_location (tree);
! static bool add_location_or_const_value_attribute (dw_die_ref, tree,
enum dwarf_attribute);
! static bool tree_add_const_value_attribute (dw_die_ref, tree);
! static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
static void add_name_attribute (dw_die_ref, const char *);
static void add_comp_dir_attribute (dw_die_ref);
static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
*************** insert_float (const_rtx rtl, unsigned ch
*** 13170,13176 ****
to an inlined function. They can also arise in C++ where declared
constants do not necessarily get memory "homes". */
! static void
add_const_value_attribute (dw_die_ref die, rtx rtl)
{
switch (GET_CODE (rtl))
--- 13170,13176 ----
to an inlined function. They can also arise in C++ where declared
constants do not necessarily get memory "homes". */
! static bool
add_const_value_attribute (dw_die_ref die, rtx rtl)
{
switch (GET_CODE (rtl))
*************** add_const_value_attribute (dw_die_ref di
*** 13184,13190 ****
else
add_AT_unsigned (die, DW_AT_const_value, (unsigned HOST_WIDE_INT) val);
}
! break;
case CONST_DOUBLE:
/* Note that a CONST_DOUBLE rtx could represent either an integer or a
--- 13184,13190 ----
else
add_AT_unsigned (die, DW_AT_const_value, (unsigned HOST_WIDE_INT) val);
}
! return true;
case CONST_DOUBLE:
/* Note that a CONST_DOUBLE rtx could represent either an integer or a
*************** add_const_value_attribute (dw_die_ref di
*** 13205,13211 ****
else
add_AT_long_long (die, DW_AT_const_value, rtl);
}
! break;
case CONST_VECTOR:
{
--- 13205,13211 ----
else
add_AT_long_long (die, DW_AT_const_value, rtl);
}
! return true;
case CONST_VECTOR:
{
*************** add_const_value_attribute (dw_die_ref di
*** 13273,13299 ****
add_AT_vec (die, DW_AT_const_value, length, elt_size, array);
}
! break;
case CONST_STRING:
add_AT_string (die, DW_AT_const_value, XSTR (rtl, 0));
! break;
case CONST:
if (CONSTANT_P (XEXP (rtl, 0)))
{
add_const_value_attribute (die, XEXP (rtl, 0));
! return;
}
/* FALLTHROUGH */
case SYMBOL_REF:
if (GET_CODE (rtl) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (rtl) != TLS_MODEL_NONE)
! break;
case LABEL_REF:
add_AT_addr (die, DW_AT_const_value, rtl);
VEC_safe_push (rtx, gc, used_rtx_array, rtl);
! break;
case PLUS:
/* In cases where an inlined instance of an inline function is passed
--- 13273,13299 ----
add_AT_vec (die, DW_AT_const_value, length, elt_size, array);
}
! return true;
case CONST_STRING:
add_AT_string (die, DW_AT_const_value, XSTR (rtl, 0));
! return true;
case CONST:
if (CONSTANT_P (XEXP (rtl, 0)))
{
add_const_value_attribute (die, XEXP (rtl, 0));
! return true;
}
/* FALLTHROUGH */
case SYMBOL_REF:
if (GET_CODE (rtl) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (rtl) != TLS_MODEL_NONE)
! return false;
case LABEL_REF:
add_AT_addr (die, DW_AT_const_value, rtl);
VEC_safe_push (rtx, gc, used_rtx_array, rtl);
! return true;
case PLUS:
/* In cases where an inlined instance of an inline function is passed
*************** add_const_value_attribute (dw_die_ref di
*** 13307,13319 ****
*value* which the artificial local variable always has during its
lifetime. We currently have no way to represent such quasi-constant
values in Dwarf, so for now we just punt and generate nothing. */
! break;
default:
/* No other kinds of rtx should be possible here. */
gcc_unreachable ();
}
!
}
/* Determine whether the evaluation of EXPR references any variables
--- 13307,13319 ----
*value* which the artificial local variable always has during its
lifetime. We currently have no way to represent such quasi-constant
values in Dwarf, so for now we just punt and generate nothing. */
! return false;
default:
/* No other kinds of rtx should be possible here. */
gcc_unreachable ();
}
! return false;
}
/* Determine whether the evaluation of EXPR references any variables
*************** fortran_common (tree decl, HOST_WIDE_INT
*** 13706,13856 ****
pointer. This can happen for example if an actual argument in an inlined
function call evaluates to a compile-time constant address. */
! static void
add_location_or_const_value_attribute (dw_die_ref die, tree decl,
enum dwarf_attribute attr)
{
rtx rtl;
! dw_loc_descr_ref descr;
! dw_loc_list_ref descr_list;
! var_loc_list *loc_list;
! struct var_loc_node *node;
if (TREE_CODE (decl) == ERROR_MARK)
! return;
gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == RESULT_DECL);
- /* See if we possibly have multiple locations for this variable. */
- loc_list = lookup_decl_loc (decl);
-
- /* If it truly has multiple locations, the first and last node will
- differ. */
- if (loc_list && loc_list->first != loc_list->last)
- {
- const char *endname, *secname;
- dw_loc_list_ref list;
- rtx varloc;
- enum var_init_status initialized;
-
- /* Now that we know what section we are using for a base,
- actually construct the list of locations.
- The first location information is what is passed to the
- function that creates the location list, and the remaining
- locations just get added on to that list.
- Note that we only know the start address for a location
- (IE location changes), so to build the range, we use
- the range [current location start, next location start].
- This means we have to special case the last node, and generate
- a range of [last location start, end of function label]. */
-
- node = loc_list->first;
- varloc = NOTE_VAR_LOCATION (node->var_loc_note);
- secname = secname_for_decl (decl);
-
- if (NOTE_VAR_LOCATION_LOC (node->var_loc_note))
- initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
- else
- initialized = VAR_INIT_STATUS_INITIALIZED;
-
- descr = loc_by_reference (loc_descriptor (varloc, DECL_MODE (decl),
- initialized), decl);
- list = new_loc_list (descr, node->label, node->next->label, secname, 1);
- node = node->next;
-
- for (; node->next; node = node->next)
- if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
- {
- /* The variable has a location between NODE->LABEL and
- NODE->NEXT->LABEL. */
- enum var_init_status initialized =
- NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
- varloc = NOTE_VAR_LOCATION (node->var_loc_note);
- descr = loc_by_reference (loc_descriptor (varloc, DECL_MODE (decl),
- initialized), decl);
- add_loc_descr_to_loc_list (&list, descr,
- node->label, node->next->label, secname);
- }
-
- /* If the variable has a location at the last label
- it keeps its location until the end of function. */
- if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
- {
- char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
- enum var_init_status initialized =
- NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
-
- varloc = NOTE_VAR_LOCATION (node->var_loc_note);
- if (!current_function_decl)
- endname = text_end_label;
- else
- {
- ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
- current_function_funcdef_no);
- endname = ggc_strdup (label_id);
- }
- descr = loc_by_reference (loc_descriptor (varloc,
- DECL_MODE (decl),
- initialized),
- decl);
- add_loc_descr_to_loc_list (&list, descr,
- node->label, endname, secname);
- }
-
- /* Finally, add the location list to the DIE, and we are done. */
- add_AT_loc_list (die, attr, list);
- return;
- }
-
/* Try to get some constant RTL for this decl, and use that as the value of
the location. */
rtl = rtl_for_decl_location (decl);
! if (rtl && (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING))
! {
! add_const_value_attribute (die, rtl);
! return;
! }
!
! /* If we have tried to generate the location otherwise, and it
! didn't work out (we wouldn't be here if we did), and we have a one entry
! location list, try generating a location from that. */
! if (loc_list && loc_list->first)
! {
! enum var_init_status status;
! node = loc_list->first;
! status = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
! rtl = NOTE_VAR_LOCATION (node->var_loc_note);
! if (GET_CODE (rtl) == VAR_LOCATION
! && GET_CODE (XEXP (rtl, 1)) != PARALLEL)
! rtl = XEXP (XEXP (rtl, 1), 0);
! if (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
! {
! add_const_value_attribute (die, rtl);
! return;
! }
! descr = loc_descriptor (NOTE_VAR_LOCATION (node->var_loc_note),
! DECL_MODE (decl), status);
! if (descr)
! {
! descr = loc_by_reference (descr, decl);
! add_AT_location_description (die, attr, single_element_loc_list (descr));
! return;
! }
! }
!
! /* We couldn't get any rtl, so try directly generating the location
! description from the tree. */
! descr_list = loc_list_from_tree (decl, 2);
! if (descr_list)
{
! descr = loc_by_reference (descr, decl);
! add_AT_location_description (die, attr, descr_list);
! return;
}
/* None of that worked, so it must not really have a location;
try adding a constant value attribute from the DECL_INITIAL. */
! tree_add_const_value_attribute_for_decl (die, decl);
}
/* Add VARIABLE and DIE into deferred locations list. */
--- 13706,13740 ----
pointer. This can happen for example if an actual argument in an inlined
function call evaluates to a compile-time constant address. */
! static bool
add_location_or_const_value_attribute (dw_die_ref die, tree decl,
enum dwarf_attribute attr)
{
rtx rtl;
! dw_loc_list_ref list;
!
if (TREE_CODE (decl) == ERROR_MARK)
! return false;
gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == RESULT_DECL);
/* Try to get some constant RTL for this decl, and use that as the value of
the location. */
rtl = rtl_for_decl_location (decl);
! if (rtl && (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
! && add_const_value_attribute (die, rtl))
! return true;
! list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2);
! if (list)
{
! add_AT_location_description (die, attr, list);
! return true;
}
/* None of that worked, so it must not really have a location;
try adding a constant value attribute from the DECL_INITIAL. */
! return tree_add_const_value_attribute_for_decl (die, decl);
}
/* Add VARIABLE and DIE into deferred locations list. */
*************** native_encode_initializer (tree init, un
*** 14014,14020 ****
/* Attach a DW_AT_const_value attribute to DIE. The value of the
attribute is the const value T. */
! static void
tree_add_const_value_attribute (dw_die_ref die, tree t)
{
tree init;
--- 13898,13904 ----
/* Attach a DW_AT_const_value attribute to DIE. The value of the
attribute is the const value T. */
! static bool
tree_add_const_value_attribute (dw_die_ref die, tree t)
{
tree init;
*************** tree_add_const_value_attribute (dw_die_r
*** 14022,14035 ****
rtx rtl;
if (!t || !TREE_TYPE (t) || TREE_TYPE (t) == error_mark_node)
! return;
init = t;
gcc_assert (!DECL_P (init));
rtl = rtl_for_decl_init (init, type);
if (rtl)
! add_const_value_attribute (die, rtl);
/* If the host and target are sane, try harder. */
else if (CHAR_BIT == 8 && BITS_PER_UNIT == 8
&& initializer_constant_valid_p (init, type))
--- 13906,13922 ----
rtx rtl;
if (!t || !TREE_TYPE (t) || TREE_TYPE (t) == error_mark_node)
! return false;
init = t;
gcc_assert (!DECL_P (init));
rtl = rtl_for_decl_init (init, type);
if (rtl)
! {
! add_const_value_attribute (die, rtl);
! return true;
! }
/* If the host and target are sane, try harder. */
else if (CHAR_BIT == 8 && BITS_PER_UNIT == 8
&& initializer_constant_valid_p (init, type))
*************** tree_add_const_value_attribute (dw_die_r
*** 14040,14048 ****
unsigned char *array = GGC_CNEWVEC (unsigned char, size);
if (native_encode_initializer (init, array, size))
! add_AT_vec (die, DW_AT_const_value, size, 1, array);
}
}
}
/* Attach a DW_AT_const_value attribute to VAR_DIE. The value of the
--- 13927,13939 ----
unsigned char *array = GGC_CNEWVEC (unsigned char, size);
if (native_encode_initializer (init, array, size))
! {
! add_AT_vec (die, DW_AT_const_value, size, 1, array);
! return true;
! }
}
}
+ return false;
}
/* Attach a DW_AT_const_value attribute to VAR_DIE. The value of the
*************** tree_add_const_value_attribute (dw_die_r
*** 14050,14072 ****
variable with static storage duration
(so it can't be a PARM_DECL or a RESULT_DECL). */
! static void
tree_add_const_value_attribute_for_decl (dw_die_ref var_die, tree decl)
{
if (!decl
|| (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != CONST_DECL))
! return;
if (TREE_READONLY (decl)
&& ! TREE_THIS_VOLATILE (decl)
&& DECL_INITIAL (decl))
/* OK */;
else
! return;
! tree_add_const_value_attribute (var_die, DECL_INITIAL (decl));
}
/* Convert the CFI instructions for the current function into a
--- 13941,13963 ----
variable with static storage duration
(so it can't be a PARM_DECL or a RESULT_DECL). */
! static bool
tree_add_const_value_attribute_for_decl (dw_die_ref var_die, tree decl)
{
if (!decl
|| (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != CONST_DECL))
! return false;
if (TREE_READONLY (decl)
&& ! TREE_THIS_VOLATILE (decl)
&& DECL_INITIAL (decl))
/* OK */;
else
! return false;
! return tree_add_const_value_attribute (var_die, DECL_INITIAL (decl));
}
/* Convert the CFI instructions for the current function into a