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
This commit is contained in:
parent
9ef13bd018
commit
2b1c543325
@ -1,3 +1,81 @@
|
||||
2011-03-16 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2011-03-16 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR target/45844
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
# Copyright (C) 1987, 1988, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
|
||||
# 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
# 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
# 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
|
||||
#This file is part of GCC.
|
||||
|
||||
@ -2933,7 +2933,7 @@ dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(LIBFUNCS_H) toplev.h $(DIAGNOSTIC_CORE_H) dwarf2out.h reload.h \
|
||||
$(GGC_H) $(EXCEPT_H) dwarf2asm.h $(TM_P_H) langhooks.h $(HASHTAB_H) \
|
||||
gt-dwarf2out.h $(TARGET_H) $(CGRAPH_H) $(MD5_H) $(INPUT_H) $(FUNCTION_H) \
|
||||
$(GIMPLE_H) $(TREE_PASS_H) $(TREE_FLOW_H) tree-pretty-print.h
|
||||
$(GIMPLE_H) $(TREE_PASS_H) $(TREE_FLOW_H) $(CFGLAYOUT_H) tree-pretty-print.h
|
||||
dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(FLAGS_H) $(RTL_H) $(TREE_H) output.h dwarf2asm.h $(TM_P_H) $(GGC_H) \
|
||||
gt-dwarf2asm.h $(DWARF2_H) $(SPLAY_TREE_H) $(TARGET_H)
|
||||
@ -3162,7 +3162,7 @@ var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) \
|
||||
$(REGS_H) $(EXPR_H) $(TIMEVAR_H) $(TREE_PASS_H) $(TREE_FLOW_H) \
|
||||
cselib.h $(TARGET_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) $(DIAGNOSTIC_H) pointer-set.h \
|
||||
$(RECOG_H) tree-pretty-print.h
|
||||
$(RECOG_H) $(TM_P_H) tree-pretty-print.h
|
||||
profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) $(FUNCTION_H) $(BASIC_BLOCK_H) \
|
||||
$(DIAGNOSTIC_CORE_H) $(COVERAGE_H) $(TREE_FLOW_H) value-prof.h cfghooks.h \
|
||||
|
48
gcc/calls.c
48
gcc/calls.c
@ -1,7 +1,7 @@
|
||||
/* Convert function calls to rtl insns, for GNU C compiler.
|
||||
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
Free Software Foundation, Inc.
|
||||
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -2784,9 +2784,7 @@ expand_call (tree exp, rtx target, int ignore)
|
||||
sibcall_failure = 1;
|
||||
}
|
||||
|
||||
if (((flags & ECF_CONST)
|
||||
|| ((flags & ECF_PURE) && ACCUMULATE_OUTGOING_ARGS))
|
||||
&& args[i].stack)
|
||||
if (args[i].stack)
|
||||
call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
|
||||
gen_rtx_USE (VOIDmode,
|
||||
args[i].stack),
|
||||
@ -3682,6 +3680,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
|
||||
|
||||
if (! (reg != 0 && partial == 0))
|
||||
{
|
||||
rtx use;
|
||||
|
||||
if (ACCUMULATE_OUTGOING_ARGS)
|
||||
{
|
||||
/* If this is being stored into a pre-allocated, fixed-size,
|
||||
@ -3752,28 +3752,22 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
|
||||
|
||||
NO_DEFER_POP;
|
||||
|
||||
if ((flags & ECF_CONST)
|
||||
|| ((flags & ECF_PURE) && ACCUMULATE_OUTGOING_ARGS))
|
||||
{
|
||||
rtx use;
|
||||
|
||||
/* Indicate argument access so that alias.c knows that these
|
||||
values are live. */
|
||||
if (argblock)
|
||||
use = plus_constant (argblock,
|
||||
argvec[argnum].locate.offset.constant);
|
||||
else
|
||||
/* When arguments are pushed, trying to tell alias.c where
|
||||
exactly this argument is won't work, because the
|
||||
auto-increment causes confusion. So we merely indicate
|
||||
that we access something with a known mode somewhere on
|
||||
the stack. */
|
||||
use = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
|
||||
gen_rtx_SCRATCH (Pmode));
|
||||
use = gen_rtx_MEM (argvec[argnum].mode, use);
|
||||
use = gen_rtx_USE (VOIDmode, use);
|
||||
call_fusage = gen_rtx_EXPR_LIST (VOIDmode, use, call_fusage);
|
||||
}
|
||||
/* Indicate argument access so that alias.c knows that these
|
||||
values are live. */
|
||||
if (argblock)
|
||||
use = plus_constant (argblock,
|
||||
argvec[argnum].locate.offset.constant);
|
||||
else
|
||||
/* When arguments are pushed, trying to tell alias.c where
|
||||
exactly this argument is won't work, because the
|
||||
auto-increment causes confusion. So we merely indicate
|
||||
that we access something with a known mode somewhere on
|
||||
the stack. */
|
||||
use = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
|
||||
gen_rtx_SCRATCH (Pmode));
|
||||
use = gen_rtx_MEM (argvec[argnum].mode, use);
|
||||
use = gen_rtx_USE (VOIDmode, use);
|
||||
call_fusage = gen_rtx_EXPR_LIST (VOIDmode, use, call_fusage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Basic block reordering routines for the GNU compiler.
|
||||
Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -54,7 +54,6 @@ static void change_scope (rtx, tree, tree);
|
||||
|
||||
void verify_insn_chain (void);
|
||||
static void fixup_fallthru_exit_predecessor (void);
|
||||
static tree insn_scope (const_rtx);
|
||||
|
||||
rtx
|
||||
unlink_insn_chain (rtx first, rtx last)
|
||||
@ -499,7 +498,7 @@ locator_scope (int loc)
|
||||
}
|
||||
|
||||
/* Return lexical scope block insn belongs to. */
|
||||
static tree
|
||||
tree
|
||||
insn_scope (const_rtx insn)
|
||||
{
|
||||
return locator_scope (INSN_LOCATOR (insn));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Basic block reordering routines for the GNU compiler.
|
||||
Copyright (C) 2000, 2003, 2004, 2007 Free Software Foundation, Inc.
|
||||
Copyright (C) 2000, 2003, 2004, 2007, 2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -27,6 +27,7 @@ extern GTY(()) rtx cfg_layout_function_header;
|
||||
|
||||
extern void cfg_layout_initialize (unsigned int);
|
||||
extern void cfg_layout_finalize (void);
|
||||
extern tree insn_scope (const_rtx);
|
||||
extern void reemit_insn_block_notes (void);
|
||||
extern bool can_copy_bbs_p (basic_block *, unsigned);
|
||||
extern void copy_bbs (basic_block *, unsigned, basic_block *,
|
||||
|
@ -1,3 +1,8 @@
|
||||
2011-03-16 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* cp-objcp-common.c (cp_function_decl_explicit_p): Don't crash if
|
||||
DECL_LANG_SPECIFIC is NULL.
|
||||
|
||||
2011-03-15 Jason Merrill <jason@redhat.com>
|
||||
|
||||
Core 1074
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Some code common to C++ and ObjC++ front ends.
|
||||
Copyright (C) 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 2004, 2007, 2008, 2009, 2010, 2011
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Ziemowit Laski <zlaski@apple.com>
|
||||
|
||||
This file is part of GCC.
|
||||
@ -160,6 +161,7 @@ cp_function_decl_explicit_p (tree decl)
|
||||
{
|
||||
return (decl
|
||||
&& FUNCTION_FIRST_USER_PARMTYPE (decl) != void_list_node
|
||||
&& DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
|
||||
&& DECL_NONCONVERTING_P (decl));
|
||||
}
|
||||
|
||||
|
374
gcc/dwarf2out.c
374
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 (!DECL_P (NOTE_VAR_LOCATION_DECL (loc_note)))
|
||||
if (!NOTE_P (loc_note))
|
||||
{
|
||||
if (CALL_P (loc_note))
|
||||
{
|
||||
call_site_count++;
|
||||
if (SIBLING_CALL_P (loc_note))
|
||||
tail_call_site_count++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* Convert RTL to assembler code and output it, for GNU compiler.
|
||||
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
|
||||
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||
2010, 2011
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -2005,6 +2006,7 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
|
||||
break;
|
||||
|
||||
case NOTE_INSN_VAR_LOCATION:
|
||||
case NOTE_INSN_CALL_ARG_LOCATION:
|
||||
if (!DECL_IGNORED_P (current_function_decl))
|
||||
debug_hooks->var_location (insn);
|
||||
break;
|
||||
@ -2671,6 +2673,8 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
|
||||
if (t)
|
||||
assemble_external (t);
|
||||
}
|
||||
if (!DECL_IGNORED_P (current_function_decl))
|
||||
debug_hooks->var_location (insn);
|
||||
}
|
||||
|
||||
/* Output assembler code from the template. */
|
||||
@ -4423,6 +4427,7 @@ rest_of_clean_state (void)
|
||||
if (final_output
|
||||
&& (!NOTE_P (insn) ||
|
||||
(NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION
|
||||
&& NOTE_KIND (insn) != NOTE_INSN_CALL_ARG_LOCATION
|
||||
&& NOTE_KIND (insn) != NOTE_INSN_BLOCK_BEG
|
||||
&& NOTE_KIND (insn) != NOTE_INSN_BLOCK_END
|
||||
&& NOTE_KIND (insn) != NOTE_INSN_CFA_RESTORE_STATE)))
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Process source files and output type information.
|
||||
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -1013,6 +1013,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
|
||||
break;
|
||||
|
||||
case NOTE_INSN_VAR_LOCATION:
|
||||
case NOTE_INSN_CALL_ARG_LOCATION:
|
||||
note_flds = create_field (note_flds, rtx_tp, "rt_rtx");
|
||||
break;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Insn note definitions.
|
||||
Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
|
||||
Copyright (C) 2004, 2005, 2007, 2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -61,6 +61,9 @@ INSN_NOTE (EH_REGION_END)
|
||||
/* The location of a variable. */
|
||||
INSN_NOTE (VAR_LOCATION)
|
||||
|
||||
/* The values passed to callee. */
|
||||
INSN_NOTE (CALL_ARG_LOCATION)
|
||||
|
||||
/* Record the struct for the following basic block. Uses
|
||||
NOTE_BASIC_BLOCK. FIXME: Redundant with the basic block pointer
|
||||
now included in every insn. */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Procedure integration for GCC.
|
||||
Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Michael Tiemann (tiemann@cygnus.com)
|
||||
|
||||
@ -112,7 +112,8 @@ set_block_origin_self (tree stmt)
|
||||
for (local_decl = BLOCK_VARS (stmt);
|
||||
local_decl != NULL_TREE;
|
||||
local_decl = DECL_CHAIN (local_decl))
|
||||
set_decl_origin_self (local_decl); /* Potential recursion. */
|
||||
if (! DECL_EXTERNAL (local_decl))
|
||||
set_decl_origin_self (local_decl); /* Potential recursion. */
|
||||
}
|
||||
|
||||
{
|
||||
@ -173,7 +174,8 @@ set_block_abstract_flags (tree stmt, int setting)
|
||||
for (local_decl = BLOCK_VARS (stmt);
|
||||
local_decl != NULL_TREE;
|
||||
local_decl = DECL_CHAIN (local_decl))
|
||||
set_decl_abstract_flags (local_decl, setting);
|
||||
if (! DECL_EXTERNAL (local_decl))
|
||||
set_decl_abstract_flags (local_decl, setting);
|
||||
|
||||
for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Print RTL for GCC.
|
||||
Copyright (C) 1987, 1988, 1992, 1997, 1998, 1999, 2000, 2002, 2003,
|
||||
2004, 2005, 2007, 2008, 2009, 2010
|
||||
2004, 2005, 2007, 2008, 2009, 2010, 2011
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -302,6 +302,7 @@ print_rtx (const_rtx in_rtx)
|
||||
}
|
||||
|
||||
case NOTE_INSN_VAR_LOCATION:
|
||||
case NOTE_INSN_CALL_ARG_LOCATION:
|
||||
#ifndef GENERATOR_FILE
|
||||
fputc (' ', outfile);
|
||||
print_rtx (NOTE_VAR_LOCATION (in_rtx));
|
||||
|
@ -2,7 +2,7 @@
|
||||
Register Transfer Expressions (rtx's) that make up the
|
||||
Register Transfer Language (rtl) used in the Back End of the GNU compiler.
|
||||
Copyright (C) 1987, 1988, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2004,
|
||||
2005, 2006, 2007, 2008, 2009, 2010
|
||||
2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -718,6 +718,10 @@ DEF_RTL_EXPR(VAR_LOCATION, "var_location", "tei", RTX_EXTRA)
|
||||
addressable. */
|
||||
DEF_RTL_EXPR(DEBUG_IMPLICIT_PTR, "debug_implicit_ptr", "t", RTX_OBJ)
|
||||
|
||||
/* Represents value that argument had on function entry. Should
|
||||
be only used in VAR_LOCATION location expression. */
|
||||
DEF_RTL_EXPR(ENTRY_VALUE, "entry_value", "e", RTX_OBJ)
|
||||
|
||||
/* All expressions from this point forward appear only in machine
|
||||
descriptions. */
|
||||
#ifdef GENERATOR_FILE
|
||||
|
@ -115,6 +115,7 @@
|
||||
#include "tree-pretty-print.h"
|
||||
#include "pointer-set.h"
|
||||
#include "recog.h"
|
||||
#include "tm_p.h"
|
||||
|
||||
/* var-tracking.c assumes that tree code with the same value as VALUE rtx code
|
||||
has no chance to appear in REG_EXPR/MEM_EXPRs and isn't a decl.
|
||||
@ -408,6 +409,7 @@ static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
|
||||
static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
|
||||
HOST_WIDE_INT *);
|
||||
static bool vt_stack_adjustments (void);
|
||||
static void note_register_arguments (rtx);
|
||||
static hashval_t variable_htab_hash (const void *);
|
||||
static int variable_htab_eq (const void *, const void *);
|
||||
static void variable_htab_free (void *);
|
||||
@ -659,11 +661,15 @@ vt_stack_adjustments (void)
|
||||
for (insn = BB_HEAD (dest);
|
||||
insn != NEXT_INSN (BB_END (dest));
|
||||
insn = NEXT_INSN (insn))
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
insn_stack_adjust_offset_pre_post (insn, &pre, &post);
|
||||
offset += pre + post;
|
||||
}
|
||||
{
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
insn_stack_adjust_offset_pre_post (insn, &pre, &post);
|
||||
offset += pre + post;
|
||||
}
|
||||
if (CALL_P (insn))
|
||||
note_register_arguments (insn);
|
||||
}
|
||||
|
||||
VTI (dest)->out.stack_adjust = offset;
|
||||
|
||||
@ -4971,6 +4977,9 @@ log_op_type (rtx x, basic_block bb, rtx insn,
|
||||
/* All preserved VALUEs. */
|
||||
static VEC (rtx, heap) *preserved_values;
|
||||
|
||||
/* Registers used in the current function for passing parameters. */
|
||||
static HARD_REG_SET argument_reg_set;
|
||||
|
||||
/* Ensure VAL is preserved and remember it in a vector for vt_emit_notes. */
|
||||
|
||||
static void
|
||||
@ -5324,10 +5333,22 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
|
||||
{
|
||||
mo.type = MO_CLOBBER;
|
||||
mo.u.loc = loc;
|
||||
if (GET_CODE (expr) == SET
|
||||
&& SET_DEST (expr) == loc
|
||||
&& REGNO (loc) < FIRST_PSEUDO_REGISTER
|
||||
&& TEST_HARD_REG_BIT (argument_reg_set, REGNO (loc))
|
||||
&& find_use_val (loc, mode, cui)
|
||||
&& GET_CODE (SET_SRC (expr)) != ASM_OPERANDS)
|
||||
{
|
||||
gcc_checking_assert (type == MO_VAL_SET);
|
||||
mo.u.loc = gen_rtx_SET (VOIDmode, loc, SET_SRC (expr));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
|
||||
if (GET_CODE (expr) == SET
|
||||
&& SET_DEST (expr) == loc
|
||||
&& GET_CODE (SET_SRC (expr)) != ASM_OPERANDS)
|
||||
src = var_lowpart (mode2, SET_SRC (expr));
|
||||
loc = var_lowpart (mode2, loc);
|
||||
|
||||
@ -5387,7 +5408,9 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
|
||||
if (GET_CODE (expr) == SET
|
||||
&& SET_DEST (expr) == loc
|
||||
&& GET_CODE (SET_SRC (expr)) != ASM_OPERANDS)
|
||||
src = var_lowpart (mode2, SET_SRC (expr));
|
||||
loc = var_lowpart (mode2, loc);
|
||||
|
||||
@ -5542,6 +5565,195 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
|
||||
VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &mo);
|
||||
}
|
||||
|
||||
/* Arguments to the call. */
|
||||
static rtx call_arguments;
|
||||
|
||||
/* Compute call_arguments. */
|
||||
|
||||
static void
|
||||
prepare_call_arguments (basic_block bb, rtx insn)
|
||||
{
|
||||
rtx link, x;
|
||||
rtx prev, cur, next;
|
||||
rtx call = PATTERN (insn);
|
||||
tree type = NULL_TREE, t;
|
||||
CUMULATIVE_ARGS args_so_far;
|
||||
|
||||
memset (&args_so_far, 0, sizeof (args_so_far));
|
||||
if (GET_CODE (call) == PARALLEL)
|
||||
call = XVECEXP (call, 0, 0);
|
||||
if (GET_CODE (call) == SET)
|
||||
call = SET_SRC (call);
|
||||
if (GET_CODE (call) == CALL
|
||||
&& MEM_P (XEXP (call, 0))
|
||||
&& GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
|
||||
{
|
||||
rtx symbol = XEXP (XEXP (call, 0), 0);
|
||||
if (SYMBOL_REF_DECL (symbol)
|
||||
&& TREE_CODE (SYMBOL_REF_DECL (symbol)) == FUNCTION_DECL
|
||||
&& TYPE_ARG_TYPES (TREE_TYPE (SYMBOL_REF_DECL (symbol))))
|
||||
{
|
||||
type = TREE_TYPE (SYMBOL_REF_DECL (symbol));
|
||||
for (t = TYPE_ARG_TYPES (type); t && t != void_list_node;
|
||||
t = TREE_CHAIN (t))
|
||||
if (TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (TREE_VALUE (t))))
|
||||
break;
|
||||
if (t == NULL || t == void_list_node)
|
||||
type = NULL;
|
||||
else
|
||||
INIT_CUMULATIVE_ARGS (args_so_far, type, NULL_RTX,
|
||||
SYMBOL_REF_DECL (symbol),
|
||||
list_length (TYPE_ARG_TYPES (type)));
|
||||
}
|
||||
}
|
||||
t = type ? TYPE_ARG_TYPES (type) : NULL_TREE;
|
||||
|
||||
for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
|
||||
if (GET_CODE (XEXP (link, 0)) == USE)
|
||||
{
|
||||
rtx item = NULL_RTX;
|
||||
x = XEXP (XEXP (link, 0), 0);
|
||||
if (REG_P (x))
|
||||
{
|
||||
cselib_val *val = cselib_lookup (x, GET_MODE (x), 0, VOIDmode);
|
||||
if (val && cselib_preserved_value_p (val))
|
||||
item = gen_rtx_CONCAT (GET_MODE (x), x, val->val_rtx);
|
||||
else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
|
||||
{
|
||||
enum machine_mode mode = GET_MODE (x);
|
||||
|
||||
while ((mode = GET_MODE_WIDER_MODE (mode)) != VOIDmode
|
||||
&& GET_MODE_BITSIZE (mode) <= BITS_PER_WORD)
|
||||
{
|
||||
rtx reg = simplify_subreg (mode, x, GET_MODE (x), 0);
|
||||
|
||||
if (reg == NULL_RTX || !REG_P (reg))
|
||||
continue;
|
||||
val = cselib_lookup (reg, mode, 0, VOIDmode);
|
||||
if (val && cselib_preserved_value_p (val))
|
||||
{
|
||||
item = gen_rtx_CONCAT (GET_MODE (x), x,
|
||||
lowpart_subreg (GET_MODE (x),
|
||||
val->val_rtx,
|
||||
mode));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (MEM_P (x))
|
||||
{
|
||||
rtx mem = x;
|
||||
cselib_val *val;
|
||||
|
||||
if (!frame_pointer_needed)
|
||||
{
|
||||
struct adjust_mem_data amd;
|
||||
amd.mem_mode = VOIDmode;
|
||||
amd.stack_adjust = -VTI (bb)->out.stack_adjust;
|
||||
amd.side_effects = NULL_RTX;
|
||||
amd.store = true;
|
||||
mem = simplify_replace_fn_rtx (mem, NULL_RTX, adjust_mems,
|
||||
&amd);
|
||||
gcc_assert (amd.side_effects == NULL_RTX);
|
||||
}
|
||||
val = cselib_lookup (mem, GET_MODE (mem), 0, VOIDmode);
|
||||
if (val && cselib_preserved_value_p (val))
|
||||
item = gen_rtx_CONCAT (GET_MODE (x), copy_rtx (x), val->val_rtx);
|
||||
}
|
||||
if (item)
|
||||
call_arguments = gen_rtx_EXPR_LIST (VOIDmode, item, call_arguments);
|
||||
if (t && t != void_list_node)
|
||||
{
|
||||
enum machine_mode mode = TYPE_MODE (TREE_VALUE (t));
|
||||
rtx reg = targetm.calls.function_arg (&args_so_far, mode,
|
||||
TREE_VALUE (t), true);
|
||||
if (TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (TREE_VALUE (t)))
|
||||
&& reg
|
||||
&& REG_P (reg)
|
||||
&& GET_MODE (reg) == mode
|
||||
&& GET_MODE_CLASS (mode) == MODE_INT
|
||||
&& REG_P (x)
|
||||
&& REGNO (x) == REGNO (reg)
|
||||
&& GET_MODE (x) == mode
|
||||
&& item)
|
||||
{
|
||||
enum machine_mode indmode
|
||||
= TYPE_MODE (TREE_TYPE (TREE_VALUE (t)));
|
||||
rtx mem = gen_rtx_MEM (indmode, x);
|
||||
cselib_val *val = cselib_lookup (mem, indmode, 0, VOIDmode);
|
||||
if (val && cselib_preserved_value_p (val))
|
||||
{
|
||||
item = gen_rtx_CONCAT (indmode, mem, val->val_rtx);
|
||||
call_arguments = gen_rtx_EXPR_LIST (VOIDmode, item,
|
||||
call_arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct elt_loc_list *l;
|
||||
tree initial;
|
||||
|
||||
/* Try harder, when passing address of a constant
|
||||
pool integer it can be easily read back. */
|
||||
val = CSELIB_VAL_PTR (XEXP (item, 1));
|
||||
for (l = val->locs; l; l = l->next)
|
||||
if (GET_CODE (l->loc) == SYMBOL_REF
|
||||
&& TREE_CONSTANT_POOL_ADDRESS_P (l->loc)
|
||||
&& SYMBOL_REF_DECL (l->loc)
|
||||
&& DECL_INITIAL (SYMBOL_REF_DECL (l->loc)))
|
||||
{
|
||||
initial = DECL_INITIAL (SYMBOL_REF_DECL (l->loc));
|
||||
if (host_integerp (initial, 0))
|
||||
{
|
||||
item = GEN_INT (tree_low_cst (initial, 0));
|
||||
item = gen_rtx_CONCAT (indmode, mem, item);
|
||||
call_arguments
|
||||
= gen_rtx_EXPR_LIST (VOIDmode, item,
|
||||
call_arguments);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
targetm.calls.function_arg_advance (&args_so_far, mode,
|
||||
TREE_VALUE (t), true);
|
||||
t = TREE_CHAIN (t);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reverse call_arguments chain. */
|
||||
prev = NULL_RTX;
|
||||
for (cur = call_arguments; cur; cur = next)
|
||||
{
|
||||
next = XEXP (cur, 1);
|
||||
XEXP (cur, 1) = prev;
|
||||
prev = cur;
|
||||
}
|
||||
call_arguments = prev;
|
||||
|
||||
x = PATTERN (insn);
|
||||
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)
|
||||
{
|
||||
cselib_val *val = cselib_lookup (x, GET_MODE (x), 0, VOIDmode);
|
||||
if (val && cselib_preserved_value_p (val))
|
||||
{
|
||||
x = gen_rtx_CONCAT (GET_MODE (x), pc_rtx, val->val_rtx);
|
||||
call_arguments
|
||||
= gen_rtx_EXPR_LIST (VOIDmode, x, call_arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Callback for cselib_record_sets_hook, that records as micro
|
||||
operations uses and stores in an insn after cselib_record_sets has
|
||||
analyzed the sets in an insn, but before it modifies the stored
|
||||
@ -5611,7 +5823,8 @@ add_with_sets (rtx insn, struct cselib_set *sets, int n_sets)
|
||||
|
||||
mo.type = MO_CALL;
|
||||
mo.insn = insn;
|
||||
mo.u.loc = NULL_RTX;
|
||||
mo.u.loc = call_arguments;
|
||||
call_arguments = NULL_RTX;
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
log_op_type (PATTERN (insn), bb, insn, mo.type, dump_file);
|
||||
@ -6927,6 +7140,10 @@ struct expand_loc_callback_data
|
||||
whose cur_loc has been already recomputed during current
|
||||
emit_notes_for_changes call. */
|
||||
bool cur_loc_changed;
|
||||
|
||||
/* True if cur_loc should be ignored and any possible location
|
||||
returned. */
|
||||
bool ignore_cur_loc;
|
||||
};
|
||||
|
||||
/* Callback for cselib_expand_value, that looks for expressions
|
||||
@ -6940,6 +7157,7 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
|
||||
= (struct expand_loc_callback_data *) data;
|
||||
bool dummy = elcd->dummy;
|
||||
bool cur_loc_changed = elcd->cur_loc_changed;
|
||||
rtx cur_loc;
|
||||
decl_or_value dv;
|
||||
variable var;
|
||||
location_chain loc;
|
||||
@ -7014,7 +7232,7 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
|
||||
VALUE_RECURSED_INTO (x) = true;
|
||||
result = NULL;
|
||||
|
||||
if (var->var_part[0].cur_loc)
|
||||
if (var->var_part[0].cur_loc && !elcd->ignore_cur_loc)
|
||||
{
|
||||
if (dummy)
|
||||
{
|
||||
@ -7029,12 +7247,16 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
|
||||
vt_expand_loc_callback, data);
|
||||
if (result)
|
||||
set_dv_changed (dv, false);
|
||||
cur_loc = var->var_part[0].cur_loc;
|
||||
}
|
||||
if (!result && dv_changed_p (dv))
|
||||
else
|
||||
cur_loc = NULL_RTX;
|
||||
if (!result && (dv_changed_p (dv) || elcd->ignore_cur_loc))
|
||||
{
|
||||
set_dv_changed (dv, false);
|
||||
if (!elcd->ignore_cur_loc)
|
||||
set_dv_changed (dv, false);
|
||||
for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
|
||||
if (loc->loc == var->var_part[0].cur_loc)
|
||||
if (loc->loc == cur_loc)
|
||||
continue;
|
||||
else if (dummy)
|
||||
{
|
||||
@ -7056,7 +7278,8 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
|
||||
}
|
||||
if (dummy && (result || var->var_part[0].cur_loc))
|
||||
var->cur_loc_changed = true;
|
||||
var->var_part[0].cur_loc = loc ? loc->loc : NULL_RTX;
|
||||
if (!elcd->ignore_cur_loc)
|
||||
var->var_part[0].cur_loc = loc ? loc->loc : NULL_RTX;
|
||||
}
|
||||
if (dummy)
|
||||
{
|
||||
@ -7077,7 +7300,7 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
|
||||
tables. */
|
||||
|
||||
static rtx
|
||||
vt_expand_loc (rtx loc, htab_t vars)
|
||||
vt_expand_loc (rtx loc, htab_t vars, bool ignore_cur_loc)
|
||||
{
|
||||
struct expand_loc_callback_data data;
|
||||
|
||||
@ -7087,6 +7310,7 @@ vt_expand_loc (rtx loc, htab_t vars)
|
||||
data.vars = vars;
|
||||
data.dummy = false;
|
||||
data.cur_loc_changed = false;
|
||||
data.ignore_cur_loc = ignore_cur_loc;
|
||||
loc = cselib_expand_value_rtx_cb (loc, scratch_regs, 8,
|
||||
vt_expand_loc_callback, &data);
|
||||
|
||||
@ -7108,6 +7332,7 @@ vt_expand_loc_dummy (rtx loc, htab_t vars, bool *pcur_loc_changed)
|
||||
data.vars = vars;
|
||||
data.dummy = true;
|
||||
data.cur_loc_changed = false;
|
||||
data.ignore_cur_loc = false;
|
||||
ret = cselib_dummy_expand_value_rtx_cb (loc, scratch_regs, 8,
|
||||
vt_expand_loc_callback, &data);
|
||||
*pcur_loc_changed = data.cur_loc_changed;
|
||||
@ -7178,7 +7403,7 @@ emit_note_insn_var_location (void **varp, void *data)
|
||||
complete = false;
|
||||
continue;
|
||||
}
|
||||
loc2 = vt_expand_loc (var->var_part[i].cur_loc, vars);
|
||||
loc2 = vt_expand_loc (var->var_part[i].cur_loc, vars, false);
|
||||
if (!loc2)
|
||||
{
|
||||
complete = false;
|
||||
@ -7208,7 +7433,7 @@ emit_note_insn_var_location (void **varp, void *data)
|
||||
&& mode == GET_MODE (var->var_part[j].cur_loc)
|
||||
&& (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts]))
|
||||
&& last_limit == var->var_part[j].offset
|
||||
&& (loc2 = vt_expand_loc (var->var_part[j].cur_loc, vars))
|
||||
&& (loc2 = vt_expand_loc (var->var_part[j].cur_loc, vars, false))
|
||||
&& GET_CODE (loc[n_var_parts]) == GET_CODE (loc2))
|
||||
{
|
||||
rtx new_loc = NULL;
|
||||
@ -7662,6 +7887,34 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
|
||||
case MO_CALL:
|
||||
dataflow_set_clear_at_call (set);
|
||||
emit_notes_for_changes (insn, EMIT_NOTE_AFTER_CALL_INSN, set->vars);
|
||||
{
|
||||
rtx arguments = mo->u.loc, *p = &arguments, note;
|
||||
while (*p)
|
||||
{
|
||||
XEXP (XEXP (*p, 0), 1)
|
||||
= vt_expand_loc (XEXP (XEXP (*p, 0), 1),
|
||||
shared_hash_htab (set->vars), true);
|
||||
/* If expansion is successful, keep it in the list. */
|
||||
if (XEXP (XEXP (*p, 0), 1))
|
||||
p = &XEXP (*p, 1);
|
||||
/* Otherwise, if the following item is data_value for it,
|
||||
drop it too too. */
|
||||
else if (XEXP (*p, 1)
|
||||
&& REG_P (XEXP (XEXP (*p, 0), 0))
|
||||
&& MEM_P (XEXP (XEXP (XEXP (*p, 1), 0), 0))
|
||||
&& REG_P (XEXP (XEXP (XEXP (XEXP (*p, 1), 0), 0),
|
||||
0))
|
||||
&& REGNO (XEXP (XEXP (*p, 0), 0))
|
||||
== REGNO (XEXP (XEXP (XEXP (XEXP (*p, 1), 0),
|
||||
0), 0)))
|
||||
*p = XEXP (XEXP (*p, 1), 1);
|
||||
/* Just drop this item. */
|
||||
else
|
||||
*p = XEXP (*p, 1);
|
||||
}
|
||||
note = emit_note_after (NOTE_INSN_CALL_ARG_LOCATION, insn);
|
||||
NOTE_VAR_LOCATION (note) = arguments;
|
||||
}
|
||||
break;
|
||||
|
||||
case MO_USE:
|
||||
@ -8095,8 +8348,8 @@ vt_add_function_parameter (tree parm)
|
||||
if (offset)
|
||||
return;
|
||||
|
||||
val = cselib_lookup (var_lowpart (mode, incoming), mode, true,
|
||||
VOIDmode);
|
||||
val = cselib_lookup_from_insn (var_lowpart (mode, incoming), mode, true,
|
||||
VOIDmode, get_insns ());
|
||||
|
||||
/* ??? Float-typed values in memory are not handled by
|
||||
cselib. */
|
||||
@ -8117,6 +8370,36 @@ vt_add_function_parameter (tree parm)
|
||||
incoming);
|
||||
set_variable_part (out, incoming, dv, offset,
|
||||
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
|
||||
if (dv_is_value_p (dv))
|
||||
{
|
||||
cselib_val *val = CSELIB_VAL_PTR (dv_as_value (dv));
|
||||
struct elt_loc_list *el;
|
||||
el = (struct elt_loc_list *)
|
||||
ggc_alloc_cleared_atomic (sizeof (*el));
|
||||
el->next = val->locs;
|
||||
el->loc = gen_rtx_ENTRY_VALUE (GET_MODE (incoming), incoming);
|
||||
el->setting_insn = get_insns ();
|
||||
val->locs = el;
|
||||
if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (parm))))
|
||||
{
|
||||
enum machine_mode indmode
|
||||
= TYPE_MODE (TREE_TYPE (TREE_TYPE (parm)));
|
||||
rtx mem = gen_rtx_MEM (indmode, incoming);
|
||||
val = cselib_lookup_from_insn (mem, indmode, true,
|
||||
VOIDmode, get_insns ());
|
||||
if (val)
|
||||
{
|
||||
preserve_value (val);
|
||||
el = (struct elt_loc_list *)
|
||||
ggc_alloc_cleared_atomic (sizeof (*el));
|
||||
el->next = val->locs;
|
||||
el->loc = gen_rtx_ENTRY_VALUE (indmode, mem);
|
||||
el->setting_insn = get_insns ();
|
||||
val->locs = el;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (MEM_P (incoming))
|
||||
{
|
||||
@ -8150,13 +8433,6 @@ vt_add_function_parameters (void)
|
||||
&& DECL_NAMELESS (vexpr))
|
||||
vt_add_function_parameter (vexpr);
|
||||
}
|
||||
|
||||
if (MAY_HAVE_DEBUG_INSNS)
|
||||
{
|
||||
cselib_preserve_only_values ();
|
||||
cselib_reset_table (cselib_get_next_uid ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Return true if INSN in the prologue initializes hard_frame_pointer_rtx. */
|
||||
@ -8184,6 +8460,23 @@ fp_setter (rtx insn)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Gather all registers used for passing arguments to other functions
|
||||
called from the current routine. */
|
||||
|
||||
static void
|
||||
note_register_arguments (rtx insn)
|
||||
{
|
||||
rtx link, x;
|
||||
|
||||
for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
|
||||
if (GET_CODE (XEXP (link, 0)) == USE)
|
||||
{
|
||||
x = XEXP (XEXP (link, 0), 0);
|
||||
if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
|
||||
SET_HARD_REG_BIT (argument_reg_set, REGNO (x));
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize cfa_base_rtx, create a preserved VALUE for it and
|
||||
ensure it isn't flushed during cselib_reset_table.
|
||||
Can be called only if frame_pointer_rtx resp. arg_pointer_rtx
|
||||
@ -8286,6 +8579,8 @@ vt_initialize (void)
|
||||
valvar_pool = NULL;
|
||||
}
|
||||
|
||||
CLEAR_HARD_REG_SET (argument_reg_set);
|
||||
|
||||
if (!frame_pointer_needed)
|
||||
{
|
||||
rtx reg, elim;
|
||||
@ -8332,9 +8627,18 @@ vt_initialize (void)
|
||||
prologue_bb = single_succ (ENTRY_BLOCK_PTR);
|
||||
}
|
||||
}
|
||||
if (frame_pointer_needed)
|
||||
{
|
||||
rtx insn;
|
||||
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
||||
if (CALL_P (insn))
|
||||
note_register_arguments (insn);
|
||||
}
|
||||
|
||||
hard_frame_pointer_adjustment = -1;
|
||||
|
||||
vt_add_function_parameters ();
|
||||
|
||||
FOR_EACH_BB (bb)
|
||||
{
|
||||
rtx insn;
|
||||
@ -8395,6 +8699,8 @@ vt_initialize (void)
|
||||
adjust_insn (bb, insn);
|
||||
if (MAY_HAVE_DEBUG_INSNS)
|
||||
{
|
||||
if (CALL_P (insn))
|
||||
prepare_call_arguments (bb, insn);
|
||||
cselib_process_insn (insn);
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
@ -8445,7 +8751,6 @@ vt_initialize (void)
|
||||
|
||||
hard_frame_pointer_adjustment = -1;
|
||||
VTI (ENTRY_BLOCK_PTR)->flooded = true;
|
||||
vt_add_function_parameters ();
|
||||
cfa_base_rtx = NULL_RTX;
|
||||
return true;
|
||||
}
|
||||
|
@ -1,3 +1,12 @@
|
||||
2011-03-16 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2011-02-28 Kai Tietz <kai.tietz@onevision.com>
|
||||
|
||||
* filenames.h (filename_ncmp): New prototype.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* Declarations and definitions of codes relating to the DWARF2 and
|
||||
DWARF3 symbolic debugging information formats.
|
||||
Copyright (C) 1992, 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002,
|
||||
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Written by Gary Funck (gary@intrepid.com) The Ada Joint Program
|
||||
@ -141,6 +141,12 @@ enum dwarf_tag
|
||||
are properly part of DWARF 5. */
|
||||
DW_TAG_GNU_template_parameter_pack = 0x4107,
|
||||
DW_TAG_GNU_formal_parameter_pack = 0x4108,
|
||||
/* The GNU call site extension, specified at
|
||||
http://www.dwarfstd.org/ShowIssue.php?issue=100909.2&type=open .
|
||||
The values of these two TAGS are in the DW_TAG_GNU_* space until the tags
|
||||
are properly part of DWARF 5. */
|
||||
DW_TAG_GNU_call_site = 0x4109,
|
||||
DW_TAG_GNU_call_site_parameter = 0x410a,
|
||||
/* Extensions for UPC. See: http://upc.gwu.edu/~upc. */
|
||||
DW_TAG_upc_shared_type = 0x8765,
|
||||
DW_TAG_upc_strict_type = 0x8766,
|
||||
@ -351,6 +357,16 @@ enum dwarf_attribute
|
||||
/* Template template argument name.
|
||||
See http://gcc.gnu.org/wiki/TemplateParmsDwarf . */
|
||||
DW_AT_GNU_template_name = 0x2110,
|
||||
/* The GNU call site extension.
|
||||
See http://www.dwarfstd.org/ShowIssue.php?issue=100909.2&type=open . */
|
||||
DW_AT_GNU_call_site_value = 0x2111,
|
||||
DW_AT_GNU_call_site_data_value = 0x2112,
|
||||
DW_AT_GNU_call_site_target = 0x2113,
|
||||
DW_AT_GNU_call_site_target_clobbered = 0x2114,
|
||||
DW_AT_GNU_tail_call = 0x2115,
|
||||
DW_AT_GNU_all_tail_call_sites = 0x2116,
|
||||
DW_AT_GNU_all_call_sites = 0x2117,
|
||||
DW_AT_GNU_all_source_call_sites = 0x2118,
|
||||
/* VMS extensions. */
|
||||
DW_AT_VMS_rtnbeg_pd_address = 0x2201,
|
||||
/* GNAT extensions. */
|
||||
@ -535,7 +551,12 @@ enum dwarf_location_atom
|
||||
/* The following is for marking variables that are uninitialized. */
|
||||
DW_OP_GNU_uninit = 0xf0,
|
||||
DW_OP_GNU_encoded_addr = 0xf1,
|
||||
/* The GNU implicit pointer extension.
|
||||
See http://www.dwarfstd.org/ShowIssue.php?issue=100831.1&type=open . */
|
||||
DW_OP_GNU_implicit_pointer = 0xf2,
|
||||
/* The GNU entry value extension.
|
||||
See http://www.dwarfstd.org/ShowIssue.php?issue=100909.1&type=open . */
|
||||
DW_OP_GNU_entry_value = 0xf3,
|
||||
/* HP extensions. */
|
||||
DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */
|
||||
DW_OP_HP_is_value = 0xe1,
|
||||
|
Loading…
Reference in New Issue
Block a user