diff options
author | Jakub Jelinek <jakub@redhat.com> | 2011-03-16 09:32:13 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2011-03-16 09:32:13 +0100 |
commit | 2b1c543325692d744eec22f779656e13605c3ceb (patch) | |
tree | aeb4609b3e08ab1fc279aa49e68d456a808be9f0 /gcc/dwarf2out.c | |
parent | 9ef13bd018fc5c6e2dc57aa36d378919c8aeded1 (diff) | |
download | gcc-2b1c543325692d744eec22f779656e13605c3ceb.zip gcc-2b1c543325692d744eec22f779656e13605c3ceb.tar.gz gcc-2b1c543325692d744eec22f779656e13605c3ceb.tar.bz2 |
final.c (final_scan_insn): Handle NOTE_INSN_CALL_ARG_LOCATION.
* final.c (final_scan_insn): Handle NOTE_INSN_CALL_ARG_LOCATION.
Call var_location debug hook even on CALL_INSNs.
(rest_of_clean_state): Don't print NOTE_INSN_CALL_ARG_LOCATION.
* rtl.def (ENTRY_VALUE): New.
* dwarf2out.c: Include cfglayout.h.
(dwarf_stack_op_name, size_of_loc_descr, output_loc_operands,
output_loc_operands_raw): Handle DW_OP_GNU_entry_value.
(struct call_arg_loc_node): New type.
(call_arg_locations, call_arg_loc_last, block_map, call_site_count,
tail_call_site_count): New variables.
(dwarf_tag_name): Handle DW_TAG_GNU_call_site and
DW_TAG_GNU_call_site_parameter.
(dwarf_attr_name): Handle DW_AT_GNU_call_site_value,
DW_AT_GNU_call_site_data_value, DW_AT_GNU_call_site_target,
DW_AT_GNU_call_site_target_clobbered, DW_AT_GNU_tail_call,
DW_AT_GNU_all_tail_call_sites, DW_AT_GNU_all_call_sites
and DW_AT_GNU_all_source_call_sites.
(mem_loc_descriptor): Handle ENTRY_VALUE.
(add_src_coords_attributes): Don't add enything if
DECL_SOURCE_LOCATION is UNKNOWN_LOCATION.
(dwarf2out_abstract_function): Save and clear call_arg_location,
call_site_count and tail_call_site_count around dwarf2out_decl call.
(gen_call_site_die): New function.
(gen_subprogram_die): Emit DW_TAG_GNU_call_site DIEs for call sites.
(gen_lexical_block_die, gen_inlined_subroutine_die): Update block_map.
(dwarf2out_function_decl): Clear call_arg_locations,
call_arg_loc_last, set call_site_count and tail_call_site_count
to -1 and free block_map.
(dwarf2out_var_location): Handle NOTE_INSN_CALL_ARG_LOCATION and
CALL_INSNs. Add NOTE_DURING_CALL_P var location notes even when not
followed by any real instructions.
(dwarf2out_begin_function): Set call_site_count and
tail_call_site_count to 0.
(resolve_addr): If DW_AT_abstract_origin of DW_TAG_GNU_call_site
is dw_val_class_addr, attempt to look it up again, for DECL_EXTERNAL
attempt to force a DIE for it and worst case remove the attribute.
(resolve_one_addr): For TREE_CONSTANT_POOL_ADDRESS_P SYMBOL_REFs
check TREE_ASM_WRITTEN of DECL_INITIAL of the decl instead of
the decl itself.
* var-tracking.c: Include tm_p.h.
(vt_stack_adjustments): For calls call note_register_arguments.
(argument_reg_set): New variable.
(add_stores): For MO_VAL_SET of non-tracked regs from argument_reg_set
ensure the VALUE is resolved.
(call_arguments): New variable.
(prepare_call_arguments): New function.
(add_with_sets): For MO_CALL set u.loc from call_arguments and clear it.
(struct expand_loc_callback_data): Add ignore_cur_loc field.
(vt_expand_loc_callback): If ignore_cur_loc, don't look at cur_loc and
always use the best expression.
(vt_expand_loc): Add ignore_cur_loc argument.
(vt_expand_loc_dummy): Clear ignore_cur_loc field.
(emit_note_insn_var_location): Adjust vt_expand_loc callers.
(emit_notes_in_bb) <case MO_CALL>: Add NOTE_INSN_CALL_ARG_LOCATION
note for all calls.
(vt_add_function_parameter): Use cselib_lookup_from_insn.
If dv is a VALUE, enter into hash table also ENTRY_VALUE for the
argument. Don't call cselib_preserve_only_values and
cselib_reset_table.
(note_register_arguments): New function.
(vt_initialize): Compute argument_reg_set. Call
vt_add_function_parameters before processing basic blocks instead of
afterwards. For calls call prepare_call_arguments before calling
cselib_process_insn.
* print-rtl.c (print_rtx): Handle NOTE_INSN_CALL_ARG_LOCATION.
* Makefile.in (dwarf2out.o): Depend on $(CFGLAYOUT_H).
(var-tracking.o): Depend on $(TM_P_H).
* cfglayout.h (insn_scope): New prototype.
* gengtype.c (adjust_field_rtx_def): Handle NOTE_INSN_CALL_ARG_LOCATION.
* cfglayout.c (insn_scope): No longer static.
* insn-notes.def (CALL_ARG_LOCATION): New.
* calls.c (expand_call, emit_library_call_value_1): Put USEs for
MEM arguments into CALL_INSN_FUNCTION_USAGE unconditionally.
* integrate.c (set_block_origin_self, set_block_abstract_flags): Do
nothing for DECL_EXTERNAL BLOCK_VARS.
cp/
* cp-objcp-common.c (cp_function_decl_explicit_p): Don't crash if
DECL_LANG_SPECIFIC is NULL.
include/
* dwarf2.h (DW_TAG_GNU_call_site, DW_TAG_GNU_call_site_parameter,
DW_AT_GNU_call_site_value, DW_AT_GNU_call_site_data_value,
DW_AT_GNU_call_site_target, DW_AT_GNU_call_site_target_clobbered,
DW_AT_GNU_tail_call, DW_AT_GNU_all_tail_call_sites,
DW_AT_GNU_all_call_sites,, DW_AT_GNU_all_source_call_sites,
DW_OP_GNU_entry_value): New.
From-SVN: r171033
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r-- | gcc/dwarf2out.c | 374 |
1 files changed, 360 insertions, 14 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 3319c61..7e257c3 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -92,6 +92,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "tree-pass.h" #include "tree-flow.h" +#include "cfglayout.h" static void dwarf2out_source_line (unsigned int, const char *, int, bool); static rtx last_var_location_insn; @@ -4794,6 +4795,8 @@ dwarf_stack_op_name (unsigned int op) return "DW_OP_GNU_encoded_addr"; case DW_OP_GNU_implicit_pointer: return "DW_OP_GNU_implicit_pointer"; + case DW_OP_GNU_entry_value: + return "DW_OP_GNU_entry_value"; default: return "OP_<unknown>"; @@ -4900,6 +4903,8 @@ loc_list_plus_const (dw_loc_list_ref list_head, HOST_WIDE_INT offset) #define DWARF_REF_SIZE \ (dwarf_version == 2 ? DWARF2_ADDR_SIZE : DWARF_OFFSET_SIZE) +static unsigned long size_of_locs (dw_loc_descr_ref); + /* Return the size of a location descriptor. */ static unsigned long @@ -5015,6 +5020,12 @@ size_of_loc_descr (dw_loc_descr_ref loc) case DW_OP_GNU_implicit_pointer: size += DWARF_REF_SIZE + size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int); break; + case DW_OP_GNU_entry_value: + { + unsigned long op_size = size_of_locs (loc->dw_loc_oprnd1.v.val_loc); + size += size_of_uleb128 (op_size) + op_size; + break; + } default: break; } @@ -5052,6 +5063,7 @@ size_of_locs (dw_loc_descr_ref loc) static HOST_WIDE_INT extract_int (const unsigned char *, unsigned); static void get_ref_die_offset_label (char *, dw_die_ref); +static void output_loc_sequence (dw_loc_descr_ref, int); /* Output location description stack opcode's operands (if any). The for_eh_or_skip parameter controls whether register numbers are @@ -5301,6 +5313,11 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip) } break; + case DW_OP_GNU_entry_value: + dw2_asm_output_data_uleb128 (size_of_locs (val1->v.val_loc), NULL); + output_loc_sequence (val1->v.val_loc, for_eh_or_skip); + break; + default: /* Other codes have no operands. */ break; @@ -5477,6 +5494,7 @@ output_loc_operands_raw (dw_loc_descr_ref loc) break; case DW_OP_GNU_implicit_pointer: + case DW_OP_GNU_entry_value: gcc_unreachable (); break; @@ -6115,10 +6133,33 @@ struct GTY (()) var_loc_list_def { }; typedef struct var_loc_list_def var_loc_list; +/* Call argument location list. */ +struct GTY ((chain_next ("%h.next"))) call_arg_loc_node { + rtx GTY (()) call_arg_loc_note; + const char * GTY (()) label; + tree GTY (()) block; + bool tail_call_p; + rtx GTY (()) symbol_ref; + struct call_arg_loc_node * GTY (()) next; +}; + /* Table of decl location linked lists. */ static GTY ((param_is (var_loc_list))) htab_t decl_loc_table; +/* Head and tail of call_arg_loc chain. */ +static GTY (()) struct call_arg_loc_node *call_arg_locations; +static struct call_arg_loc_node *call_arg_loc_last; + +/* Number of call sites in the current function. */ +static int call_site_count = -1; +/* Number of tail call sites in the current function. */ +static int tail_call_site_count = -1; + +/* Vector mapping block numbers to DW_TAG_{lexical_block,inlined_subroutine} + DIEs. */ +static VEC (dw_die_ref, heap) *block_map; + /* 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. */ @@ -6907,6 +6948,10 @@ dwarf_tag_name (unsigned int tag) return "DW_TAG_GNU_EINCL"; case DW_TAG_GNU_template_template_param: return "DW_TAG_GNU_template_template_param"; + case DW_TAG_GNU_call_site: + return "DW_TAG_GNU_call_site"; + case DW_TAG_GNU_call_site_parameter: + return "DW_TAG_GNU_call_site_parameter"; default: return "DW_TAG_<unknown>"; } @@ -7151,6 +7196,22 @@ dwarf_attr_name (unsigned int attr) return "DW_AT_GNU_odr_signature"; case DW_AT_GNU_template_name: return "DW_AT_GNU_template_name"; + case DW_AT_GNU_call_site_value: + return "DW_AT_GNU_call_site_value"; + case DW_AT_GNU_call_site_data_value: + return "DW_AT_GNU_call_site_data_value"; + case DW_AT_GNU_call_site_target: + return "DW_AT_GNU_call_site_target"; + case DW_AT_GNU_call_site_target_clobbered: + return "DW_AT_GNU_call_site_target_clobbered"; + case DW_AT_GNU_tail_call: + return "DW_AT_GNU_tail_call"; + case DW_AT_GNU_all_tail_call_sites: + return "DW_AT_GNU_all_tail_call_sites"; + case DW_AT_GNU_all_call_sites: + return "DW_AT_GNU_all_call_sites"; + case DW_AT_GNU_all_source_call_sites: + return "DW_AT_GNU_all_source_call_sites"; case DW_AT_VMS_rtnbeg_pd_address: return "DW_AT_VMS_rtnbeg_pd_address"; @@ -13964,6 +14025,26 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, "CONCAT/CONCATN/VAR_LOCATION is handled only by loc_descriptor"); return 0; + case ENTRY_VALUE: + mem_loc_result = new_loc_descr (DW_OP_GNU_entry_value, 0, 0); + mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_loc; + if (REG_P (XEXP (rtl, 0))) + mem_loc_result->dw_loc_oprnd1.v.val_loc + = one_reg_loc_descriptor (dbx_reg_number (XEXP (rtl, 0)), + VAR_INIT_STATUS_INITIALIZED); + else if (MEM_P (XEXP (rtl, 0)) && REG_P (XEXP (XEXP (rtl, 0), 0))) + { + dw_loc_descr_ref ref + = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl), + VAR_INIT_STATUS_INITIALIZED); + if (ref == NULL) + return NULL; + mem_loc_result->dw_loc_oprnd1.v.val_loc = ref; + } + else + gcc_unreachable (); + return mem_loc_result; + case PRE_MODIFY: /* Extract the PLUS expression nested inside and fall into PLUS code below. */ @@ -17842,8 +17923,11 @@ add_linkage_attr (dw_die_ref die, tree decl) static void add_src_coords_attributes (dw_die_ref die, tree decl) { - expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl)); + expanded_location s; + if (DECL_SOURCE_LOCATION (decl) == UNKNOWN_LOCATION) + return; + s = expand_location (DECL_SOURCE_LOCATION (decl)); add_AT_file (die, DW_AT_decl_file, lookup_filename (s.file)); add_AT_unsigned (die, DW_AT_decl_line, s.line); } @@ -18872,6 +18956,8 @@ dwarf2out_abstract_function (tree decl) tree context; int was_abstract; htab_t old_decl_loc_table; + int old_call_site_count, old_tail_call_site_count; + struct call_arg_loc_node *old_call_arg_locations; /* Make sure we have the actual abstract inline, not a clone. */ decl = DECL_ORIGIN (decl); @@ -18886,6 +18972,12 @@ dwarf2out_abstract_function (tree decl) get locations in abstract instantces. */ old_decl_loc_table = decl_loc_table; decl_loc_table = NULL; + old_call_arg_locations = call_arg_locations; + call_arg_locations = NULL; + old_call_site_count = call_site_count; + call_site_count = -1; + old_tail_call_site_count = tail_call_site_count; + tail_call_site_count = -1; /* Be sure we've emitted the in-class declaration DIE (if any) first, so we don't get confused by DECL_ABSTRACT. */ @@ -18910,6 +19002,9 @@ dwarf2out_abstract_function (tree decl) current_function_decl = save_fn; decl_loc_table = old_decl_loc_table; + call_arg_locations = old_call_arg_locations; + call_site_count = old_call_site_count; + tail_call_site_count = old_tail_call_site_count; pop_cfun (); } @@ -18985,6 +19080,43 @@ premark_types_used_by_global_vars (void) premark_types_used_by_global_vars_helper, NULL); } +/* Generate a DW_TAG_GNU_call_site DIE in function DECL under SUBR_DIE + for CA_LOC call arg loc node. */ + +static dw_die_ref +gen_call_site_die (tree decl, dw_die_ref subr_die, + struct call_arg_loc_node *ca_loc) +{ + dw_die_ref stmt_die = NULL, die; + tree block = ca_loc->block; + + while (block + && block != DECL_INITIAL (decl) + && TREE_CODE (block) == BLOCK) + { + if (VEC_length (dw_die_ref, block_map) > BLOCK_NUMBER (block)) + stmt_die = VEC_index (dw_die_ref, block_map, BLOCK_NUMBER (block)); + if (stmt_die) + break; + block = BLOCK_SUPERCONTEXT (block); + } + if (stmt_die == NULL) + stmt_die = subr_die; + die = new_die (DW_TAG_GNU_call_site, stmt_die, NULL_TREE); + add_AT_lbl_id (die, DW_AT_low_pc, ca_loc->label); + if (ca_loc->tail_call_p) + add_AT_flag (die, DW_AT_GNU_tail_call, 1); + if (ca_loc->symbol_ref) + { + dw_die_ref tdie = lookup_decl_die (SYMBOL_REF_DECL (ca_loc->symbol_ref)); + if (tdie) + add_AT_die_ref (die, DW_AT_abstract_origin, tdie); + else + add_AT_addr (die, DW_AT_abstract_origin, ca_loc->symbol_ref); + } + return die; +} + /* Generate a DIE to represent a declared function (either file-scope or block-local). */ @@ -19467,12 +19599,113 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) constructor function. */ if (! declaration && TREE_CODE (outer_scope) != ERROR_MARK) { + int call_site_note_count = 0; + int tail_call_site_note_count = 0; + /* Emit a DW_TAG_variable DIE for a named return value. */ if (DECL_NAME (DECL_RESULT (decl))) gen_decl_die (DECL_RESULT (decl), NULL, subr_die); current_function_has_inlines = 0; decls_for_scope (outer_scope, subr_die, 0); + + if (call_arg_locations) + { + struct call_arg_loc_node *ca_loc; + for (ca_loc = call_arg_locations; ca_loc; ca_loc = ca_loc->next) + { + dw_die_ref die = NULL; + rtx tloc = NULL_RTX; + rtx arg, next_arg; + + for (arg = NOTE_VAR_LOCATION (ca_loc->call_arg_loc_note); + arg; arg = next_arg) + { + dw_loc_descr_ref reg, val; + enum machine_mode mode = GET_MODE (XEXP (XEXP (arg, 0), 1)); + dw_die_ref cdie; + + next_arg = XEXP (arg, 1); + if (REG_P (XEXP (XEXP (arg, 0), 0)) + && next_arg + && MEM_P (XEXP (XEXP (next_arg, 0), 0)) + && REG_P (XEXP (XEXP (XEXP (next_arg, 0), 0), 0)) + && REGNO (XEXP (XEXP (arg, 0), 0)) + == REGNO (XEXP (XEXP (XEXP (next_arg, 0), 0), 0))) + next_arg = XEXP (next_arg, 1); + if (mode == VOIDmode) + mode = GET_MODE (XEXP (XEXP (arg, 0), 0)); + if (GET_MODE_CLASS (mode) != MODE_INT + || GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE) + continue; + if (XEXP (XEXP (arg, 0), 0) == pc_rtx) + { + gcc_assert (ca_loc->symbol_ref == NULL_RTX); + tloc = XEXP (XEXP (arg, 0), 1); + continue; + } + if (REG_P (XEXP (XEXP (arg, 0), 0))) + reg = reg_loc_descriptor (XEXP (XEXP (arg, 0), 0), + VAR_INIT_STATUS_INITIALIZED); + else if (MEM_P (XEXP (XEXP (arg, 0), 0))) + reg = mem_loc_descriptor (XEXP (XEXP (XEXP (arg, 0), + 0), 0), mode, + VAR_INIT_STATUS_INITIALIZED); + else + continue; + if (reg == NULL) + continue; + val = mem_loc_descriptor (XEXP (XEXP (arg, 0), 1), VOIDmode, + VAR_INIT_STATUS_INITIALIZED); + if (val == NULL) + continue; + if (die == NULL) + die = gen_call_site_die (decl, subr_die, ca_loc); + cdie = new_die (DW_TAG_GNU_call_site_parameter, die, + NULL_TREE); + add_AT_loc (cdie, DW_AT_location, reg); + add_AT_loc (cdie, DW_AT_GNU_call_site_value, val); + if (next_arg != XEXP (arg, 1)) + { + val = mem_loc_descriptor (XEXP (XEXP (XEXP (arg, 1), + 0), 1), VOIDmode, + VAR_INIT_STATUS_INITIALIZED); + if (val != NULL) + add_AT_loc (cdie, DW_AT_GNU_call_site_data_value, val); + } + } + if (die == NULL + && (ca_loc->symbol_ref || tloc)) + die = gen_call_site_die (decl, subr_die, ca_loc); + if (die != NULL && tloc != NULL_RTX) + { + dw_loc_descr_ref tval + = mem_loc_descriptor (tloc, VOIDmode, + VAR_INIT_STATUS_INITIALIZED); + if (tval) + add_AT_loc (die, DW_AT_GNU_call_site_target, tval); + } + if (die != NULL) + { + call_site_note_count++; + if (ca_loc->tail_call_p) + tail_call_site_note_count++; + } + } + call_arg_locations = NULL; + call_arg_loc_last = NULL; + } + if (tail_call_site_count >= 0 + && tail_call_site_count == tail_call_site_note_count) + { + if (call_site_count >= 0 + && call_site_count == call_site_note_count) + add_AT_flag (subr_die, DW_AT_GNU_all_call_sites, 1); + else + add_AT_flag (subr_die, DW_AT_GNU_all_tail_call_sites, 1); + } + call_site_count = -1; + tail_call_site_count = -1; } /* Add the calling convention attribute if requested. */ add_calling_convention_attribute (subr_die, decl); @@ -19861,6 +20094,14 @@ gen_lexical_block_die (tree stmt, dw_die_ref context_die, int depth) { dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt); + if (call_arg_locations) + { + if (VEC_length (dw_die_ref, block_map) <= BLOCK_NUMBER (stmt)) + VEC_safe_grow_cleared (dw_die_ref, heap, block_map, + BLOCK_NUMBER (stmt) + 1); + VEC_replace (dw_die_ref, block_map, BLOCK_NUMBER (stmt), stmt_die); + } + if (! BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt)) add_high_low_attributes (stmt, stmt_die); @@ -19891,6 +20132,13 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die, int depth) dw_die_ref subr_die = new_die (DW_TAG_inlined_subroutine, context_die, stmt); + if (call_arg_locations) + { + if (VEC_length (dw_die_ref, block_map) <= BLOCK_NUMBER (stmt)) + VEC_safe_grow_cleared (dw_die_ref, heap, block_map, + BLOCK_NUMBER (stmt) + 1); + VEC_replace (dw_die_ref, block_map, BLOCK_NUMBER (stmt), subr_die); + } add_abstract_origin_attribute (subr_die, decl); if (TREE_ASM_WRITTEN (stmt)) add_high_low_attributes (stmt, subr_die); @@ -21502,7 +21750,11 @@ static void dwarf2out_function_decl (tree decl) { dwarf2out_decl (decl); - + call_arg_locations = NULL; + call_arg_loc_last = NULL; + call_site_count = -1; + tail_call_site_count = -1; + VEC_free (dw_die_ref, heap, block_map); htab_empty (decl_loc_table); } @@ -21899,16 +22151,35 @@ dwarf2out_var_location (rtx loc_note) static const char *last_postcall_label; static bool last_in_cold_section_p; tree decl; + bool var_loc_p; + + if (!NOTE_P (loc_note)) + { + if (CALL_P (loc_note)) + { + call_site_count++; + if (SIBLING_CALL_P (loc_note)) + tail_call_site_count++; + } + return; + } - if (!DECL_P (NOTE_VAR_LOCATION_DECL (loc_note))) + var_loc_p = NOTE_KIND (loc_note) == NOTE_INSN_VAR_LOCATION; + if (var_loc_p && !DECL_P (NOTE_VAR_LOCATION_DECL (loc_note))) return; next_real = next_real_insn (loc_note); + /* If there are no instructions which would be affected by this note, don't do anything. */ - if (next_real == NULL_RTX && !NOTE_DURING_CALL_P (loc_note)) + if (var_loc_p + && next_real == NULL_RTX + && !NOTE_DURING_CALL_P (loc_note)) return; + if (next_real == NULL_RTX) + next_real = get_last_insn (); + /* If there were any real insns between note we processed last time and this note (or if it is the first note), clear last_{,postcall_}label so that they are not reused this time. */ @@ -21920,12 +22191,20 @@ dwarf2out_var_location (rtx loc_note) last_postcall_label = NULL; } - decl = NOTE_VAR_LOCATION_DECL (loc_note); - newloc = add_var_loc_to_decl (decl, loc_note, - NOTE_DURING_CALL_P (loc_note) - ? last_postcall_label : last_label); - if (newloc == NULL) - return; + if (var_loc_p) + { + decl = NOTE_VAR_LOCATION_DECL (loc_note); + newloc = add_var_loc_to_decl (decl, loc_note, + NOTE_DURING_CALL_P (loc_note) + ? last_postcall_label : last_label); + if (newloc == NULL) + return; + } + else + { + decl = NULL_TREE; + newloc = NULL; + } /* If there were no real insns between note we processed last time and this note, use the label we emitted last time. Otherwise @@ -21938,7 +22217,43 @@ dwarf2out_var_location (rtx loc_note) last_label = ggc_strdup (loclabel); } - if (!NOTE_DURING_CALL_P (loc_note)) + if (!var_loc_p) + { + struct call_arg_loc_node *ca_loc + = ggc_alloc_cleared_call_arg_loc_node (); + rtx prev = prev_real_insn (loc_note), x; + ca_loc->call_arg_loc_note = loc_note; + ca_loc->next = NULL; + ca_loc->label = last_label; + gcc_assert (prev + && (CALL_P (prev) + || (NONJUMP_INSN_P (prev) + && GET_CODE (PATTERN (prev)) == SEQUENCE + && CALL_P (XVECEXP (PATTERN (prev), 0, 0))))); + if (!CALL_P (prev)) + prev = XVECEXP (PATTERN (prev), 0, 0); + ca_loc->tail_call_p = SIBLING_CALL_P (prev); + x = PATTERN (prev); + if (GET_CODE (x) == PARALLEL) + x = XVECEXP (x, 0, 0); + if (GET_CODE (x) == SET) + x = SET_SRC (x); + if (GET_CODE (x) == CALL && MEM_P (XEXP (x, 0))) + { + x = XEXP (XEXP (x, 0), 0); + if (GET_CODE (x) == SYMBOL_REF + && SYMBOL_REF_DECL (x) + && TREE_CODE (SYMBOL_REF_DECL (x)) == FUNCTION_DECL) + ca_loc->symbol_ref = x; + } + ca_loc->block = insn_scope (prev); + if (call_arg_locations) + call_arg_loc_last->next = ca_loc; + else + call_arg_locations = ca_loc; + call_arg_loc_last = ca_loc; + } + else if (!NOTE_DURING_CALL_P (loc_note)) newloc->label = last_label; else { @@ -21974,6 +22289,8 @@ dwarf2out_begin_function (tree fun) } dwarf2out_note_section_used (); + call_site_count = 0; + tail_call_site_count = 0; } /* Output a label to mark the beginning of a source code line entry @@ -22804,9 +23121,16 @@ resolve_one_addr (rtx *addr, void *data ATTRIBUTE_UNUSED) } if (GET_CODE (rtl) == SYMBOL_REF - && SYMBOL_REF_DECL (rtl) - && !TREE_ASM_WRITTEN (SYMBOL_REF_DECL (rtl))) - return 1; + && SYMBOL_REF_DECL (rtl)) + { + if (TREE_CONSTANT_POOL_ADDRESS_P (rtl)) + { + if (!TREE_ASM_WRITTEN (DECL_INITIAL (SYMBOL_REF_DECL (rtl)))) + return 1; + } + else if (!TREE_ASM_WRITTEN (SYMBOL_REF_DECL (rtl))) + return 1; + } if (GET_CODE (rtl) == CONST && for_each_rtx (&XEXP (rtl, 0), resolve_one_addr, NULL)) @@ -22898,6 +23222,28 @@ resolve_addr (dw_die_ref die) remove_AT (die, a->dw_attr); ix--; } + if (die->die_tag == DW_TAG_GNU_call_site + && a->dw_attr == DW_AT_abstract_origin) + { + tree tdecl = SYMBOL_REF_DECL (a->dw_attr_val.v.val_addr); + dw_die_ref tdie = lookup_decl_die (tdecl); + if (tdie == NULL && DECL_EXTERNAL (tdecl)) + { + force_decl_die (tdecl); + tdie = lookup_decl_die (tdecl); + } + if (tdie) + { + a->dw_attr_val.val_class = dw_val_class_die_ref; + a->dw_attr_val.v.val_die_ref.die = tdie; + a->dw_attr_val.v.val_die_ref.external = 0; + } + else + { + remove_AT (die, a->dw_attr); + ix--; + } + } break; default: break; |