Commit 0a2d3d69 by Daniel Berlin Committed by Josef Zlomek

dwarf2out.c (struct gcc_debug_hooks): Call dwarf2out_begin_function at the beginning of function...

	* dwarf2out.c (struct gcc_debug_hooks): Call dwarf2out_begin_function
	at the beginning of function, call dwarf2out_var_location for
	NOTE_INSN_VAR_LOCATION note.
	(struct var_loc_node, struct var_loc_list_def, loclabel_num,
	decl_loc_table): New.
	(lookup_decl_loc): New function.
	(add_var_loc_to_decl): New function.
	(based_loc_descr): Added parameter can_use_fbreg, DW_OP_fbreg is used
	only if can_use_fbreg.
	(mem_loc_descriptor): Added parameter can_use_fbreg, pass it to other
	functions.
	(loc_descriptor): Likewise. Process VAR_LOCATION.
	(concat_loc_descriptor): Call loc_descriptor with can_use_fbreg == true.
	(loc_descriptor_from_tree): Call mem_loc_descriptor with
	can_use_fbreg == true.
	(add_location_or_const_value_attribute): Added parameter enum
	dwarf_attribute attr, generate attribute ATTR.  Create the location list.
	(add_bound_info): Call loc_descriptor with can_use_fbreg == true.
	(gen_formal_parameter_die): Call add_location_or_const_value_attribute
	with attr == DW_AT_location.
	(gen_subprogram_die): Generate the location list for DW_AT_frame_base
	if frame_base_decl is defined and has a location list.
	(gen_variable_die): Call add_location_or_const_value_attribute with
	attr == DW_AT_location.
	(dwarf2out_var_location): New function.
	(dwarf2out_begin_function): New function.
	(dwarf2out_init): Create decl_loc_table.

Co-Authored-By: Josef Zlomek <zlomekj@suse.cz>

