From: Daniel Berlin Date: Fri, 6 Feb 2004 20:17:00 +0000 (+0000) Subject: dwarf2out.c (struct gcc_debug_hooks): Call dwarf2out_begin_function at the beginning... X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0a2d3d691973e08a0e5c20c4c90cbb38010b0c9e;p=platform%2Fupstream%2Fgcc.git 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 From-SVN: r77421 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6853041..b44197f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,34 @@ +2004-02-06 Daniel Berlin + Josef Zlomek + + * 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 * loop.c (force_movables): Transitively increase the priorities of diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index e407a0b..b35b5ea 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -3251,6 +3251,8 @@ static bool dwarf2out_ignore_block (tree); static void dwarf2out_global_decl (tree); static void dwarf2out_imported_module_or_decl (tree, tree); static void dwarf2out_abstract_function (tree); +static void dwarf2out_var_location (rtx); +static void dwarf2out_begin_function (tree); /* The debug hooks structure. */ @@ -3269,7 +3271,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = dwarf2out_begin_prologue, debug_nothing_int_charstar, /* end_prologue */ dwarf2out_end_epilogue, - debug_nothing_tree, /* begin_function */ + dwarf2out_begin_function, debug_nothing_int, /* end_function */ dwarf2out_decl, /* function_decl */ dwarf2out_global_decl, @@ -3281,7 +3283,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = dwarf2out_abstract_function, /* outlining_inline_function */ debug_nothing_rtx, /* label */ debug_nothing_int, /* handle_pch */ - debug_nothing_rtx /* var_location */ + dwarf2out_var_location }; #endif @@ -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. */ 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 are uniquely identified by their tag, presence/absence of children DIE's, and list of attribute/value pairs. */ @@ -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 int decl_die_table_eq (const void *, const void *); 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 add_var_loc_to_decl (tree, struct var_loc_node *); static void print_spaces (FILE *); static void print_die (dw_die_ref, FILE *); static void print_dwarf_line_table (FILE *); @@ -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 multiple_reg_loc_descriptor (rtx, rtx); 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 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 loc_descriptor (rtx); +static dw_loc_descr_ref loc_descriptor (rtx, bool); static dw_loc_descr_ref loc_descriptor_from_tree (tree, int); static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int); static tree field_type (tree); @@ -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_const_value_attribute (dw_die_ref, rtx); 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 add_name_attribute (dw_die_ref, const char *); static void add_comp_dir_attribute (dw_die_ref); @@ -5229,6 +5264,31 @@ lookup_decl_die (tree 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. */ static void @@ -5241,6 +5301,45 @@ equate_decl_number_to_die (tree decl, dw_die_ref decl_die) *slot = decl_die; 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 output of the debugging routines that print the structure of @@ -8204,7 +8303,7 @@ int_loc_descriptor (HOST_WIDE_INT i) /* Return a location descriptor that designates a base+offset location. */ 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; /* 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) ? HARD_FRAME_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); else if (reg <= 31) loc_result = new_loc_descr (DW_OP_breg0 + reg, offset, 0); @@ -8248,10 +8347,15 @@ is_based_loc (rtx rtl) MODE is the mode of the memory reference, needed to handle some 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. */ 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; @@ -8297,11 +8401,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) memory) so DWARF consumers need to be aware of the subtle distinction between OP_REG and OP_BASEREG. */ 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; 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) add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0)); break; @@ -8368,10 +8473,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) plus: if (is_based_loc (rtl)) mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)), - INTVAL (XEXP (rtl, 1))); + INTVAL (XEXP (rtl, 1)), + can_use_fbreg); 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) break; @@ -8383,7 +8490,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) else { 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, new_loc_descr (DW_OP_plus, 0, 0)); } @@ -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 be replaced with a MEM containing a multiply. */ - dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode); - dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode); + dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, + can_use_fbreg); + dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode, + can_use_fbreg); if (op0 == 0 || op1 == 0) break; @@ -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 represent this. */ 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 return 0; @@ -8432,8 +8543,8 @@ static dw_loc_descr_ref concat_loc_descriptor (rtx x0, rtx x1) { dw_loc_descr_ref cc_loc_result = NULL; - dw_loc_descr_ref x0_ref = loc_descriptor (x0); - dw_loc_descr_ref x1_ref = loc_descriptor (x1); + dw_loc_descr_ref x0_ref = loc_descriptor (x0, true); + dw_loc_descr_ref x1_ref = loc_descriptor (x1, true); if (x0_ref == 0 || x1_ref == 0) return 0; @@ -8460,7 +8571,7 @@ concat_loc_descriptor (rtx x0, rtx x1) If we don't know how to describe it, return 0. */ static dw_loc_descr_ref -loc_descriptor (rtx rtl) +loc_descriptor (rtx rtl, bool can_use_fbreg) { dw_loc_descr_ref loc_result = NULL; @@ -8481,13 +8592,49 @@ loc_descriptor (rtx rtl) break; 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; case CONCAT: loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1)); 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: abort (); } @@ -8603,7 +8750,7 @@ loc_descriptor_from_tree (tree loc, int addressp) rtl = XEXP (rtl, 0); } - ret = mem_loc_descriptor (rtl, mode); + ret = mem_loc_descriptor (rtl, mode, true); } } break; @@ -8687,7 +8834,7 @@ loc_descriptor_from_tree (tree loc, int addressp) rtl = (*targetm.delegitimize_address) (rtl); indirect_p = 1; - ret = mem_loc_descriptor (rtl, mode); + ret = mem_loc_descriptor (rtl, mode, true); break; } @@ -9481,16 +9628,110 @@ rtl_for_decl_location (tree decl) function call evaluates to a compile-time constant address. */ 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; dw_loc_descr_ref descr; + var_loc_list *loc_list; if (TREE_CODE (decl) == ERROR_MARK) return; else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL) 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); if (rtl == NULL_RTX) return; @@ -9527,9 +9768,9 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl) case REG: case SUBREG: 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; case PARALLEL: @@ -9540,7 +9781,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl) int i; /* 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)); add_loc_descr (&descr, 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) { 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); mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); add_loc_descr (&descr, @@ -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_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx); 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); } @@ -10517,7 +10758,7 @@ gen_formal_parameter_die (tree node, dw_die_ref context_die) equate_decl_number_to_die (node, parm_die); 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; @@ -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 frame pointer or stack pointer registers, since the RTL for local variables is relative to one of them. */ - fp_reg - = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx; - add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg)); + 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 + = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx; + add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg)); + } #if 0 /* ??? This fails for nested inline functions, because context_display @@ -11022,7 +11271,7 @@ gen_variable_die (tree decl, dw_die_ref context_die) 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); } else @@ -12542,6 +12791,61 @@ init_file_table (void) 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 and record information relating to this source line, in 'line_info_table' for later output of the .debug_line section. */ @@ -12714,10 +13018,14 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED) { 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_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. */ VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table");