mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
Add ability to track uninitialized variables, and mark uninitialized variables in the Dwarf debug info.
Add ability to track uninitialized variables, and mark uninitialized variables in the Dwarf debug info. Controlled by compile option -fvar-tracking-uninit From-SVN: r126630
This commit is contained in:
parent
f861f54dd7
commit
62760ffd15
@ -1,3 +1,102 @@
|
||||
2007-07-13 Caroline Tice <ctice@apple.com>
|
||||
|
||||
* toplev.c (process_options): Turn flag_var_tracking_uninit off when
|
||||
flag_var_tracking is explicitly turned off (i.e. when variable
|
||||
tracking is not feasible); otherwise, turn flag_var_tracking on when
|
||||
flag_var_tracking_uninit is on.
|
||||
* rtl.def (VAR_LOCATION): Add a new integer subfield to VAR_LOCATION
|
||||
note definitions, to allow recording of initialization status in the
|
||||
notes.
|
||||
* dwarf2out.c (dwarf_stack_op_name): Add case for DW_OP_GNU_uninit.
|
||||
(add_var_loc_to_decl): Add comparison of NOTE_VAR_LOCATION_STATUS to
|
||||
determine if two note locations are equal.
|
||||
(output_loc_list): Don't output list entries whose start & end labels
|
||||
are the same.
|
||||
(reg_loc_descriptor): Add parameter for initialization status; pass it
|
||||
to other loc descriptor functions.
|
||||
(one_reg_loc_descriptor): Add parameter for initialization status;
|
||||
check its value and add DW_OP_GNU_uninit to returned loc descr if
|
||||
appropriate.
|
||||
(multiple_reg_loc_descriptor): Add parameter for initialization
|
||||
status;
|
||||
pass init status argument to other loc descriptor functions; check
|
||||
value of intialization parameter and add DW_OP_GNU_uninit to returned
|
||||
loc descr if appropriate.
|
||||
(based_loc_descr): Add parameter for initialization status; add new
|
||||
variable for return value; check value of initialization parameter and
|
||||
add DW_OP_GNU_uninit to returned loc descr if appropriate.
|
||||
(concatn_mem_loc_descriptor): Add parameter for initialization status;
|
||||
pass init status argument to other loc descriptor functions; check
|
||||
value of intialization parameter and add DW_OP_GNU_uninit to returned
|
||||
loc descr if appropriate.
|
||||
(mem_loc_descriptor): Likewise.
|
||||
(concat_loc_descriptor): Likewise.
|
||||
(concatn_loc_descriptor): Likewise.
|
||||
(loc_descriptor): Add parameter for initialization status; pass it as
|
||||
argument to other loc descriptor function calls.
|
||||
(loc_descriptor_from_tree_1): Add appropriate initialization status
|
||||
to loc descriptor function calls.
|
||||
(add_location_or_const_value_attribute): Get initialization status
|
||||
from VAR_LOCATION note; add initialization status to loc descriptor
|
||||
function calls.
|
||||
* dwarf2.h (enum dwarf_location_atom): New op, DW_OP_GNU_uninit.
|
||||
* print-rtl.c (print_rtx): When printing a VAR_LOCATION note, if
|
||||
status is uninitialized, add "[uninint]" to output.
|
||||
* common.opt (fvar-tracking-uninit): New option, similar to
|
||||
fvar-tracking, to turn on tracking of uninitialized variables; creates
|
||||
a new global flag, flag_var_tracking_uninit.
|
||||
* rtl.h (NOTE_VAR_LOCATION_STATUS): New macro for accessing new field.
|
||||
(enum var_init_status): New type, for var initialization status field.
|
||||
* var-tracking.c (struct location_chain_def): Two new fields, init,
|
||||
for initialization status, and set_src for the assignment value expr.
|
||||
(unshare_variable): New parameter for initialization status;
|
||||
initialize new init and set_src fields.
|
||||
(var_reg_set): New parameters for initialization status and value;
|
||||
pass them to set_variable_part.
|
||||
(var_mem_set): Likewise.
|
||||
(get_init_value): New function.
|
||||
(var_reg_delete_and_set): New initialization status & value
|
||||
parameters; add call to get_init_value if status is unknown; pass new
|
||||
parameters to clobber_variable_part and var_reg_set.
|
||||
(var_mem_delete_and_set): Likewise.
|
||||
(var_reg_delete): Pass null set_src value to clobber_variable_part.
|
||||
(var_mem_delete): Likewise.
|
||||
(variable_union): Pass status to unshare_variable; initialize new init
|
||||
and set_src fields. If flag_var_tracking_uninit is not set, force
|
||||
status to initialized.
|
||||
(add_stores): Store insn, rather than NEXT_INSN(insn), so it can be
|
||||
used later to get the set_src value.
|
||||
(find_src_status): New function.
|
||||
(find_src_set_src): New function.
|
||||
(compute_bb_dataflow): Pass init status to calls to var_reg_set,
|
||||
var_mem_set, var_reg_delete_and_set and var_mem_delete_and_set; for
|
||||
MO_SET, get set_src value and pass it to var_reg_delete_and_set
|
||||
and var_mem_delete_and_set.
|
||||
(dump_variable): Print out "[uninit]" if appropriate.
|
||||
(set_variable_part): Add new initialization and set_src parameters;
|
||||
pass status to unshare_variable; set node->init and node- >set_src
|
||||
fields and modify slot in hash table appropriately; save the init and
|
||||
set_src values if appropriate and assign to the new node.
|
||||
(clobber_variable_part): New set_src parameter; if two nodes have
|
||||
same variable and same location but different set_src (assignment)
|
||||
values, clobber old node.
|
||||
(delete_variable_part): Pass init status to unshare_variable.
|
||||
(emit_note_insn_var_location): Add initialized var; assign var's init
|
||||
status to new 'initialized'; pass new init status field to calls to
|
||||
gen_rtx_VAR_LOCATION. If flag_var_tracking_uninit is not set, force
|
||||
status to initialized.
|
||||
(emit_notes_in_bb): Pass initialization status to calls to
|
||||
var_reg_set, var_mem_set, var_reg_delete_and_set and
|
||||
var_mem_delete_and_set; for MO_SET, get set_src value and pass it to
|
||||
var_reg_delete_and_set and var_mem_delete_and_set; call
|
||||
emit_notes_for_changes on NEXT_INSN(insn) rather than on insn, to
|
||||
make up for change in add_stores.
|
||||
(vt_add_function_parameters): Add status to calls to
|
||||
set_variable_part.
|
||||
* config/darwin.c (darwin_override_options): Turn on uninitialized
|
||||
tracking automatically, if var_tracking is on and the system is
|
||||
10.5 or higher.
|
||||
|
||||
2007-07-13 Sa Liu <saliu@de.ibm.com>
|
||||
|
||||
* config.gcc: Add options for arch and tune on SPU.
|
||||
|
@ -1130,6 +1130,10 @@ fvar-tracking
|
||||
Common Report Var(flag_var_tracking) VarExists Optimization
|
||||
Perform variable tracking
|
||||
|
||||
fvar-tracking-uninit
|
||||
Common Report Var(flag_var_tracking_uninit) Optimization
|
||||
Perform variable tracking and also tag variables that are uninitialized
|
||||
|
||||
ftree-vectorize
|
||||
Common Report Var(flag_tree_vectorize) Optimization
|
||||
Enable loop vectorization on trees
|
||||
|
@ -1728,6 +1728,9 @@ darwin_override_options (void)
|
||||
/* No -fnon-call-exceptions data in kexts. */
|
||||
flag_non_call_exceptions = 0;
|
||||
}
|
||||
if (flag_var_tracking
|
||||
&& strverscmp (darwin_macosx_version_min, "10.5") >= 0)
|
||||
flag_var_tracking_uninit = 1;
|
||||
}
|
||||
|
||||
#include "gt-darwin.h"
|
||||
|
@ -540,6 +540,8 @@ enum dwarf_location_atom
|
||||
DW_OP_bit_piece = 0x9d,
|
||||
/* GNU extensions. */
|
||||
DW_OP_GNU_push_tls_address = 0xe0,
|
||||
/* The following is for marking variables that are uninitialized. */
|
||||
DW_OP_GNU_uninit = 0xf0,
|
||||
/* HP extensions. */
|
||||
DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */
|
||||
DW_OP_HP_is_value = 0xe1,
|
||||
|
179
gcc/dwarf2out.c
179
gcc/dwarf2out.c
@ -3125,6 +3125,8 @@ dwarf_stack_op_name (unsigned int op)
|
||||
return "DW_OP_call_ref";
|
||||
case DW_OP_GNU_push_tls_address:
|
||||
return "DW_OP_GNU_push_tls_address";
|
||||
case DW_OP_GNU_uninit:
|
||||
return "DW_OP_GNU_uninit";
|
||||
default:
|
||||
return "OP_<unknown>";
|
||||
}
|
||||
@ -4193,15 +4195,20 @@ static dw_die_ref modified_type_die (tree, int, int, dw_die_ref);
|
||||
static int type_is_enum (tree);
|
||||
static unsigned int dbx_reg_number (rtx);
|
||||
static void add_loc_descr_op_piece (dw_loc_descr_ref *, int);
|
||||
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 reg_loc_descriptor (rtx, enum var_init_status);
|
||||
static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int,
|
||||
enum var_init_status);
|
||||
static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx,
|
||||
enum var_init_status);
|
||||
static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT);
|
||||
static dw_loc_descr_ref based_loc_descr (rtx, HOST_WIDE_INT);
|
||||
static dw_loc_descr_ref based_loc_descr (rtx, HOST_WIDE_INT,
|
||||
enum var_init_status);
|
||||
static int is_based_loc (rtx);
|
||||
static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode);
|
||||
static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx);
|
||||
static dw_loc_descr_ref loc_descriptor (rtx);
|
||||
static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode,
|
||||
enum var_init_status);
|
||||
static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx,
|
||||
enum var_init_status);
|
||||
static dw_loc_descr_ref loc_descriptor (rtx, enum var_init_status);
|
||||
static dw_loc_descr_ref loc_descriptor_from_tree_1 (tree, int);
|
||||
static dw_loc_descr_ref loc_descriptor_from_tree (tree);
|
||||
static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
|
||||
@ -5757,9 +5764,16 @@ add_var_loc_to_decl (tree decl, struct var_loc_node *loc)
|
||||
if (temp->last)
|
||||
{
|
||||
/* If the current location is the same as the end of the list,
|
||||
and either both or neither of the locations is uninitialized,
|
||||
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)))
|
||||
if ((!rtx_equal_p (NOTE_VAR_LOCATION_LOC (temp->last->var_loc_note),
|
||||
NOTE_VAR_LOCATION_LOC (loc->var_loc_note)))
|
||||
|| ((NOTE_VAR_LOCATION_STATUS (temp->last->var_loc_note)
|
||||
!= NOTE_VAR_LOCATION_STATUS (loc->var_loc_note))
|
||||
&& ((NOTE_VAR_LOCATION_STATUS (temp->last->var_loc_note)
|
||||
== VAR_INIT_STATUS_UNINITIALIZED)
|
||||
|| (NOTE_VAR_LOCATION_STATUS (loc->var_loc_note)
|
||||
== VAR_INIT_STATUS_UNINITIALIZED))))
|
||||
{
|
||||
/* Add LOC to the end of list and update LAST. */
|
||||
temp->last->next = loc;
|
||||
@ -7069,6 +7083,9 @@ output_loc_list (dw_loc_list_ref list_head)
|
||||
for (curr = list_head; curr != NULL; curr = curr->dw_loc_next)
|
||||
{
|
||||
unsigned long size;
|
||||
/* Don't output an entry that starts and ends at the same address. */
|
||||
if (strcmp (curr->begin, curr->end) == 0)
|
||||
continue;
|
||||
if (!have_multiple_function_sections)
|
||||
{
|
||||
dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section,
|
||||
@ -8747,7 +8764,7 @@ add_loc_descr_op_piece (dw_loc_descr_ref *list_head, int size)
|
||||
zero if there is none. */
|
||||
|
||||
static dw_loc_descr_ref
|
||||
reg_loc_descriptor (rtx rtl)
|
||||
reg_loc_descriptor (rtx rtl, enum var_init_status initialized)
|
||||
{
|
||||
rtx regs;
|
||||
|
||||
@ -8757,28 +8774,35 @@ reg_loc_descriptor (rtx rtl)
|
||||
regs = targetm.dwarf_register_span (rtl);
|
||||
|
||||
if (hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)] > 1 || regs)
|
||||
return multiple_reg_loc_descriptor (rtl, regs);
|
||||
return multiple_reg_loc_descriptor (rtl, regs, initialized);
|
||||
else
|
||||
return one_reg_loc_descriptor (dbx_reg_number (rtl));
|
||||
return one_reg_loc_descriptor (dbx_reg_number (rtl), initialized);
|
||||
}
|
||||
|
||||
/* Return a location descriptor that designates a machine register for
|
||||
a given hard register number. */
|
||||
|
||||
static dw_loc_descr_ref
|
||||
one_reg_loc_descriptor (unsigned int regno)
|
||||
one_reg_loc_descriptor (unsigned int regno, enum var_init_status initialized)
|
||||
{
|
||||
dw_loc_descr_ref reg_loc_descr;
|
||||
if (regno <= 31)
|
||||
return new_loc_descr (DW_OP_reg0 + regno, 0, 0);
|
||||
reg_loc_descr = new_loc_descr (DW_OP_reg0 + regno, 0, 0);
|
||||
else
|
||||
return new_loc_descr (DW_OP_regx, regno, 0);
|
||||
reg_loc_descr = new_loc_descr (DW_OP_regx, regno, 0);
|
||||
|
||||
if (initialized == VAR_INIT_STATUS_UNINITIALIZED)
|
||||
add_loc_descr (®_loc_descr, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
|
||||
|
||||
return reg_loc_descr;
|
||||
}
|
||||
|
||||
/* Given an RTL of a register, return a location descriptor that
|
||||
designates a value that spans more than one register. */
|
||||
|
||||
static dw_loc_descr_ref
|
||||
multiple_reg_loc_descriptor (rtx rtl, rtx regs)
|
||||
multiple_reg_loc_descriptor (rtx rtl, rtx regs,
|
||||
enum var_init_status initialized)
|
||||
{
|
||||
int nregs, size, i;
|
||||
unsigned reg;
|
||||
@ -8806,7 +8830,8 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
|
||||
{
|
||||
dw_loc_descr_ref t;
|
||||
|
||||
t = one_reg_loc_descriptor (DBX_REGISTER_NUMBER (reg));
|
||||
t = one_reg_loc_descriptor (DBX_REGISTER_NUMBER (reg),
|
||||
VAR_INIT_STATUS_INITIALIZED);
|
||||
add_loc_descr (&loc_result, t);
|
||||
add_loc_descr_op_piece (&loc_result, size);
|
||||
++reg;
|
||||
@ -8825,11 +8850,15 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
|
||||
{
|
||||
dw_loc_descr_ref t;
|
||||
|
||||
t = one_reg_loc_descriptor (REGNO (XVECEXP (regs, 0, i)));
|
||||
t = one_reg_loc_descriptor (REGNO (XVECEXP (regs, 0, i)),
|
||||
VAR_INIT_STATUS_INITIALIZED);
|
||||
add_loc_descr (&loc_result, t);
|
||||
size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0)));
|
||||
add_loc_descr_op_piece (&loc_result, size);
|
||||
}
|
||||
|
||||
if (loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
|
||||
add_loc_descr (&loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
|
||||
return loc_result;
|
||||
}
|
||||
|
||||
@ -8875,9 +8904,11 @@ 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 (rtx reg, HOST_WIDE_INT offset)
|
||||
based_loc_descr (rtx reg, HOST_WIDE_INT offset,
|
||||
enum var_init_status initialized)
|
||||
{
|
||||
unsigned int regno;
|
||||
dw_loc_descr_ref result;
|
||||
|
||||
/* We only use "frame base" when we're sure we're talking about the
|
||||
post-prologue local stack frame. We do this by *not* running
|
||||
@ -8904,9 +8935,14 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset)
|
||||
|
||||
regno = dbx_reg_number (reg);
|
||||
if (regno <= 31)
|
||||
return new_loc_descr (DW_OP_breg0 + regno, offset, 0);
|
||||
result = new_loc_descr (DW_OP_breg0 + regno, offset, 0);
|
||||
else
|
||||
return new_loc_descr (DW_OP_bregx, regno, offset);
|
||||
result = new_loc_descr (DW_OP_bregx, regno, offset);
|
||||
|
||||
if (initialized == VAR_INIT_STATUS_UNINITIALIZED)
|
||||
add_loc_descr (&result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return true if this RTL expression describes a base+offset calculation. */
|
||||
@ -8924,7 +8960,8 @@ is_based_loc (rtx rtl)
|
||||
used to form the address of a memory location. */
|
||||
|
||||
static dw_loc_descr_ref
|
||||
concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode)
|
||||
concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode,
|
||||
enum var_init_status initialized)
|
||||
{
|
||||
unsigned int i;
|
||||
dw_loc_descr_ref cc_loc_result = NULL;
|
||||
@ -8935,7 +8972,7 @@ concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode)
|
||||
dw_loc_descr_ref ref;
|
||||
rtx x = XVECEXP (concatn, 0, i);
|
||||
|
||||
ref = mem_loc_descriptor (x, mode);
|
||||
ref = mem_loc_descriptor (x, mode, VAR_INIT_STATUS_INITIALIZED);
|
||||
if (ref == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -8943,6 +8980,9 @@ concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode)
|
||||
add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x)));
|
||||
}
|
||||
|
||||
if (cc_loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
|
||||
add_loc_descr (&cc_loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
|
||||
|
||||
return cc_loc_result;
|
||||
}
|
||||
|
||||
@ -8965,7 +9005,8 @@ concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode)
|
||||
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,
|
||||
enum var_init_status initialized)
|
||||
{
|
||||
dw_loc_descr_ref mem_loc_result = NULL;
|
||||
enum dwarf_location_atom op;
|
||||
@ -9012,11 +9053,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 (rtl, 0);
|
||||
mem_loc_result = based_loc_descr (rtl, 0, VAR_INIT_STATUS_INITIALIZED);
|
||||
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),
|
||||
VAR_INIT_STATUS_INITIALIZED);
|
||||
if (mem_loc_result != 0)
|
||||
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
|
||||
break;
|
||||
@ -9083,10 +9125,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
|
||||
plus:
|
||||
if (is_based_loc (rtl))
|
||||
mem_loc_result = based_loc_descr (XEXP (rtl, 0),
|
||||
INTVAL (XEXP (rtl, 1)));
|
||||
INTVAL (XEXP (rtl, 1)),
|
||||
VAR_INIT_STATUS_INITIALIZED);
|
||||
else
|
||||
{
|
||||
mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
|
||||
mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode,
|
||||
VAR_INIT_STATUS_INITIALIZED);
|
||||
if (mem_loc_result == 0)
|
||||
break;
|
||||
|
||||
@ -9098,7 +9142,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,
|
||||
VAR_INIT_STATUS_INITIALIZED));
|
||||
add_loc_descr (&mem_loc_result,
|
||||
new_loc_descr (DW_OP_plus, 0, 0));
|
||||
}
|
||||
@ -9125,8 +9170,10 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
|
||||
|
||||
do_binop:
|
||||
{
|
||||
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,
|
||||
VAR_INIT_STATUS_INITIALIZED);
|
||||
dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode,
|
||||
VAR_INIT_STATUS_INITIALIZED);
|
||||
|
||||
if (op0 == 0 || op1 == 0)
|
||||
break;
|
||||
@ -9142,13 +9189,17 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
|
||||
break;
|
||||
|
||||
case CONCATN:
|
||||
mem_loc_result = concatn_mem_loc_descriptor (rtl, mode);
|
||||
mem_loc_result = concatn_mem_loc_descriptor (rtl, mode,
|
||||
VAR_INIT_STATUS_INITIALIZED);
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
if (mem_loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
|
||||
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
|
||||
|
||||
return mem_loc_result;
|
||||
}
|
||||
|
||||
@ -9156,11 +9207,11 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
|
||||
This is typically a complex variable. */
|
||||
|
||||
static dw_loc_descr_ref
|
||||
concat_loc_descriptor (rtx x0, rtx x1)
|
||||
concat_loc_descriptor (rtx x0, rtx x1, enum var_init_status initialized)
|
||||
{
|
||||
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, VAR_INIT_STATUS_INITIALIZED);
|
||||
dw_loc_descr_ref x1_ref = loc_descriptor (x1, VAR_INIT_STATUS_INITIALIZED);
|
||||
|
||||
if (x0_ref == 0 || x1_ref == 0)
|
||||
return 0;
|
||||
@ -9171,6 +9222,9 @@ concat_loc_descriptor (rtx x0, rtx x1)
|
||||
add_loc_descr (&cc_loc_result, x1_ref);
|
||||
add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x1)));
|
||||
|
||||
if (initialized == VAR_INIT_STATUS_UNINITIALIZED)
|
||||
add_loc_descr (&cc_loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
|
||||
|
||||
return cc_loc_result;
|
||||
}
|
||||
|
||||
@ -9178,7 +9232,7 @@ concat_loc_descriptor (rtx x0, rtx x1)
|
||||
locations. */
|
||||
|
||||
static dw_loc_descr_ref
|
||||
concatn_loc_descriptor (rtx concatn)
|
||||
concatn_loc_descriptor (rtx concatn, enum var_init_status initialized)
|
||||
{
|
||||
unsigned int i;
|
||||
dw_loc_descr_ref cc_loc_result = NULL;
|
||||
@ -9189,7 +9243,7 @@ concatn_loc_descriptor (rtx concatn)
|
||||
dw_loc_descr_ref ref;
|
||||
rtx x = XVECEXP (concatn, 0, i);
|
||||
|
||||
ref = loc_descriptor (x);
|
||||
ref = loc_descriptor (x, VAR_INIT_STATUS_INITIALIZED);
|
||||
if (ref == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -9197,6 +9251,9 @@ concatn_loc_descriptor (rtx concatn)
|
||||
add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x)));
|
||||
}
|
||||
|
||||
if (cc_loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
|
||||
add_loc_descr (&cc_loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
|
||||
|
||||
return cc_loc_result;
|
||||
}
|
||||
|
||||
@ -9209,7 +9266,7 @@ concatn_loc_descriptor (rtx concatn)
|
||||
If we don't know how to describe it, return 0. */
|
||||
|
||||
static dw_loc_descr_ref
|
||||
loc_descriptor (rtx rtl)
|
||||
loc_descriptor (rtx rtl, enum var_init_status initialized)
|
||||
{
|
||||
dw_loc_descr_ref loc_result = NULL;
|
||||
|
||||
@ -9226,26 +9283,28 @@ loc_descriptor (rtx rtl)
|
||||
/* ... fall through ... */
|
||||
|
||||
case REG:
|
||||
loc_result = reg_loc_descriptor (rtl);
|
||||
loc_result = reg_loc_descriptor (rtl, initialized);
|
||||
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),
|
||||
initialized);
|
||||
break;
|
||||
|
||||
case CONCAT:
|
||||
loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1));
|
||||
loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1),
|
||||
initialized);
|
||||
break;
|
||||
|
||||
case CONCATN:
|
||||
loc_result = concatn_loc_descriptor (rtl);
|
||||
loc_result = concatn_loc_descriptor (rtl, initialized);
|
||||
break;
|
||||
|
||||
case VAR_LOCATION:
|
||||
/* Single part. */
|
||||
if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
|
||||
{
|
||||
loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0));
|
||||
loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0), initialized);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -9260,14 +9319,16 @@ loc_descriptor (rtx rtl)
|
||||
int i;
|
||||
|
||||
/* Create the first one, so we have something to add to. */
|
||||
loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0));
|
||||
loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0),
|
||||
initialized);
|
||||
mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
|
||||
add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
|
||||
for (i = 1; i < num_elem; i++)
|
||||
{
|
||||
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),
|
||||
initialized);
|
||||
add_loc_descr (&loc_result, temp);
|
||||
mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
|
||||
add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
|
||||
@ -9399,7 +9460,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
|
||||
|
||||
/* Certain constructs can only be represented at top-level. */
|
||||
if (want_address == 2)
|
||||
return loc_descriptor (rtl);
|
||||
return loc_descriptor (rtl, VAR_INIT_STATUS_INITIALIZED);
|
||||
|
||||
mode = GET_MODE (rtl);
|
||||
if (MEM_P (rtl))
|
||||
@ -9407,7 +9468,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
|
||||
rtl = XEXP (rtl, 0);
|
||||
have_address = 1;
|
||||
}
|
||||
ret = mem_loc_descriptor (rtl, mode);
|
||||
ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -9488,7 +9549,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
|
||||
return 0;
|
||||
mode = GET_MODE (rtl);
|
||||
rtl = XEXP (rtl, 0);
|
||||
ret = mem_loc_descriptor (rtl, mode);
|
||||
ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
|
||||
have_address = 1;
|
||||
break;
|
||||
}
|
||||
@ -10575,6 +10636,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
|
||||
const char *endname, *secname;
|
||||
dw_loc_list_ref list;
|
||||
rtx varloc;
|
||||
enum var_init_status initialized;
|
||||
|
||||
/* Now that we know what section we are using for a base,
|
||||
actually construct the list of locations.
|
||||
@ -10591,7 +10653,12 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
|
||||
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
|
||||
secname = secname_for_decl (decl);
|
||||
|
||||
list = new_loc_list (loc_descriptor (varloc),
|
||||
if (NOTE_VAR_LOCATION_LOC (node->var_loc_note))
|
||||
initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
|
||||
else
|
||||
initialized = VAR_INIT_STATUS_INITIALIZED;
|
||||
|
||||
list = new_loc_list (loc_descriptor (varloc, initialized),
|
||||
node->label, node->next->label, secname, 1);
|
||||
node = node->next;
|
||||
|
||||
@ -10600,8 +10667,11 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
|
||||
{
|
||||
/* The variable has a location between NODE->LABEL and
|
||||
NODE->NEXT->LABEL. */
|
||||
enum var_init_status initialized =
|
||||
NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
|
||||
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
|
||||
add_loc_descr_to_loc_list (&list, loc_descriptor (varloc),
|
||||
add_loc_descr_to_loc_list (&list,
|
||||
loc_descriptor (varloc, initialized),
|
||||
node->label, node->next->label, secname);
|
||||
}
|
||||
|
||||
@ -10610,6 +10680,8 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
|
||||
if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
|
||||
{
|
||||
char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
|
||||
enum var_init_status initialized =
|
||||
NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
|
||||
|
||||
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
|
||||
if (!current_function_decl)
|
||||
@ -10620,7 +10692,8 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
|
||||
current_function_funcdef_no);
|
||||
endname = ggc_strdup (label_id);
|
||||
}
|
||||
add_loc_descr_to_loc_list (&list, loc_descriptor (varloc),
|
||||
add_loc_descr_to_loc_list (&list,
|
||||
loc_descriptor (varloc, initialized),
|
||||
node->label, endname, secname);
|
||||
}
|
||||
|
||||
@ -10644,8 +10717,10 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
|
||||
location list, try generating a location from that. */
|
||||
if (loc_list && loc_list->first)
|
||||
{
|
||||
enum var_init_status status;
|
||||
node = loc_list->first;
|
||||
descr = loc_descriptor (NOTE_VAR_LOCATION (node->var_loc_note));
|
||||
status = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
|
||||
descr = loc_descriptor (NOTE_VAR_LOCATION (node->var_loc_note), status);
|
||||
if (descr)
|
||||
{
|
||||
add_AT_location_description (die, attr, descr);
|
||||
|
@ -325,6 +325,9 @@ print_rtx (rtx in_rtx)
|
||||
print_mem_expr (outfile, NOTE_VAR_LOCATION_DECL (in_rtx));
|
||||
fprintf (outfile, " ");
|
||||
print_rtx (NOTE_VAR_LOCATION_LOC (in_rtx));
|
||||
if (NOTE_VAR_LOCATION_STATUS (in_rtx) ==
|
||||
VAR_INIT_STATUS_UNINITIALIZED)
|
||||
fprintf (outfile, " [uninit]");
|
||||
fprintf (outfile, ")");
|
||||
#endif
|
||||
break;
|
||||
|
@ -680,7 +680,9 @@ DEF_RTL_EXPR(SS_TRUNCATE, "ss_truncate", "e", RTX_UNARY)
|
||||
DEF_RTL_EXPR(US_TRUNCATE, "us_truncate", "e", RTX_UNARY)
|
||||
|
||||
/* Information about the variable and its location. */
|
||||
DEF_RTL_EXPR(VAR_LOCATION, "var_location", "te", RTX_EXTRA)
|
||||
/* Changed 'te' to 'tei'; the 'i' field is for recording
|
||||
initialization status of variables. */
|
||||
DEF_RTL_EXPR(VAR_LOCATION, "var_location", "tei", RTX_EXTRA)
|
||||
|
||||
/* All expressions from this point forward appear only in machine
|
||||
descriptions. */
|
||||
|
16
gcc/rtl.h
16
gcc/rtl.h
@ -847,6 +847,22 @@ extern const char * const reg_note_name[];
|
||||
#define NOTE_VAR_LOCATION_LOC(INSN) (XCEXP (XCEXP (INSN, 4, NOTE), \
|
||||
1, VAR_LOCATION))
|
||||
|
||||
/* Initialization status of the variable in the location. Status
|
||||
can be unknown, uninitialized or initialized. See enumeration
|
||||
type below. */
|
||||
#define NOTE_VAR_LOCATION_STATUS(INSN) (XCINT (XCEXP (INSN, 4, NOTE), \
|
||||
2, VAR_LOCATION))
|
||||
|
||||
/* Possible initialization status of a variable. When requested
|
||||
by the user, this information is tracked and recorded in the DWARF
|
||||
debug information, along with the variable's location. */
|
||||
enum var_init_status
|
||||
{
|
||||
VAR_INIT_STATUS_UNKNOWN,
|
||||
VAR_INIT_STATUS_UNINITIALIZED,
|
||||
VAR_INIT_STATUS_INITIALIZED
|
||||
};
|
||||
|
||||
/* Codes that appear in the NOTE_KIND field for kinds of notes
|
||||
that are not line numbers. These codes are all negative.
|
||||
|
||||
|
10
gcc/toplev.c
10
gcc/toplev.c
@ -1874,7 +1874,8 @@ process_options (void)
|
||||
if (debug_info_level < DINFO_LEVEL_NORMAL
|
||||
|| debug_hooks->var_location == do_nothing_debug_hooks.var_location)
|
||||
{
|
||||
if (flag_var_tracking == 1)
|
||||
if (flag_var_tracking == 1
|
||||
|| flag_var_tracking_uninit == 1)
|
||||
{
|
||||
if (debug_info_level < DINFO_LEVEL_NORMAL)
|
||||
warning (0, "variable tracking requested, but useless unless "
|
||||
@ -1884,6 +1885,7 @@ process_options (void)
|
||||
"by this debug format");
|
||||
}
|
||||
flag_var_tracking = 0;
|
||||
flag_var_tracking_uninit = 0;
|
||||
}
|
||||
|
||||
if (flag_rename_registers == AUTODETECT_VALUE)
|
||||
@ -1893,6 +1895,12 @@ process_options (void)
|
||||
if (flag_var_tracking == AUTODETECT_VALUE)
|
||||
flag_var_tracking = optimize >= 1;
|
||||
|
||||
/* If the user specifically requested variable tracking with tagging
|
||||
uninitialized variables, we need to turn on variable tracking.
|
||||
(We already determined above that variable tracking is feasible.) */
|
||||
if (flag_var_tracking_uninit)
|
||||
flag_var_tracking = 1;
|
||||
|
||||
/* If auxiliary info generation is desired, open the output file.
|
||||
This goes in the same directory as the source file--unlike
|
||||
all the other output files. */
|
||||
|
@ -219,6 +219,12 @@ typedef struct location_chain_def
|
||||
|
||||
/* The location (REG or MEM). */
|
||||
rtx loc;
|
||||
|
||||
/* The "value" stored in this location. */
|
||||
rtx set_src;
|
||||
|
||||
/* Initialized? */
|
||||
enum var_init_status init;
|
||||
} *location_chain;
|
||||
|
||||
/* Structure describing one part of variable. */
|
||||
@ -294,16 +300,19 @@ static void attrs_list_copy (attrs *, attrs);
|
||||
static void attrs_list_union (attrs *, attrs);
|
||||
|
||||
static void vars_clear (htab_t);
|
||||
static variable unshare_variable (dataflow_set *set, variable var);
|
||||
static variable unshare_variable (dataflow_set *set, variable var,
|
||||
enum var_init_status);
|
||||
static int vars_copy_1 (void **, void *);
|
||||
static void vars_copy (htab_t, htab_t);
|
||||
static tree var_debug_decl (tree);
|
||||
static void var_reg_set (dataflow_set *, rtx);
|
||||
static void var_reg_delete_and_set (dataflow_set *, rtx, bool);
|
||||
static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
|
||||
static void var_reg_delete_and_set (dataflow_set *, rtx, bool,
|
||||
enum var_init_status, rtx);
|
||||
static void var_reg_delete (dataflow_set *, rtx, bool);
|
||||
static void var_regno_delete (dataflow_set *, int);
|
||||
static void var_mem_set (dataflow_set *, rtx);
|
||||
static void var_mem_delete_and_set (dataflow_set *, rtx, bool);
|
||||
static void var_mem_set (dataflow_set *, rtx, enum var_init_status, rtx);
|
||||
static void var_mem_delete_and_set (dataflow_set *, rtx, bool,
|
||||
enum var_init_status, rtx);
|
||||
static void var_mem_delete (dataflow_set *, rtx, bool);
|
||||
|
||||
static void dataflow_set_init (dataflow_set *, int);
|
||||
@ -338,8 +347,10 @@ static void dump_dataflow_set (dataflow_set *);
|
||||
static void dump_dataflow_sets (void);
|
||||
|
||||
static void variable_was_changed (variable, htab_t);
|
||||
static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT);
|
||||
static void clobber_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT);
|
||||
static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT,
|
||||
enum var_init_status, rtx);
|
||||
static void clobber_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT,
|
||||
rtx);
|
||||
static void delete_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT);
|
||||
static int emit_note_insn_var_location (void **, void *);
|
||||
static void emit_notes_for_changes (rtx, enum emit_note_where);
|
||||
@ -727,7 +738,8 @@ vars_clear (htab_t vars)
|
||||
/* Return a copy of a variable VAR and insert it to dataflow set SET. */
|
||||
|
||||
static variable
|
||||
unshare_variable (dataflow_set *set, variable var)
|
||||
unshare_variable (dataflow_set *set, variable var,
|
||||
enum var_init_status initialized)
|
||||
{
|
||||
void **slot;
|
||||
variable new_var;
|
||||
@ -752,6 +764,14 @@ unshare_variable (dataflow_set *set, variable var)
|
||||
|
||||
new_lc = pool_alloc (loc_chain_pool);
|
||||
new_lc->next = NULL;
|
||||
if (node->init > initialized)
|
||||
new_lc->init = node->init;
|
||||
else
|
||||
new_lc->init = initialized;
|
||||
if (node->set_src && !(MEM_P (node->set_src)))
|
||||
new_lc->set_src = node->set_src;
|
||||
else
|
||||
new_lc->set_src = NULL;
|
||||
new_lc->loc = node->loc;
|
||||
|
||||
*nextp = new_lc;
|
||||
@ -819,7 +839,8 @@ var_debug_decl (tree decl)
|
||||
/* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
|
||||
|
||||
static void
|
||||
var_reg_set (dataflow_set *set, rtx loc)
|
||||
var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
|
||||
rtx set_src)
|
||||
{
|
||||
tree decl = REG_EXPR (loc);
|
||||
HOST_WIDE_INT offset = REG_OFFSET (loc);
|
||||
@ -832,7 +853,38 @@ var_reg_set (dataflow_set *set, rtx loc)
|
||||
break;
|
||||
if (!node)
|
||||
attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc);
|
||||
set_variable_part (set, loc, decl, offset);
|
||||
set_variable_part (set, loc, decl, offset, initialized, set_src);
|
||||
}
|
||||
|
||||
static int
|
||||
get_init_value (dataflow_set *set, rtx loc, tree decl)
|
||||
{
|
||||
void **slot;
|
||||
variable var;
|
||||
int i;
|
||||
int ret_val = VAR_INIT_STATUS_UNKNOWN;
|
||||
|
||||
if (! flag_var_tracking_uninit)
|
||||
return VAR_INIT_STATUS_INITIALIZED;
|
||||
|
||||
slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
|
||||
NO_INSERT);
|
||||
if (slot)
|
||||
{
|
||||
var = * (variable *) slot;
|
||||
for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++)
|
||||
{
|
||||
location_chain nextp;
|
||||
for (nextp = var->var_part[i].loc_chain; nextp; nextp = nextp->next)
|
||||
if (rtx_equal_p (nextp->loc, loc))
|
||||
{
|
||||
ret_val = nextp->init;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/* Delete current content of register LOC in dataflow set SET and set
|
||||
@ -843,7 +895,8 @@ var_reg_set (dataflow_set *set, rtx loc)
|
||||
part. */
|
||||
|
||||
static void
|
||||
var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify)
|
||||
var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
|
||||
enum var_init_status initialized, rtx set_src)
|
||||
{
|
||||
tree decl = REG_EXPR (loc);
|
||||
HOST_WIDE_INT offset = REG_OFFSET (loc);
|
||||
@ -852,6 +905,9 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify)
|
||||
|
||||
decl = var_debug_decl (decl);
|
||||
|
||||
if (initialized == VAR_INIT_STATUS_UNKNOWN)
|
||||
initialized = get_init_value (set, loc, decl);
|
||||
|
||||
nextp = &set->regs[REGNO (loc)];
|
||||
for (node = *nextp; node; node = next)
|
||||
{
|
||||
@ -869,8 +925,8 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify)
|
||||
}
|
||||
}
|
||||
if (modify)
|
||||
clobber_variable_part (set, loc, decl, offset);
|
||||
var_reg_set (set, loc);
|
||||
clobber_variable_part (set, loc, decl, offset, set_src);
|
||||
var_reg_set (set, loc, initialized, set_src);
|
||||
}
|
||||
|
||||
/* Delete current content of register LOC in dataflow set SET. If
|
||||
@ -890,7 +946,7 @@ var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
|
||||
|
||||
decl = var_debug_decl (decl);
|
||||
|
||||
clobber_variable_part (set, NULL, decl, offset);
|
||||
clobber_variable_part (set, NULL, decl, offset, NULL);
|
||||
}
|
||||
|
||||
for (node = *reg; node; node = next)
|
||||
@ -924,14 +980,15 @@ var_regno_delete (dataflow_set *set, int regno)
|
||||
Adjust the address first if it is stack pointer based. */
|
||||
|
||||
static void
|
||||
var_mem_set (dataflow_set *set, rtx loc)
|
||||
var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
|
||||
rtx set_src)
|
||||
{
|
||||
tree decl = MEM_EXPR (loc);
|
||||
HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
|
||||
|
||||
decl = var_debug_decl (decl);
|
||||
|
||||
set_variable_part (set, loc, decl, offset);
|
||||
set_variable_part (set, loc, decl, offset, initialized, set_src);
|
||||
}
|
||||
|
||||
/* Delete and set the location part of variable MEM_EXPR (LOC) in
|
||||
@ -942,16 +999,20 @@ var_mem_set (dataflow_set *set, rtx loc)
|
||||
Adjust the address first if it is stack pointer based. */
|
||||
|
||||
static void
|
||||
var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify)
|
||||
var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify,
|
||||
enum var_init_status initialized, rtx set_src)
|
||||
{
|
||||
tree decl = MEM_EXPR (loc);
|
||||
HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
|
||||
|
||||
decl = var_debug_decl (decl);
|
||||
|
||||
if (initialized == VAR_INIT_STATUS_UNKNOWN)
|
||||
initialized = get_init_value (set, loc, decl);
|
||||
|
||||
if (modify)
|
||||
clobber_variable_part (set, NULL, decl, offset);
|
||||
var_mem_set (set, loc);
|
||||
clobber_variable_part (set, NULL, decl, offset, set_src);
|
||||
var_mem_set (set, loc, initialized, set_src);
|
||||
}
|
||||
|
||||
/* Delete the location part LOC from dataflow set SET. If CLOBBER is
|
||||
@ -966,7 +1027,7 @@ var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
|
||||
|
||||
decl = var_debug_decl (decl);
|
||||
if (clobber)
|
||||
clobber_variable_part (set, NULL, decl, offset);
|
||||
clobber_variable_part (set, NULL, decl, offset, NULL);
|
||||
delete_variable_part (set, loc, decl, offset);
|
||||
}
|
||||
|
||||
@ -1078,7 +1139,14 @@ variable_union (void **slot, void *data)
|
||||
}
|
||||
}
|
||||
if (k < src->n_var_parts)
|
||||
unshare_variable (set, src);
|
||||
{
|
||||
enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
|
||||
|
||||
if (! flag_var_tracking_uninit)
|
||||
status = VAR_INIT_STATUS_INITIALIZED;
|
||||
|
||||
unshare_variable (set, src, status);
|
||||
}
|
||||
else
|
||||
*dstp = src;
|
||||
|
||||
@ -1112,7 +1180,13 @@ variable_union (void **slot, void *data)
|
||||
gcc_assert (k <= MAX_VAR_PARTS);
|
||||
|
||||
if (dst->refcount > 1 && dst->n_var_parts != k)
|
||||
dst = unshare_variable (set, dst);
|
||||
{
|
||||
enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
|
||||
|
||||
if (! flag_var_tracking_uninit)
|
||||
status = VAR_INIT_STATUS_INITIALIZED;
|
||||
dst = unshare_variable (set, dst, status);
|
||||
}
|
||||
|
||||
i = src->n_var_parts - 1;
|
||||
j = dst->n_var_parts - 1;
|
||||
@ -1145,10 +1219,12 @@ variable_union (void **slot, void *data)
|
||||
&& REG_P (node->loc)
|
||||
&& REGNO (node2->loc) == REGNO (node->loc))
|
||||
|| rtx_equal_p (node2->loc, node->loc)))
|
||||
if (node2->init < node->init)
|
||||
node2->init = node->init;
|
||||
break;
|
||||
}
|
||||
if (node || node2)
|
||||
dst = unshare_variable (set, dst);
|
||||
dst = unshare_variable (set, dst, VAR_INIT_STATUS_UNKNOWN);
|
||||
}
|
||||
|
||||
src_l = 0;
|
||||
@ -1194,6 +1270,11 @@ variable_union (void **slot, void *data)
|
||||
/* Copy the location from SRC. */
|
||||
new_node = pool_alloc (loc_chain_pool);
|
||||
new_node->loc = node->loc;
|
||||
new_node->init = node->init;
|
||||
if (!node->set_src || MEM_P (node->set_src))
|
||||
new_node->set_src = NULL;
|
||||
else
|
||||
new_node->set_src = node->set_src;
|
||||
vui[n].lc = new_node;
|
||||
vui[n].pos_src = ii;
|
||||
vui[n].pos_dst = src_l + dst_l;
|
||||
@ -1240,6 +1321,11 @@ variable_union (void **slot, void *data)
|
||||
|
||||
new_lc = pool_alloc (loc_chain_pool);
|
||||
new_lc->next = NULL;
|
||||
new_lc->init = node->init;
|
||||
if (!node->set_src || MEM_P (node->set_src))
|
||||
new_lc->set_src = NULL;
|
||||
else
|
||||
new_lc->set_src = node->set_src;
|
||||
new_lc->loc = node->loc;
|
||||
|
||||
*nextp = new_lc;
|
||||
@ -1258,6 +1344,18 @@ variable_union (void **slot, void *data)
|
||||
dst->var_part[k].cur_loc = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
|
||||
{
|
||||
location_chain node, node2;
|
||||
for (node = src->var_part[i].loc_chain; node; node = node->next)
|
||||
for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next)
|
||||
if (rtx_equal_p (node->loc, node2->loc))
|
||||
{
|
||||
if (node->init > node2->init)
|
||||
node2->init = node->init;
|
||||
}
|
||||
}
|
||||
|
||||
/* Continue traversing the hash table. */
|
||||
return 1;
|
||||
}
|
||||
@ -1679,7 +1777,7 @@ add_stores (rtx loc, rtx expr, void *insn)
|
||||
else
|
||||
mo->type = MO_SET;
|
||||
mo->u.loc = loc;
|
||||
mo->insn = NEXT_INSN ((rtx) insn);
|
||||
mo->insn = (rtx) insn;
|
||||
}
|
||||
else if (MEM_P (loc)
|
||||
&& MEM_EXPR (loc)
|
||||
@ -1700,10 +1798,99 @@ add_stores (rtx loc, rtx expr, void *insn)
|
||||
else
|
||||
mo->type = MO_SET;
|
||||
mo->u.loc = loc;
|
||||
mo->insn = NEXT_INSN ((rtx) insn);
|
||||
mo->insn = (rtx) insn;
|
||||
}
|
||||
}
|
||||
|
||||
static enum var_init_status
|
||||
find_src_status (dataflow_set *in, rtx loc, rtx insn)
|
||||
{
|
||||
rtx src = NULL_RTX;
|
||||
tree decl = NULL_TREE;
|
||||
enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
|
||||
|
||||
if (! flag_var_tracking_uninit)
|
||||
status = VAR_INIT_STATUS_INITIALIZED;
|
||||
|
||||
if (GET_CODE (PATTERN (insn)) == SET)
|
||||
src = SET_SRC (PATTERN (insn));
|
||||
else if (GET_CODE (PATTERN (insn)) == PARALLEL
|
||||
|| GET_CODE (PATTERN (insn)) == SEQUENCE)
|
||||
{
|
||||
int i;
|
||||
for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
|
||||
if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET
|
||||
&& SET_DEST (XVECEXP (PATTERN (insn), 0, i)) == loc)
|
||||
src = SET_SRC (XVECEXP (PATTERN (insn), 0, i));
|
||||
}
|
||||
|
||||
if (REG_P (src))
|
||||
decl = var_debug_decl (REG_EXPR (src));
|
||||
else if (MEM_P (src))
|
||||
decl = var_debug_decl (MEM_EXPR (src));
|
||||
|
||||
if (src && decl)
|
||||
status = get_init_value (in, src, decl);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* LOC is the destination the variable is being copied to. INSN
|
||||
contains the copy instruction. SET is the dataflow set containing
|
||||
the variable in LOC. */
|
||||
|
||||
static rtx
|
||||
find_src_set_src (dataflow_set *set, rtx loc, rtx insn)
|
||||
{
|
||||
tree decl = NULL_TREE; /* The variable being copied around. */
|
||||
rtx src = NULL_RTX; /* The location "decl" is being copied from. */
|
||||
rtx set_src = NULL_RTX; /* The value for "decl" stored in "src". */
|
||||
void **slot;
|
||||
variable var;
|
||||
location_chain nextp;
|
||||
int i;
|
||||
bool found;
|
||||
|
||||
if (GET_CODE (PATTERN (insn)) == SET)
|
||||
src = SET_SRC (PATTERN (insn));
|
||||
else if (GET_CODE (PATTERN (insn)) == PARALLEL
|
||||
|| GET_CODE (PATTERN (insn)) == SEQUENCE)
|
||||
{
|
||||
for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
|
||||
if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET
|
||||
&& SET_DEST (XVECEXP (PATTERN (insn), 0, i)) == loc)
|
||||
src = SET_SRC (XVECEXP (PATTERN (insn), 0, i));
|
||||
}
|
||||
|
||||
if (REG_P (src))
|
||||
decl = var_debug_decl (REG_EXPR (src));
|
||||
else if (MEM_P (src))
|
||||
decl = var_debug_decl (MEM_EXPR (src));
|
||||
|
||||
if (src && decl)
|
||||
{
|
||||
slot = htab_find_slot_with_hash (set->vars, decl,
|
||||
VARIABLE_HASH_VAL (decl), NO_INSERT);
|
||||
|
||||
if (slot)
|
||||
{
|
||||
var = *(variable *) slot;
|
||||
found = false;
|
||||
for (i = 0; i < var->n_var_parts && !found; i++)
|
||||
for (nextp = var->var_part[i].loc_chain; nextp && !found;
|
||||
nextp = nextp->next)
|
||||
if (rtx_equal_p (nextp->loc, src))
|
||||
{
|
||||
set_src = nextp->set_src;
|
||||
found = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return set_src;
|
||||
}
|
||||
|
||||
/* Compute the changes of variable locations in the basic block BB. */
|
||||
|
||||
static bool
|
||||
@ -1733,33 +1920,65 @@ compute_bb_dataflow (basic_block bb)
|
||||
case MO_USE:
|
||||
{
|
||||
rtx loc = VTI (bb)->mos[i].u.loc;
|
||||
enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
|
||||
|
||||
if (! flag_var_tracking_uninit)
|
||||
status = VAR_INIT_STATUS_INITIALIZED;
|
||||
|
||||
if (GET_CODE (loc) == REG)
|
||||
var_reg_set (out, loc);
|
||||
var_reg_set (out, loc, status, NULL);
|
||||
else if (GET_CODE (loc) == MEM)
|
||||
var_mem_set (out, loc);
|
||||
var_mem_set (out, loc, status, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case MO_SET:
|
||||
{
|
||||
rtx loc = VTI (bb)->mos[i].u.loc;
|
||||
rtx set_src = NULL;
|
||||
rtx insn = VTI (bb)->mos[i].insn;
|
||||
|
||||
if (GET_CODE (PATTERN (insn)) == SET)
|
||||
set_src = SET_SRC (PATTERN (insn));
|
||||
else if (GET_CODE (PATTERN (insn)) == PARALLEL
|
||||
|| GET_CODE (PATTERN (insn)) == SEQUENCE)
|
||||
{
|
||||
int j;
|
||||
for (j = XVECLEN (PATTERN (insn), 0) - 1; j >= 0; j--)
|
||||
if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == SET
|
||||
&& SET_DEST (XVECEXP (PATTERN (insn), 0, j)) == loc)
|
||||
set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, j));
|
||||
}
|
||||
|
||||
if (REG_P (loc))
|
||||
var_reg_delete_and_set (out, loc, true);
|
||||
var_reg_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
|
||||
set_src);
|
||||
else if (MEM_P (loc))
|
||||
var_mem_delete_and_set (out, loc, true);
|
||||
var_mem_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
|
||||
set_src);
|
||||
}
|
||||
break;
|
||||
|
||||
case MO_COPY:
|
||||
{
|
||||
rtx loc = VTI (bb)->mos[i].u.loc;
|
||||
enum var_init_status src_status;
|
||||
rtx set_src;
|
||||
|
||||
if (! flag_var_tracking_uninit)
|
||||
src_status = VAR_INIT_STATUS_INITIALIZED;
|
||||
else
|
||||
src_status = find_src_status (in, loc, VTI (bb)->mos[i].insn);
|
||||
|
||||
if (src_status == VAR_INIT_STATUS_UNKNOWN)
|
||||
src_status = find_src_status (out, loc, VTI (bb)->mos[i].insn);
|
||||
|
||||
set_src = find_src_set_src (in, loc, VTI (bb)->mos[i].insn);
|
||||
|
||||
if (REG_P (loc))
|
||||
var_reg_delete_and_set (out, loc, false);
|
||||
var_reg_delete_and_set (out, loc, false, src_status, set_src);
|
||||
else if (MEM_P (loc))
|
||||
var_mem_delete_and_set (out, loc, false);
|
||||
var_mem_delete_and_set (out, loc, false, src_status, set_src);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1932,6 +2151,8 @@ dump_variable (void **slot, void *data ATTRIBUTE_UNUSED)
|
||||
for (node = var->var_part[i].loc_chain; node; node = node->next)
|
||||
{
|
||||
fprintf (dump_file, " ");
|
||||
if (node->init == VAR_INIT_STATUS_UNINITIALIZED)
|
||||
fprintf (dump_file, "[uninit]");
|
||||
print_rtl_single (dump_file, node->loc);
|
||||
}
|
||||
}
|
||||
@ -2077,7 +2298,8 @@ find_variable_location_part (variable var, HOST_WIDE_INT offset,
|
||||
part's location by LOC. */
|
||||
|
||||
static void
|
||||
set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
|
||||
set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset,
|
||||
enum var_init_status initialized, rtx set_src)
|
||||
{
|
||||
int pos;
|
||||
location_chain node, next;
|
||||
@ -2119,13 +2341,19 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
|
||||
{
|
||||
/* LOC is in the beginning of the chain so we have nothing
|
||||
to do. */
|
||||
if (node->init < initialized)
|
||||
node->init = initialized;
|
||||
if (set_src != NULL)
|
||||
node->set_src = set_src;
|
||||
|
||||
*slot = var;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have to make a copy of a shared variable. */
|
||||
if (var->refcount > 1)
|
||||
var = unshare_variable (set, var);
|
||||
var = unshare_variable (set, var, initialized);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2134,7 +2362,7 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
|
||||
|
||||
/* We have to make a copy of the shared variable. */
|
||||
if (var->refcount > 1)
|
||||
var = unshare_variable (set, var);
|
||||
var = unshare_variable (set, var, initialized);
|
||||
|
||||
/* We track only variables whose size is <= MAX_VAR_PARTS bytes
|
||||
thus there are at most MAX_VAR_PARTS different offsets. */
|
||||
@ -2161,6 +2389,12 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
|
||||
&& REGNO (node->loc) == REGNO (loc))
|
||||
|| rtx_equal_p (node->loc, loc))
|
||||
{
|
||||
/* Save these values, to assign to the new node, before
|
||||
deleting this one. */
|
||||
if (node->init > initialized)
|
||||
initialized = node->init;
|
||||
if (node->set_src != NULL && set_src == NULL)
|
||||
set_src = node->set_src;
|
||||
pool_free (loc_chain_pool, node);
|
||||
*nextp = next;
|
||||
break;
|
||||
@ -2172,6 +2406,8 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
|
||||
/* Add the location to the beginning. */
|
||||
node = pool_alloc (loc_chain_pool);
|
||||
node->loc = loc;
|
||||
node->init = initialized;
|
||||
node->set_src = set_src;
|
||||
node->next = var->var_part[pos].loc_chain;
|
||||
var->var_part[pos].loc_chain = node;
|
||||
|
||||
@ -2190,7 +2426,7 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
|
||||
|
||||
static void
|
||||
clobber_variable_part (dataflow_set *set, rtx loc, tree decl,
|
||||
HOST_WIDE_INT offset)
|
||||
HOST_WIDE_INT offset, rtx set_src)
|
||||
{
|
||||
void **slot;
|
||||
|
||||
@ -2213,7 +2449,11 @@ clobber_variable_part (dataflow_set *set, rtx loc, tree decl,
|
||||
for (node = next; node; node = next)
|
||||
{
|
||||
next = node->next;
|
||||
if (node->loc != loc)
|
||||
if (node->loc != loc
|
||||
&& (!flag_var_tracking_uninit
|
||||
|| !set_src
|
||||
|| MEM_P (set_src)
|
||||
|| !rtx_equal_p (set_src, node->set_src)))
|
||||
{
|
||||
if (REG_P (node->loc))
|
||||
{
|
||||
@ -2278,7 +2518,10 @@ delete_variable_part (dataflow_set *set, rtx loc, tree decl,
|
||||
&& REGNO (node->loc) == REGNO (loc))
|
||||
|| rtx_equal_p (node->loc, loc))
|
||||
{
|
||||
var = unshare_variable (set, var);
|
||||
enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
|
||||
if (! flag_var_tracking_uninit)
|
||||
status = VAR_INIT_STATUS_INITIALIZED;
|
||||
var = unshare_variable (set, var, status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2345,6 +2588,7 @@ emit_note_insn_var_location (void **varp, void *data)
|
||||
rtx note;
|
||||
int i, j, n_var_parts;
|
||||
bool complete;
|
||||
enum var_init_status initialized = VAR_INIT_STATUS_UNINITIALIZED;
|
||||
HOST_WIDE_INT last_limit;
|
||||
tree type_size_unit;
|
||||
HOST_WIDE_INT offsets[MAX_VAR_PARTS];
|
||||
@ -2352,6 +2596,9 @@ emit_note_insn_var_location (void **varp, void *data)
|
||||
|
||||
gcc_assert (var->decl);
|
||||
|
||||
if (! flag_var_tracking_uninit)
|
||||
initialized = VAR_INIT_STATUS_INITIALIZED;
|
||||
|
||||
complete = true;
|
||||
last_limit = 0;
|
||||
n_var_parts = 0;
|
||||
@ -2369,6 +2616,7 @@ emit_note_insn_var_location (void **varp, void *data)
|
||||
offsets[n_var_parts] = var->var_part[i].offset;
|
||||
loc[n_var_parts] = var->var_part[i].loc_chain->loc;
|
||||
mode = GET_MODE (loc[n_var_parts]);
|
||||
initialized = var->var_part[i].loc_chain->init;
|
||||
last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
|
||||
|
||||
/* Attempt to merge adjacent registers or memory. */
|
||||
@ -2447,10 +2695,13 @@ emit_note_insn_var_location (void **varp, void *data)
|
||||
else
|
||||
note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
|
||||
|
||||
if (! flag_var_tracking_uninit)
|
||||
initialized = VAR_INIT_STATUS_INITIALIZED;
|
||||
|
||||
if (!complete)
|
||||
{
|
||||
NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
|
||||
NULL_RTX);
|
||||
NULL_RTX, (int) initialized);
|
||||
}
|
||||
else if (n_var_parts == 1)
|
||||
{
|
||||
@ -2458,7 +2709,8 @@ emit_note_insn_var_location (void **varp, void *data)
|
||||
= gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0]));
|
||||
|
||||
NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
|
||||
expr_list);
|
||||
expr_list,
|
||||
(int) initialized);
|
||||
}
|
||||
else if (n_var_parts)
|
||||
{
|
||||
@ -2471,7 +2723,8 @@ emit_note_insn_var_location (void **varp, void *data)
|
||||
parallel = gen_rtx_PARALLEL (VOIDmode,
|
||||
gen_rtvec_v (n_var_parts, loc));
|
||||
NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
|
||||
parallel);
|
||||
parallel,
|
||||
(int) initialized);
|
||||
}
|
||||
|
||||
htab_clear_slot (changed_variables, varp);
|
||||
@ -2602,11 +2855,14 @@ emit_notes_in_bb (basic_block bb)
|
||||
case MO_USE:
|
||||
{
|
||||
rtx loc = VTI (bb)->mos[i].u.loc;
|
||||
|
||||
|
||||
enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
|
||||
if (! flag_var_tracking_uninit)
|
||||
status = VAR_INIT_STATUS_INITIALIZED;
|
||||
if (GET_CODE (loc) == REG)
|
||||
var_reg_set (&set, loc);
|
||||
var_reg_set (&set, loc, status, NULL);
|
||||
else
|
||||
var_mem_set (&set, loc);
|
||||
var_mem_set (&set, loc, status, NULL);
|
||||
|
||||
emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
|
||||
}
|
||||
@ -2615,26 +2871,46 @@ emit_notes_in_bb (basic_block bb)
|
||||
case MO_SET:
|
||||
{
|
||||
rtx loc = VTI (bb)->mos[i].u.loc;
|
||||
rtx set_src = NULL;
|
||||
|
||||
if (GET_CODE (PATTERN (insn)) == SET)
|
||||
set_src = SET_SRC (PATTERN (insn));
|
||||
else if (GET_CODE (PATTERN (insn)) == PARALLEL
|
||||
|| GET_CODE (PATTERN (insn)) == SEQUENCE)
|
||||
{
|
||||
int j;
|
||||
for (j = XVECLEN (PATTERN (insn), 0) - 1; j >= 0; j--)
|
||||
if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == SET
|
||||
&& SET_DEST (XVECEXP (PATTERN (insn), 0, j)) == loc)
|
||||
set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, j));
|
||||
}
|
||||
|
||||
if (REG_P (loc))
|
||||
var_reg_delete_and_set (&set, loc, true);
|
||||
var_reg_delete_and_set (&set, loc, true, VAR_INIT_STATUS_INITIALIZED,
|
||||
set_src);
|
||||
else
|
||||
var_mem_delete_and_set (&set, loc, true);
|
||||
var_mem_delete_and_set (&set, loc, true, VAR_INIT_STATUS_INITIALIZED,
|
||||
set_src);
|
||||
|
||||
emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
|
||||
emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
|
||||
}
|
||||
break;
|
||||
|
||||
case MO_COPY:
|
||||
{
|
||||
rtx loc = VTI (bb)->mos[i].u.loc;
|
||||
enum var_init_status src_status;
|
||||
rtx set_src;
|
||||
|
||||
src_status = find_src_status (&set, loc, VTI (bb)->mos[i].insn);
|
||||
set_src = find_src_set_src (&set, loc, VTI (bb)->mos[i].insn);
|
||||
|
||||
if (REG_P (loc))
|
||||
var_reg_delete_and_set (&set, loc, false);
|
||||
var_reg_delete_and_set (&set, loc, false, src_status, set_src);
|
||||
else
|
||||
var_mem_delete_and_set (&set, loc, false);
|
||||
var_mem_delete_and_set (&set, loc, false, src_status, set_src);
|
||||
|
||||
emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
|
||||
emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2660,7 +2936,7 @@ emit_notes_in_bb (basic_block bb)
|
||||
else
|
||||
var_mem_delete (&set, loc, true);
|
||||
|
||||
emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
|
||||
emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2776,10 +3052,12 @@ vt_add_function_parameters (void)
|
||||
gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
|
||||
attrs_list_insert (&out->regs[REGNO (incoming)],
|
||||
parm, offset, incoming);
|
||||
set_variable_part (out, incoming, parm, offset);
|
||||
set_variable_part (out, incoming, parm, offset, VAR_INIT_STATUS_INITIALIZED,
|
||||
NULL);
|
||||
}
|
||||
else if (MEM_P (incoming))
|
||||
set_variable_part (out, incoming, parm, offset);
|
||||
set_variable_part (out, incoming, parm, offset, VAR_INIT_STATUS_INITIALIZED,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user