From-SVN: r77421
parent 1f0db3df
2004-02-06 Daniel Berlin <dberlin@dberlin.org>
Josef Zlomek <zlomekj@suse.cz>
* dwarf2out.c (struct gcc_debug_hooks): Call dwarf2out_begin_function
at the beginning of function, call dwarf2out_var_location for
NOTE_INSN_VAR_LOCATION note.
(struct var_loc_node, struct var_loc_list_def, loclabel_num,
decl_loc_table): New.
(lookup_decl_loc): New function.
(add_var_loc_to_decl): New function.
(based_loc_descr): Added parameter can_use_fbreg, DW_OP_fbreg is used
only if can_use_fbreg.
(mem_loc_descriptor): Added parameter can_use_fbreg, pass it to other
functions.
(loc_descriptor): Likewise. Process VAR_LOCATION.
(concat_loc_descriptor): Call loc_descriptor with can_use_fbreg == true.
(loc_descriptor_from_tree): Call mem_loc_descriptor with
can_use_fbreg == true.
(add_location_or_const_value_attribute): Added parameter enum
dwarf_attribute attr, generate attribute ATTR. Create the location list.
(add_bound_info): Call loc_descriptor with can_use_fbreg == true.
(gen_formal_parameter_die): Call add_location_or_const_value_attribute
with attr == DW_AT_location.
(gen_subprogram_die): Generate the location list for DW_AT_frame_base
if frame_base_decl is defined and has a location list.
(gen_variable_die): Call add_location_or_const_value_attribute with
attr == DW_AT_location.
(dwarf2out_var_location): New function.
(dwarf2out_begin_function): New function.
(dwarf2out_init): Create decl_loc_table.
2004-02-06 Ulrich Weigand <uweigand@de.ibm.com> 2004-02-06 Ulrich Weigand <uweigand@de.ibm.com>
* loop.c (force_movables): Transitively increase the priorities of * loop.c (force_movables): Transitively increase the priorities of
......
...@@ -3251,6 +3251,8 @@ static bool dwarf2out_ignore_block (tree); ...@@ -3251,6 +3251,8 @@ static bool dwarf2out_ignore_block (tree);
static void dwarf2out_global_decl (tree); static void dwarf2out_global_decl (tree);
static void dwarf2out_imported_module_or_decl (tree, tree); static void dwarf2out_imported_module_or_decl (tree, tree);
static void dwarf2out_abstract_function (tree); static void dwarf2out_abstract_function (tree);
static void dwarf2out_var_location (rtx);
static void dwarf2out_begin_function (tree);
/* The debug hooks structure. */ /* The debug hooks structure. */
...@@ -3269,7 +3271,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = ...@@ -3269,7 +3271,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
dwarf2out_begin_prologue, dwarf2out_begin_prologue,
debug_nothing_int_charstar, /* end_prologue */ debug_nothing_int_charstar, /* end_prologue */
dwarf2out_end_epilogue, dwarf2out_end_epilogue,
debug_nothing_tree, /* begin_function */ dwarf2out_begin_function,
debug_nothing_int, /* end_function */ debug_nothing_int, /* end_function */
dwarf2out_decl, /* function_decl */ dwarf2out_decl, /* function_decl */
dwarf2out_global_decl, dwarf2out_global_decl,
...@@ -3281,7 +3283,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = ...@@ -3281,7 +3283,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
dwarf2out_abstract_function, /* outlining_inline_function */ dwarf2out_abstract_function, /* outlining_inline_function */
debug_nothing_rtx, /* label */ debug_nothing_rtx, /* label */
debug_nothing_int, /* handle_pch */ debug_nothing_int, /* handle_pch */
debug_nothing_rtx /* var_location */ dwarf2out_var_location
}; };
#endif #endif
...@@ -3477,6 +3479,34 @@ static GTY(()) size_t file_table_last_lookup_index; ...@@ -3477,6 +3479,34 @@ static GTY(()) size_t file_table_last_lookup_index;
The key is a DECL_UID() which is a unique number identifying each decl. */ The key is a DECL_UID() which is a unique number identifying each decl. */
static GTY ((param_is (struct die_struct))) htab_t decl_die_table; static GTY ((param_is (struct die_struct))) htab_t decl_die_table;
/* Node of the variable location list. */
struct var_loc_node GTY ((chain_next ("%h.next")))
{
rtx GTY (()) var_loc_note;
const char * GTY (()) label;
struct var_loc_node * GTY (()) next;
};
/* Variable location list. */
struct var_loc_list_def GTY (())
{
struct var_loc_node * GTY (()) first;
/* Do not mark the last element of the chained list because
it is marked through the chain. */
struct var_loc_node * GTY ((skip ("%h"))) last;
/* DECL_UID of the variable decl. */
unsigned int decl_id;
};
typedef struct var_loc_list_def var_loc_list;
/* Unique label counter. */
static unsigned int loclabel_num = 0;
/* Table of decl location linked lists. */
static GTY ((param_is (var_loc_list))) htab_t decl_loc_table;
/* A pointer to the base of a list of references to DIE's that /* A pointer to the base of a list of references to DIE's that
are uniquely identified by their tag, presence/absence of are uniquely identified by their tag, presence/absence of
children DIE's, and list of attribute/value pairs. */ children DIE's, and list of attribute/value pairs. */
...@@ -3651,7 +3681,11 @@ static void equate_type_number_to_die (tree, dw_die_ref); ...@@ -3651,7 +3681,11 @@ static void equate_type_number_to_die (tree, dw_die_ref);
static hashval_t decl_die_table_hash (const void *); static hashval_t decl_die_table_hash (const void *);
static int decl_die_table_eq (const void *, const void *); static int decl_die_table_eq (const void *, const void *);
static dw_die_ref lookup_decl_die (tree); static dw_die_ref lookup_decl_die (tree);
static hashval_t decl_loc_table_hash (const void *);
static int decl_loc_table_eq (const void *, const void *);
static var_loc_list *lookup_decl_loc (tree);
static void equate_decl_number_to_die (tree, dw_die_ref); static void equate_decl_number_to_die (tree, dw_die_ref);
static void add_var_loc_to_decl (tree, struct var_loc_node *);
static void print_spaces (FILE *); static void print_spaces (FILE *);
static void print_die (dw_die_ref, FILE *); static void print_die (dw_die_ref, FILE *);
static void print_dwarf_line_table (FILE *); static void print_dwarf_line_table (FILE *);
...@@ -3717,11 +3751,11 @@ static dw_loc_descr_ref reg_loc_descriptor (rtx); ...@@ -3717,11 +3751,11 @@ static dw_loc_descr_ref reg_loc_descriptor (rtx);
static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int); static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int);
static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx); static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx);
static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT); static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT);
static dw_loc_descr_ref based_loc_descr (unsigned, HOST_WIDE_INT); static dw_loc_descr_ref based_loc_descr (unsigned, HOST_WIDE_INT, bool);
static int is_based_loc (rtx); static int is_based_loc (rtx);
static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode); static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode, bool);
static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx); static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx);
static dw_loc_descr_ref loc_descriptor (rtx); static dw_loc_descr_ref loc_descriptor (rtx, bool);
static dw_loc_descr_ref loc_descriptor_from_tree (tree, int); static dw_loc_descr_ref loc_descriptor_from_tree (tree, int);
static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int); static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
static tree field_type (tree); static tree field_type (tree);
...@@ -3734,7 +3768,8 @@ static void add_AT_location_description (dw_die_ref, enum dwarf_attribute, ...@@ -3734,7 +3768,8 @@ static void add_AT_location_description (dw_die_ref, enum dwarf_attribute,
static void add_data_member_location_attribute (dw_die_ref, tree); static void add_data_member_location_attribute (dw_die_ref, tree);
static void add_const_value_attribute (dw_die_ref, rtx); static void add_const_value_attribute (dw_die_ref, rtx);
static rtx rtl_for_decl_location (tree); static rtx rtl_for_decl_location (tree);
static void add_location_or_const_value_attribute (dw_die_ref, 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 (dw_die_ref, tree);
static void add_name_attribute (dw_die_ref, const char *); static void add_name_attribute (dw_die_ref, const char *);
static void add_comp_dir_attribute (dw_die_ref); static void add_comp_dir_attribute (dw_die_ref);
...@@ -5229,6 +5264,31 @@ lookup_decl_die (tree decl) ...@@ -5229,6 +5264,31 @@ lookup_decl_die (tree decl)
return htab_find_with_hash (decl_die_table, decl, DECL_UID (decl)); return htab_find_with_hash (decl_die_table, decl, DECL_UID (decl));
} }
/* Returns a hash value for X (which really is a var_loc_list). */
static hashval_t
decl_loc_table_hash (const void *x)
{
return (hashval_t) ((const var_loc_list *) x)->decl_id;
}
/* Return nonzero if decl_id of var_loc_list X is the same as
UID of decl *Y. */
static int
decl_loc_table_eq (const void *x, const void *y)
{
return (((const var_loc_list *) x)->decl_id == DECL_UID ((const tree) y));
}
/* Return the var_loc list associated with a given declaration. */
static inline var_loc_list *
lookup_decl_loc (tree decl)
{
return htab_find_with_hash (decl_loc_table, decl, DECL_UID (decl));
}
/* Equate a DIE to a particular declaration. */ /* Equate a DIE to a particular declaration. */
static void static void
...@@ -5242,6 +5302,45 @@ equate_decl_number_to_die (tree decl, dw_die_ref decl_die) ...@@ -5242,6 +5302,45 @@ equate_decl_number_to_die (tree decl, dw_die_ref decl_die)
decl_die->decl_id = decl_id; decl_die->decl_id = decl_id;
} }
/* Add a variable location node to the linked list for DECL. */
static void
add_var_loc_to_decl (tree decl, struct var_loc_node *loc)
{
unsigned int decl_id = DECL_UID (decl);
var_loc_list *temp;
void **slot;
slot = htab_find_slot_with_hash (decl_loc_table, decl, decl_id, INSERT);
if (*slot == NULL)
{
temp = ggc_alloc_cleared (sizeof (var_loc_list));
temp->decl_id = decl_id;
*slot = temp;
}
else
temp = *slot;
if (temp->last)
{
/* If the current location is the same as the end of the list,
we have nothing to do. */
if (!rtx_equal_p (NOTE_VAR_LOCATION_LOC (temp->last->var_loc_note),
NOTE_VAR_LOCATION_LOC (loc->var_loc_note)))
{
/* Add LOC to the end of list and update LAST. */
temp->last->next = loc;
temp->last = loc;
}
}
/* Do not add empty location to the beginning of the list. */
else if (NOTE_VAR_LOCATION_LOC (loc->var_loc_note) != NULL_RTX)
{
temp->first = loc;
temp->last = loc;
}
}
/* Keep track of the number of spaces used to indent the /* Keep track of the number of spaces used to indent the
output of the debugging routines that print the structure of output of the debugging routines that print the structure of
the DIE internal representation. */ the DIE internal representation. */
...@@ -8204,7 +8303,7 @@ int_loc_descriptor (HOST_WIDE_INT i) ...@@ -8204,7 +8303,7 @@ int_loc_descriptor (HOST_WIDE_INT i)
/* Return a location descriptor that designates a base+offset location. */ /* Return a location descriptor that designates a base+offset location. */
static dw_loc_descr_ref static dw_loc_descr_ref
based_loc_descr (unsigned int reg, HOST_WIDE_INT offset) based_loc_descr (unsigned int reg, HOST_WIDE_INT offset, bool can_use_fbreg)
{ {
dw_loc_descr_ref loc_result; dw_loc_descr_ref loc_result;
/* For the "frame base", we use the frame pointer or stack pointer /* For the "frame base", we use the frame pointer or stack pointer
...@@ -8214,7 +8313,7 @@ based_loc_descr (unsigned int reg, HOST_WIDE_INT offset) ...@@ -8214,7 +8313,7 @@ based_loc_descr (unsigned int reg, HOST_WIDE_INT offset)
? HARD_FRAME_POINTER_REGNUM ? HARD_FRAME_POINTER_REGNUM
: STACK_POINTER_REGNUM); : STACK_POINTER_REGNUM);
if (reg == fp_reg) if (reg == fp_reg && can_use_fbreg)
loc_result = new_loc_descr (DW_OP_fbreg, offset, 0); loc_result = new_loc_descr (DW_OP_fbreg, offset, 0);
else if (reg <= 31) else if (reg <= 31)
loc_result = new_loc_descr (DW_OP_breg0 + reg, offset, 0); loc_result = new_loc_descr (DW_OP_breg0 + reg, offset, 0);
...@@ -8248,10 +8347,15 @@ is_based_loc (rtx rtl) ...@@ -8248,10 +8347,15 @@ is_based_loc (rtx rtl)
MODE is the mode of the memory reference, needed to handle some MODE is the mode of the memory reference, needed to handle some
autoincrement addressing modes. autoincrement addressing modes.
CAN_USE_FBREG is a flag whether we can use DW_AT_frame_base in the location
list for RTL. We can't use it when we are emitting location list for
virtual variable frame_base_decl (i.e. a location list for DW_AT_frame_base)
which describes how frame base changes when !frame_pointer_needed.
Return 0 if we can't represent the location. */ Return 0 if we can't represent the location. */
static dw_loc_descr_ref static dw_loc_descr_ref
mem_loc_descriptor (rtx rtl, enum machine_mode mode) mem_loc_descriptor (rtx rtl, enum machine_mode mode, bool can_use_fbreg)
{ {
dw_loc_descr_ref mem_loc_result = NULL; dw_loc_descr_ref mem_loc_result = NULL;
...@@ -8297,11 +8401,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) ...@@ -8297,11 +8401,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
memory) so DWARF consumers need to be aware of the subtle memory) so DWARF consumers need to be aware of the subtle
distinction between OP_REG and OP_BASEREG. */ distinction between OP_REG and OP_BASEREG. */
if (REGNO (rtl) < FIRST_PSEUDO_REGISTER) if (REGNO (rtl) < FIRST_PSEUDO_REGISTER)
mem_loc_result = based_loc_descr (reg_number (rtl), 0); mem_loc_result = based_loc_descr (reg_number (rtl), 0, can_use_fbreg);
break; break;
case MEM: case MEM:
mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl)); mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
can_use_fbreg);
if (mem_loc_result != 0) if (mem_loc_result != 0)
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0)); add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
break; break;
...@@ -8368,10 +8473,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) ...@@ -8368,10 +8473,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
plus: plus:
if (is_based_loc (rtl)) if (is_based_loc (rtl))
mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)), mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)),
INTVAL (XEXP (rtl, 1))); INTVAL (XEXP (rtl, 1)),
can_use_fbreg);
else else
{ {
mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode); mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode,
can_use_fbreg);
if (mem_loc_result == 0) if (mem_loc_result == 0)
break; break;
...@@ -8383,7 +8490,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) ...@@ -8383,7 +8490,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
else else
{ {
add_loc_descr (&mem_loc_result, add_loc_descr (&mem_loc_result,
mem_loc_descriptor (XEXP (rtl, 1), mode)); mem_loc_descriptor (XEXP (rtl, 1), mode,
can_use_fbreg));
add_loc_descr (&mem_loc_result, add_loc_descr (&mem_loc_result,
new_loc_descr (DW_OP_plus, 0, 0)); new_loc_descr (DW_OP_plus, 0, 0));
} }
...@@ -8394,8 +8502,10 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) ...@@ -8394,8 +8502,10 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
{ {
/* If a pseudo-reg is optimized away, it is possible for it to /* If a pseudo-reg is optimized away, it is possible for it to
be replaced with a MEM containing a multiply. */ be replaced with a MEM containing a multiply. */
dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode); dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode,
dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode); can_use_fbreg);
dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode,
can_use_fbreg);
if (op0 == 0 || op1 == 0) if (op0 == 0 || op1 == 0)
break; break;
...@@ -8414,7 +8524,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) ...@@ -8414,7 +8524,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
/* If this is a MEM, return its address. Otherwise, we can't /* If this is a MEM, return its address. Otherwise, we can't
represent this. */ represent this. */
if (GET_CODE (XEXP (rtl, 0)) == MEM) if (GET_CODE (XEXP (rtl, 0)) == MEM)
return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode); return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode,
can_use_fbreg);
else else
return 0; return 0;
...@@ -8432,8 +8543,8 @@ static dw_loc_descr_ref ...@@ -8432,8 +8543,8 @@ static dw_loc_descr_ref
concat_loc_descriptor (rtx x0, rtx x1) concat_loc_descriptor (rtx x0, rtx x1)
{ {
dw_loc_descr_ref cc_loc_result = NULL; dw_loc_descr_ref cc_loc_result = NULL;
dw_loc_descr_ref x0_ref = loc_descriptor (x0); dw_loc_descr_ref x0_ref = loc_descriptor (x0, true);
dw_loc_descr_ref x1_ref = loc_descriptor (x1); dw_loc_descr_ref x1_ref = loc_descriptor (x1, true);
if (x0_ref == 0 || x1_ref == 0) if (x0_ref == 0 || x1_ref == 0)
return 0; return 0;
...@@ -8460,7 +8571,7 @@ concat_loc_descriptor (rtx x0, rtx x1) ...@@ -8460,7 +8571,7 @@ concat_loc_descriptor (rtx x0, rtx x1)
If we don't know how to describe it, return 0. */ If we don't know how to describe it, return 0. */
static dw_loc_descr_ref static dw_loc_descr_ref
loc_descriptor (rtx rtl) loc_descriptor (rtx rtl, bool can_use_fbreg)
{ {
dw_loc_descr_ref loc_result = NULL; dw_loc_descr_ref loc_result = NULL;
...@@ -8481,13 +8592,49 @@ loc_descriptor (rtx rtl) ...@@ -8481,13 +8592,49 @@ loc_descriptor (rtx rtl)
break; break;
case MEM: case MEM:
loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl)); loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
can_use_fbreg);
break; break;
case CONCAT: case CONCAT:
loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1)); loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1));
break; break;
case VAR_LOCATION:
/* Single part. */
if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
{
loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0), can_use_fbreg);
}
/* Multiple parts. */
else
{
rtvec par_elems = XVEC (XEXP (rtl, 1), 0);
int num_elem = GET_NUM_ELEM (par_elems);
enum machine_mode mode;
int i;
/* Create the first one, so we have something to add to. */
loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0),
can_use_fbreg);
mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
add_loc_descr (&loc_result,
new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
for (i = 1; i < num_elem; i++)
{
dw_loc_descr_ref temp;
temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0),
can_use_fbreg);
add_loc_descr (&loc_result, temp);
mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
add_loc_descr (&loc_result,
new_loc_descr (DW_OP_piece,
GET_MODE_SIZE (mode), 0));
}
}
break;
default: default:
abort (); abort ();
} }
...@@ -8603,7 +8750,7 @@ loc_descriptor_from_tree (tree loc, int addressp) ...@@ -8603,7 +8750,7 @@ loc_descriptor_from_tree (tree loc, int addressp)
rtl = XEXP (rtl, 0); rtl = XEXP (rtl, 0);
} }
ret = mem_loc_descriptor (rtl, mode); ret = mem_loc_descriptor (rtl, mode, true);
} }
} }
break; break;
...@@ -8687,7 +8834,7 @@ loc_descriptor_from_tree (tree loc, int addressp) ...@@ -8687,7 +8834,7 @@ loc_descriptor_from_tree (tree loc, int addressp)
rtl = (*targetm.delegitimize_address) (rtl); rtl = (*targetm.delegitimize_address) (rtl);
indirect_p = 1; indirect_p = 1;
ret = mem_loc_descriptor (rtl, mode); ret = mem_loc_descriptor (rtl, mode, true);
break; break;
} }
...@@ -9481,16 +9628,110 @@ rtl_for_decl_location (tree decl) ...@@ -9481,16 +9628,110 @@ rtl_for_decl_location (tree decl)
function call evaluates to a compile-time constant address. */ function call evaluates to a compile-time constant address. */
static void static void
add_location_or_const_value_attribute (dw_die_ref die, tree decl) add_location_or_const_value_attribute (dw_die_ref die, tree decl,
enum dwarf_attribute attr)
{ {
rtx rtl; rtx rtl;
dw_loc_descr_ref descr; dw_loc_descr_ref descr;
var_loc_list *loc_list;
if (TREE_CODE (decl) == ERROR_MARK) if (TREE_CODE (decl) == ERROR_MARK)
return; return;
else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL) else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL)
abort (); abort ();
/* 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 *secname;
const char *endname;
dw_loc_list_ref list;
rtx varloc;
struct var_loc_node *node;
/* We need to figure out what section we should use as the base
for the address ranges where a given location is valid.
1. If this particular DECL has a section associated with it,
use that.
2. If this function has a section associated with it, use
that.
3. Otherwise, use the text section.
XXX: If you split a variable across multiple sections, this
won't notice. */
if (DECL_SECTION_NAME (decl))
{
tree sectree = DECL_SECTION_NAME (decl);
secname = TREE_STRING_POINTER (sectree);
}
else if (current_function_decl
&& DECL_SECTION_NAME (current_function_decl))
{
tree sectree = DECL_SECTION_NAME (current_function_decl);
secname = TREE_STRING_POINTER (sectree);
}
else
secname = TEXT_SECTION_NAME;
/* 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);
list = new_loc_list (loc_descriptor (varloc, attr != DW_AT_frame_base),
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. */
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
add_loc_descr_to_loc_list (&list,
loc_descriptor (varloc,
attr != DW_AT_frame_base),
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];
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);
}
add_loc_descr_to_loc_list (&list,
loc_descriptor (varloc,
attr != DW_AT_frame_base),
node->label, endname, secname);
}
/* Finally, add the location list to the DIE, and we are done. */
add_AT_loc_list (die, attr, list);
return;
}
rtl = rtl_for_decl_location (decl); rtl = rtl_for_decl_location (decl);
if (rtl == NULL_RTX) if (rtl == NULL_RTX)
return; return;
...@@ -9527,9 +9768,9 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl) ...@@ -9527,9 +9768,9 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl)
case REG: case REG:
case SUBREG: case SUBREG:
case CONCAT: case CONCAT:
descr = loc_descriptor (rtl); descr = loc_descriptor (rtl, true);
} }
add_AT_location_description (die, DW_AT_location, descr); add_AT_location_description (die, attr, descr);
break; break;
case PARALLEL: case PARALLEL:
...@@ -9540,7 +9781,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl) ...@@ -9540,7 +9781,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl)
int i; int i;
/* Create the first one, so we have something to add to. */ /* Create the first one, so we have something to add to. */
descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0)); descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), true);
mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0)); mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
add_loc_descr (&descr, add_loc_descr (&descr,
new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0)); new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
...@@ -9548,7 +9789,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl) ...@@ -9548,7 +9789,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl)
{ {
dw_loc_descr_ref temp; dw_loc_descr_ref temp;
temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0)); temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0), true);
add_loc_descr (&descr, temp); add_loc_descr (&descr, temp);
mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
add_loc_descr (&descr, add_loc_descr (&descr,
...@@ -9694,7 +9935,7 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b ...@@ -9694,7 +9935,7 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b
add_AT_flag (decl_die, DW_AT_artificial, 1); add_AT_flag (decl_die, DW_AT_artificial, 1);
add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx); add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
add_AT_location_description (decl_die, DW_AT_location, add_AT_location_description (decl_die, DW_AT_location,
loc_descriptor (loc)); loc_descriptor (loc, true));
add_AT_die_ref (subrange_die, bound_attr, decl_die); add_AT_die_ref (subrange_die, bound_attr, decl_die);
} }
...@@ -10517,7 +10758,7 @@ gen_formal_parameter_die (tree node, dw_die_ref context_die) ...@@ -10517,7 +10758,7 @@ gen_formal_parameter_die (tree node, dw_die_ref context_die)
equate_decl_number_to_die (node, parm_die); equate_decl_number_to_die (node, parm_die);
if (! DECL_ABSTRACT (node)) if (! DECL_ABSTRACT (node))
add_location_or_const_value_attribute (parm_die, node); add_location_or_const_value_attribute (parm_die, node, DW_AT_location);
break; break;
...@@ -10851,9 +11092,17 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) ...@@ -10851,9 +11092,17 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
/* Define the "frame base" location for this routine. We use the /* Define the "frame base" location for this routine. We use the
frame pointer or stack pointer registers, since the RTL for local frame pointer or stack pointer registers, since the RTL for local
variables is relative to one of them. */ variables is relative to one of them. */
if (frame_base_decl && lookup_decl_loc (frame_base_decl) != NULL)
{
add_location_or_const_value_attribute (subr_die, frame_base_decl,
DW_AT_frame_base);
}
else
{
fp_reg fp_reg
= frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx; = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx;
add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg)); add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg));
}
#if 0 #if 0
/* ??? This fails for nested inline functions, because context_display /* ??? This fails for nested inline functions, because context_display
...@@ -11022,7 +11271,7 @@ gen_variable_die (tree decl, dw_die_ref context_die) ...@@ -11022,7 +11271,7 @@ gen_variable_die (tree decl, dw_die_ref context_die)
if (! declaration && ! DECL_ABSTRACT (decl)) if (! declaration && ! DECL_ABSTRACT (decl))
{ {
add_location_or_const_value_attribute (var_die, decl); add_location_or_const_value_attribute (var_die, decl, DW_AT_location);
add_pubname (decl, var_die); add_pubname (decl, var_die);
} }
else else
...@@ -12542,6 +12791,61 @@ init_file_table (void) ...@@ -12542,6 +12791,61 @@ init_file_table (void)
file_table_last_lookup_index = 0; file_table_last_lookup_index = 0;
} }
/* Called by the final INSN scan whenever we see a var location. We
use it to drop labels in the right places, and throw the location in
our lookup table. */
static void
dwarf2out_var_location (rtx loc_note)
{
char loclabel[MAX_ARTIFICIAL_LABEL_BYTES];
struct var_loc_node *newloc;
rtx prev_insn;
static rtx last_insn;
static const char *last_label;
if (!DECL_P (NOTE_VAR_LOCATION_DECL (loc_note)))
return;
prev_insn = PREV_INSN (loc_note);
newloc = ggc_alloc_cleared (sizeof (struct var_loc_node));
/* If the insn we processed last time is the previous insn
and it is also a var location note, use the label we emitted
last time. */
if (last_insn != NULL_RTX
&& last_insn == prev_insn
&& GET_CODE (prev_insn) == NOTE
&& NOTE_LINE_NUMBER (prev_insn) == NOTE_INSN_VAR_LOCATION)
{
newloc->label = last_label;
}
else
{
ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", loclabel_num);
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LVL", loclabel_num);
loclabel_num++;
newloc->label = ggc_strdup (loclabel);
}
newloc->var_loc_note = loc_note;
newloc->next = NULL;
last_insn = loc_note;
last_label = newloc->label;
add_var_loc_to_decl (NOTE_VAR_LOCATION_DECL (loc_note), newloc);
}
/* We need to reset the locations at the beginning of each
function. We can't do this in the end_function hook, because the
declarations that use the locations won't have been outputted when
that hook is called. */
static void
dwarf2out_begin_function (tree unused ATTRIBUTE_UNUSED)
{
htab_empty (decl_loc_table);
}
/* Output a label to mark the beginning of a source code line entry /* Output a label to mark the beginning of a source code line entry
and record information relating to this source line, in and record information relating to this source line, in
'line_info_table' for later output of the .debug_line section. */ 'line_info_table' for later output of the .debug_line section. */
...@@ -12714,10 +13018,14 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED) ...@@ -12714,10 +13018,14 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
{ {
init_file_table (); init_file_table ();
/* Allocate the initial hunk of the decl_die_table. */ /* Allocate the decl_die_table. */
decl_die_table = htab_create_ggc (10, decl_die_table_hash, decl_die_table = htab_create_ggc (10, decl_die_table_hash,
decl_die_table_eq, NULL); decl_die_table_eq, NULL);
/* Allocate the decl_loc_table. */
decl_loc_table = htab_create_ggc (10, decl_loc_table_hash,
decl_loc_table_eq, NULL);
/* Allocate the initial hunk of the decl_scope_table. */ /* Allocate the initial hunk of the decl_scope_table. */
VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table"); VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table");
......
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