Commit 62760ffd by Caroline Tice Committed by Caroline Tice

Add ability to track uninitialized variables, and mark uninitialized variables…

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
parent f861f54d
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> 2007-07-13 Sa Liu <saliu@de.ibm.com>
* config.gcc: Add options for arch and tune on SPU. * config.gcc: Add options for arch and tune on SPU.
......
...@@ -1130,6 +1130,10 @@ fvar-tracking ...@@ -1130,6 +1130,10 @@ fvar-tracking
Common Report Var(flag_var_tracking) VarExists Optimization Common Report Var(flag_var_tracking) VarExists Optimization
Perform variable tracking 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 ftree-vectorize
Common Report Var(flag_tree_vectorize) Optimization Common Report Var(flag_tree_vectorize) Optimization
Enable loop vectorization on trees Enable loop vectorization on trees
......
...@@ -1728,6 +1728,9 @@ darwin_override_options (void) ...@@ -1728,6 +1728,9 @@ darwin_override_options (void)
/* No -fnon-call-exceptions data in kexts. */ /* No -fnon-call-exceptions data in kexts. */
flag_non_call_exceptions = 0; 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" #include "gt-darwin.h"
...@@ -540,6 +540,8 @@ enum dwarf_location_atom ...@@ -540,6 +540,8 @@ enum dwarf_location_atom
DW_OP_bit_piece = 0x9d, DW_OP_bit_piece = 0x9d,
/* GNU extensions. */ /* GNU extensions. */
DW_OP_GNU_push_tls_address = 0xe0, DW_OP_GNU_push_tls_address = 0xe0,
/* The following is for marking variables that are uninitialized. */
DW_OP_GNU_uninit = 0xf0,
/* HP extensions. */ /* HP extensions. */
DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */ DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */
DW_OP_HP_is_value = 0xe1, DW_OP_HP_is_value = 0xe1,
......
...@@ -3125,6 +3125,8 @@ dwarf_stack_op_name (unsigned int op) ...@@ -3125,6 +3125,8 @@ dwarf_stack_op_name (unsigned int op)
return "DW_OP_call_ref"; return "DW_OP_call_ref";
case DW_OP_GNU_push_tls_address: case DW_OP_GNU_push_tls_address:
return "DW_OP_GNU_push_tls_address"; return "DW_OP_GNU_push_tls_address";
case DW_OP_GNU_uninit:
return "DW_OP_GNU_uninit";
default: default:
return "OP_<unknown>"; return "OP_<unknown>";
} }
...@@ -4193,15 +4195,20 @@ static dw_die_ref modified_type_die (tree, int, int, dw_die_ref); ...@@ -4193,15 +4195,20 @@ static dw_die_ref modified_type_die (tree, int, int, dw_die_ref);
static int type_is_enum (tree); static int type_is_enum (tree);
static unsigned int dbx_reg_number (rtx); static unsigned int dbx_reg_number (rtx);
static void add_loc_descr_op_piece (dw_loc_descr_ref *, int); 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 reg_loc_descriptor (rtx, enum var_init_status);
static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int); static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int,
static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx); 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 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 int is_based_loc (rtx);
static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode); static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode,
static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx); enum var_init_status);
static dw_loc_descr_ref loc_descriptor (rtx); 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_1 (tree, int);
static dw_loc_descr_ref loc_descriptor_from_tree (tree); static dw_loc_descr_ref loc_descriptor_from_tree (tree);
static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int); 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) ...@@ -5757,9 +5764,16 @@ add_var_loc_to_decl (tree decl, struct var_loc_node *loc)
if (temp->last) if (temp->last)
{ {
/* If the current location is the same as the end of the list, /* 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. */ we have nothing to do. */
if (!rtx_equal_p (NOTE_VAR_LOCATION_LOC (temp->last->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_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. */ /* Add LOC to the end of list and update LAST. */
temp->last->next = loc; temp->last->next = loc;
...@@ -7069,6 +7083,9 @@ output_loc_list (dw_loc_list_ref list_head) ...@@ -7069,6 +7083,9 @@ output_loc_list (dw_loc_list_ref list_head)
for (curr = list_head; curr != NULL; curr = curr->dw_loc_next) for (curr = list_head; curr != NULL; curr = curr->dw_loc_next)
{ {
unsigned long size; 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) if (!have_multiple_function_sections)
{ {
dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section, 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) ...@@ -8747,7 +8764,7 @@ add_loc_descr_op_piece (dw_loc_descr_ref *list_head, int size)
zero if there is none. */ zero if there is none. */
static dw_loc_descr_ref static dw_loc_descr_ref
reg_loc_descriptor (rtx rtl) reg_loc_descriptor (rtx rtl, enum var_init_status initialized)
{ {
rtx regs; rtx regs;
...@@ -8757,28 +8774,35 @@ reg_loc_descriptor (rtx rtl) ...@@ -8757,28 +8774,35 @@ reg_loc_descriptor (rtx rtl)
regs = targetm.dwarf_register_span (rtl); regs = targetm.dwarf_register_span (rtl);
if (hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)] > 1 || regs) 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 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 /* Return a location descriptor that designates a machine register for
a given hard register number. */ a given hard register number. */
static dw_loc_descr_ref 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) 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 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 (&reg_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 /* Given an RTL of a register, return a location descriptor that
designates a value that spans more than one register. */ designates a value that spans more than one register. */
static dw_loc_descr_ref 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; int nregs, size, i;
unsigned reg; unsigned reg;
...@@ -8806,7 +8830,8 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs) ...@@ -8806,7 +8830,8 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
{ {
dw_loc_descr_ref t; 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 (&loc_result, t);
add_loc_descr_op_piece (&loc_result, size); add_loc_descr_op_piece (&loc_result, size);
++reg; ++reg;
...@@ -8825,11 +8850,15 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs) ...@@ -8825,11 +8850,15 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
{ {
dw_loc_descr_ref t; 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); add_loc_descr (&loc_result, t);
size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0))); size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0)));
add_loc_descr_op_piece (&loc_result, size); 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; return loc_result;
} }
...@@ -8875,9 +8904,11 @@ int_loc_descriptor (HOST_WIDE_INT i) ...@@ -8875,9 +8904,11 @@ int_loc_descriptor (HOST_WIDE_INT i)
/* Return a location descriptor that designates a base+offset location. */ /* Return a location descriptor that designates a base+offset location. */
static dw_loc_descr_ref static dw_loc_descr_ref
based_loc_descr (rtx reg, HOST_WIDE_INT offset) based_loc_descr (rtx reg, HOST_WIDE_INT offset,
enum var_init_status initialized)
{ {
unsigned int regno; unsigned int regno;
dw_loc_descr_ref result;
/* We only use "frame base" when we're sure we're talking about the /* 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 post-prologue local stack frame. We do this by *not* running
...@@ -8904,9 +8935,14 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset) ...@@ -8904,9 +8935,14 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset)
regno = dbx_reg_number (reg); regno = dbx_reg_number (reg);
if (regno <= 31) if (regno <= 31)
return new_loc_descr (DW_OP_breg0 + regno, offset, 0); result = new_loc_descr (DW_OP_breg0 + regno, offset, 0);
else 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. */ /* Return true if this RTL expression describes a base+offset calculation. */
...@@ -8924,7 +8960,8 @@ is_based_loc (rtx rtl) ...@@ -8924,7 +8960,8 @@ is_based_loc (rtx rtl)
used to form the address of a memory location. */ used to form the address of a memory location. */
static dw_loc_descr_ref 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; unsigned int i;
dw_loc_descr_ref cc_loc_result = NULL; dw_loc_descr_ref cc_loc_result = NULL;
...@@ -8935,7 +8972,7 @@ concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode) ...@@ -8935,7 +8972,7 @@ concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode)
dw_loc_descr_ref ref; dw_loc_descr_ref ref;
rtx x = XVECEXP (concatn, 0, i); 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) if (ref == NULL)
return NULL; return NULL;
...@@ -8943,6 +8980,9 @@ concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode) ...@@ -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))); 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; return cc_loc_result;
} }
...@@ -8965,7 +9005,8 @@ concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode) ...@@ -8965,7 +9005,8 @@ concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode)
Return 0 if we can't represent the location. */ Return 0 if we can't represent the location. */
static dw_loc_descr_ref static dw_loc_descr_ref
mem_loc_descriptor (rtx rtl, enum machine_mode mode) mem_loc_descriptor (rtx rtl, enum machine_mode mode,
enum var_init_status initialized)
{ {
dw_loc_descr_ref mem_loc_result = NULL; dw_loc_descr_ref mem_loc_result = NULL;
enum dwarf_location_atom op; enum dwarf_location_atom op;
...@@ -9012,11 +9053,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) ...@@ -9012,11 +9053,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
memory) so DWARF consumers need to be aware of the subtle memory) so DWARF consumers need to be aware of the subtle
distinction between OP_REG and OP_BASEREG. */ distinction between OP_REG and OP_BASEREG. */
if (REGNO (rtl) < FIRST_PSEUDO_REGISTER) if (REGNO (rtl) < FIRST_PSEUDO_REGISTER)
mem_loc_result = based_loc_descr (rtl, 0); mem_loc_result = based_loc_descr (rtl, 0, VAR_INIT_STATUS_INITIALIZED);
break; break;
case MEM: case MEM:
mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl)); mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
VAR_INIT_STATUS_INITIALIZED);
if (mem_loc_result != 0) if (mem_loc_result != 0)
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0)); add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
break; break;
...@@ -9083,10 +9125,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) ...@@ -9083,10 +9125,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
plus: plus:
if (is_based_loc (rtl)) if (is_based_loc (rtl))
mem_loc_result = based_loc_descr (XEXP (rtl, 0), mem_loc_result = based_loc_descr (XEXP (rtl, 0),
INTVAL (XEXP (rtl, 1))); INTVAL (XEXP (rtl, 1)),
VAR_INIT_STATUS_INITIALIZED);
else 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) if (mem_loc_result == 0)
break; break;
...@@ -9098,7 +9142,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) ...@@ -9098,7 +9142,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
else else
{ {
add_loc_descr (&mem_loc_result, add_loc_descr (&mem_loc_result,
mem_loc_descriptor (XEXP (rtl, 1), mode)); mem_loc_descriptor (XEXP (rtl, 1), mode,
VAR_INIT_STATUS_INITIALIZED));
add_loc_descr (&mem_loc_result, add_loc_descr (&mem_loc_result,
new_loc_descr (DW_OP_plus, 0, 0)); new_loc_descr (DW_OP_plus, 0, 0));
} }
...@@ -9125,8 +9170,10 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) ...@@ -9125,8 +9170,10 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
do_binop: do_binop:
{ {
dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode); dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode,
dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode); 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) if (op0 == 0 || op1 == 0)
break; break;
...@@ -9142,13 +9189,17 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) ...@@ -9142,13 +9189,17 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
break; break;
case CONCATN: 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; break;
default: default:
gcc_unreachable (); 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; return mem_loc_result;
} }
...@@ -9156,11 +9207,11 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode) ...@@ -9156,11 +9207,11 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode)
This is typically a complex variable. */ This is typically a complex variable. */
static dw_loc_descr_ref 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 cc_loc_result = NULL;
dw_loc_descr_ref x0_ref = loc_descriptor (x0); dw_loc_descr_ref x0_ref = loc_descriptor (x0, VAR_INIT_STATUS_INITIALIZED);
dw_loc_descr_ref x1_ref = loc_descriptor (x1); dw_loc_descr_ref x1_ref = loc_descriptor (x1, VAR_INIT_STATUS_INITIALIZED);
if (x0_ref == 0 || x1_ref == 0) if (x0_ref == 0 || x1_ref == 0)
return 0; return 0;
...@@ -9171,6 +9222,9 @@ concat_loc_descriptor (rtx x0, rtx x1) ...@@ -9171,6 +9222,9 @@ concat_loc_descriptor (rtx x0, rtx x1)
add_loc_descr (&cc_loc_result, x1_ref); add_loc_descr (&cc_loc_result, x1_ref);
add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x1))); 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; return cc_loc_result;
} }
...@@ -9178,7 +9232,7 @@ concat_loc_descriptor (rtx x0, rtx x1) ...@@ -9178,7 +9232,7 @@ concat_loc_descriptor (rtx x0, rtx x1)
locations. */ locations. */
static dw_loc_descr_ref static dw_loc_descr_ref
concatn_loc_descriptor (rtx concatn) concatn_loc_descriptor (rtx concatn, enum var_init_status initialized)
{ {
unsigned int i; unsigned int i;
dw_loc_descr_ref cc_loc_result = NULL; dw_loc_descr_ref cc_loc_result = NULL;
...@@ -9189,7 +9243,7 @@ concatn_loc_descriptor (rtx concatn) ...@@ -9189,7 +9243,7 @@ concatn_loc_descriptor (rtx concatn)
dw_loc_descr_ref ref; dw_loc_descr_ref ref;
rtx x = XVECEXP (concatn, 0, i); rtx x = XVECEXP (concatn, 0, i);
ref = loc_descriptor (x); ref = loc_descriptor (x, VAR_INIT_STATUS_INITIALIZED);
if (ref == NULL) if (ref == NULL)
return NULL; return NULL;
...@@ -9197,6 +9251,9 @@ concatn_loc_descriptor (rtx concatn) ...@@ -9197,6 +9251,9 @@ concatn_loc_descriptor (rtx concatn)
add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x))); 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; return cc_loc_result;
} }
...@@ -9209,7 +9266,7 @@ concatn_loc_descriptor (rtx concatn) ...@@ -9209,7 +9266,7 @@ concatn_loc_descriptor (rtx concatn)
If we don't know how to describe it, return 0. */ If we don't know how to describe it, return 0. */
static dw_loc_descr_ref static dw_loc_descr_ref
loc_descriptor (rtx rtl) loc_descriptor (rtx rtl, enum var_init_status initialized)
{ {
dw_loc_descr_ref loc_result = NULL; dw_loc_descr_ref loc_result = NULL;
...@@ -9226,26 +9283,28 @@ loc_descriptor (rtx rtl) ...@@ -9226,26 +9283,28 @@ loc_descriptor (rtx rtl)
/* ... fall through ... */ /* ... fall through ... */
case REG: case REG:
loc_result = reg_loc_descriptor (rtl); loc_result = reg_loc_descriptor (rtl, initialized);
break; break;
case MEM: case MEM:
loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl)); loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
initialized);
break; break;
case CONCAT: case CONCAT:
loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1)); loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1),
initialized);
break; break;
case CONCATN: case CONCATN:
loc_result = concatn_loc_descriptor (rtl); loc_result = concatn_loc_descriptor (rtl, initialized);
break; break;
case VAR_LOCATION: case VAR_LOCATION:
/* Single part. */ /* Single part. */
if (GET_CODE (XEXP (rtl, 1)) != PARALLEL) 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; break;
} }
...@@ -9260,14 +9319,16 @@ loc_descriptor (rtx rtl) ...@@ -9260,14 +9319,16 @@ loc_descriptor (rtx rtl)
int i; int i;
/* Create the first one, so we have something to add to. */ /* Create the first one, so we have something to add to. */
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)); mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode)); add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
for (i = 1; i < num_elem; i++) for (i = 1; i < num_elem; i++)
{ {
dw_loc_descr_ref temp; dw_loc_descr_ref temp;
temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0)); temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0),
initialized);
add_loc_descr (&loc_result, temp); add_loc_descr (&loc_result, temp);
mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode)); 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) ...@@ -9399,7 +9460,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
/* Certain constructs can only be represented at top-level. */ /* Certain constructs can only be represented at top-level. */
if (want_address == 2) if (want_address == 2)
return loc_descriptor (rtl); return loc_descriptor (rtl, VAR_INIT_STATUS_INITIALIZED);
mode = GET_MODE (rtl); mode = GET_MODE (rtl);
if (MEM_P (rtl)) if (MEM_P (rtl))
...@@ -9407,7 +9468,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address) ...@@ -9407,7 +9468,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
rtl = XEXP (rtl, 0); rtl = XEXP (rtl, 0);
have_address = 1; have_address = 1;
} }
ret = mem_loc_descriptor (rtl, mode); ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
} }
} }
break; break;
...@@ -9488,7 +9549,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address) ...@@ -9488,7 +9549,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
return 0; return 0;
mode = GET_MODE (rtl); mode = GET_MODE (rtl);
rtl = XEXP (rtl, 0); rtl = XEXP (rtl, 0);
ret = mem_loc_descriptor (rtl, mode); ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
have_address = 1; have_address = 1;
break; break;
} }
...@@ -10575,6 +10636,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, ...@@ -10575,6 +10636,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
const char *endname, *secname; const char *endname, *secname;
dw_loc_list_ref list; dw_loc_list_ref list;
rtx varloc; rtx varloc;
enum var_init_status initialized;
/* Now that we know what section we are using for a base, /* Now that we know what section we are using for a base,
actually construct the list of locations. actually construct the list of locations.
...@@ -10591,7 +10653,12 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, ...@@ -10591,7 +10653,12 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
varloc = NOTE_VAR_LOCATION (node->var_loc_note); varloc = NOTE_VAR_LOCATION (node->var_loc_note);
secname = secname_for_decl (decl); 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->label, node->next->label, secname, 1);
node = node->next; node = node->next;
...@@ -10600,8 +10667,11 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, ...@@ -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 /* The variable has a location between NODE->LABEL and
NODE->NEXT->LABEL. */ NODE->NEXT->LABEL. */
enum var_init_status initialized =
NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
varloc = NOTE_VAR_LOCATION (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); node->label, node->next->label, secname);
} }
...@@ -10610,6 +10680,8 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, ...@@ -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) if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
{ {
char label_id[MAX_ARTIFICIAL_LABEL_BYTES]; 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); varloc = NOTE_VAR_LOCATION (node->var_loc_note);
if (!current_function_decl) if (!current_function_decl)
...@@ -10620,7 +10692,8 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, ...@@ -10620,7 +10692,8 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
current_function_funcdef_no); current_function_funcdef_no);
endname = ggc_strdup (label_id); 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); node->label, endname, secname);
} }
...@@ -10644,8 +10717,10 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, ...@@ -10644,8 +10717,10 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
location list, try generating a location from that. */ location list, try generating a location from that. */
if (loc_list && loc_list->first) if (loc_list && loc_list->first)
{ {
enum var_init_status status;
node = loc_list->first; 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) if (descr)
{ {
add_AT_location_description (die, attr, descr); add_AT_location_description (die, attr, descr);
......
...@@ -325,6 +325,9 @@ print_rtx (rtx in_rtx) ...@@ -325,6 +325,9 @@ print_rtx (rtx in_rtx)
print_mem_expr (outfile, NOTE_VAR_LOCATION_DECL (in_rtx)); print_mem_expr (outfile, NOTE_VAR_LOCATION_DECL (in_rtx));
fprintf (outfile, " "); fprintf (outfile, " ");
print_rtx (NOTE_VAR_LOCATION_LOC (in_rtx)); print_rtx (NOTE_VAR_LOCATION_LOC (in_rtx));
if (NOTE_VAR_LOCATION_STATUS (in_rtx) ==
VAR_INIT_STATUS_UNINITIALIZED)
fprintf (outfile, " [uninit]");
fprintf (outfile, ")"); fprintf (outfile, ")");
#endif #endif
break; break;
......
...@@ -680,7 +680,9 @@ DEF_RTL_EXPR(SS_TRUNCATE, "ss_truncate", "e", RTX_UNARY) ...@@ -680,7 +680,9 @@ DEF_RTL_EXPR(SS_TRUNCATE, "ss_truncate", "e", RTX_UNARY)
DEF_RTL_EXPR(US_TRUNCATE, "us_truncate", "e", RTX_UNARY) DEF_RTL_EXPR(US_TRUNCATE, "us_truncate", "e", RTX_UNARY)
/* Information about the variable and its location. */ /* 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 /* All expressions from this point forward appear only in machine
descriptions. */ descriptions. */
......
...@@ -847,6 +847,22 @@ extern const char * const reg_note_name[]; ...@@ -847,6 +847,22 @@ extern const char * const reg_note_name[];
#define NOTE_VAR_LOCATION_LOC(INSN) (XCEXP (XCEXP (INSN, 4, NOTE), \ #define NOTE_VAR_LOCATION_LOC(INSN) (XCEXP (XCEXP (INSN, 4, NOTE), \
1, VAR_LOCATION)) 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 /* Codes that appear in the NOTE_KIND field for kinds of notes
that are not line numbers. These codes are all negative. that are not line numbers. These codes are all negative.
......
...@@ -1874,7 +1874,8 @@ process_options (void) ...@@ -1874,7 +1874,8 @@ process_options (void)
if (debug_info_level < DINFO_LEVEL_NORMAL if (debug_info_level < DINFO_LEVEL_NORMAL
|| debug_hooks->var_location == do_nothing_debug_hooks.var_location) || 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) if (debug_info_level < DINFO_LEVEL_NORMAL)
warning (0, "variable tracking requested, but useless unless " warning (0, "variable tracking requested, but useless unless "
...@@ -1884,6 +1885,7 @@ process_options (void) ...@@ -1884,6 +1885,7 @@ process_options (void)
"by this debug format"); "by this debug format");
} }
flag_var_tracking = 0; flag_var_tracking = 0;
flag_var_tracking_uninit = 0;
} }
if (flag_rename_registers == AUTODETECT_VALUE) if (flag_rename_registers == AUTODETECT_VALUE)
...@@ -1893,6 +1895,12 @@ process_options (void) ...@@ -1893,6 +1895,12 @@ process_options (void)
if (flag_var_tracking == AUTODETECT_VALUE) if (flag_var_tracking == AUTODETECT_VALUE)
flag_var_tracking = optimize >= 1; 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. /* If auxiliary info generation is desired, open the output file.
This goes in the same directory as the source file--unlike This goes in the same directory as the source file--unlike
all the other output files. */ all the other output files. */
......
...@@ -219,6 +219,12 @@ typedef struct location_chain_def ...@@ -219,6 +219,12 @@ typedef struct location_chain_def
/* The location (REG or MEM). */ /* The location (REG or MEM). */
rtx loc; rtx loc;
/* The "value" stored in this location. */
rtx set_src;
/* Initialized? */
enum var_init_status init;
} *location_chain; } *location_chain;
/* Structure describing one part of variable. */ /* Structure describing one part of variable. */
...@@ -294,16 +300,19 @@ static void attrs_list_copy (attrs *, attrs); ...@@ -294,16 +300,19 @@ static void attrs_list_copy (attrs *, attrs);
static void attrs_list_union (attrs *, attrs); static void attrs_list_union (attrs *, attrs);
static void vars_clear (htab_t); 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 int vars_copy_1 (void **, void *);
static void vars_copy (htab_t, htab_t); static void vars_copy (htab_t, htab_t);
static tree var_debug_decl (tree); static tree var_debug_decl (tree);
static void var_reg_set (dataflow_set *, rtx); static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
static void var_reg_delete_and_set (dataflow_set *, rtx, bool); 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_reg_delete (dataflow_set *, rtx, bool);
static void var_regno_delete (dataflow_set *, int); static void var_regno_delete (dataflow_set *, int);
static void var_mem_set (dataflow_set *, rtx); static void var_mem_set (dataflow_set *, rtx, enum var_init_status, rtx);
static void var_mem_delete_and_set (dataflow_set *, rtx, bool); 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 var_mem_delete (dataflow_set *, rtx, bool);
static void dataflow_set_init (dataflow_set *, int); static void dataflow_set_init (dataflow_set *, int);
...@@ -338,8 +347,10 @@ static void dump_dataflow_set (dataflow_set *); ...@@ -338,8 +347,10 @@ static void dump_dataflow_set (dataflow_set *);
static void dump_dataflow_sets (void); static void dump_dataflow_sets (void);
static void variable_was_changed (variable, htab_t); static void variable_was_changed (variable, htab_t);
static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT); static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT,
static void clobber_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 void delete_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT);
static int emit_note_insn_var_location (void **, void *); static int emit_note_insn_var_location (void **, void *);
static void emit_notes_for_changes (rtx, enum emit_note_where); static void emit_notes_for_changes (rtx, enum emit_note_where);
...@@ -727,7 +738,8 @@ vars_clear (htab_t vars) ...@@ -727,7 +738,8 @@ vars_clear (htab_t vars)
/* Return a copy of a variable VAR and insert it to dataflow set SET. */ /* Return a copy of a variable VAR and insert it to dataflow set SET. */
static variable static variable
unshare_variable (dataflow_set *set, variable var) unshare_variable (dataflow_set *set, variable var,
enum var_init_status initialized)
{ {
void **slot; void **slot;
variable new_var; variable new_var;
...@@ -752,6 +764,14 @@ unshare_variable (dataflow_set *set, variable var) ...@@ -752,6 +764,14 @@ unshare_variable (dataflow_set *set, variable var)
new_lc = pool_alloc (loc_chain_pool); new_lc = pool_alloc (loc_chain_pool);
new_lc->next = NULL; 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; new_lc->loc = node->loc;
*nextp = new_lc; *nextp = new_lc;
...@@ -819,7 +839,8 @@ var_debug_decl (tree decl) ...@@ -819,7 +839,8 @@ var_debug_decl (tree decl)
/* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */ /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
static void 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); tree decl = REG_EXPR (loc);
HOST_WIDE_INT offset = REG_OFFSET (loc); HOST_WIDE_INT offset = REG_OFFSET (loc);
...@@ -832,7 +853,38 @@ var_reg_set (dataflow_set *set, rtx loc) ...@@ -832,7 +853,38 @@ var_reg_set (dataflow_set *set, rtx loc)
break; break;
if (!node) if (!node)
attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc); 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 /* Delete current content of register LOC in dataflow set SET and set
...@@ -843,7 +895,8 @@ var_reg_set (dataflow_set *set, rtx loc) ...@@ -843,7 +895,8 @@ var_reg_set (dataflow_set *set, rtx loc)
part. */ part. */
static void 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); tree decl = REG_EXPR (loc);
HOST_WIDE_INT offset = REG_OFFSET (loc); HOST_WIDE_INT offset = REG_OFFSET (loc);
...@@ -852,6 +905,9 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify) ...@@ -852,6 +905,9 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify)
decl = var_debug_decl (decl); decl = var_debug_decl (decl);
if (initialized == VAR_INIT_STATUS_UNKNOWN)
initialized = get_init_value (set, loc, decl);
nextp = &set->regs[REGNO (loc)]; nextp = &set->regs[REGNO (loc)];
for (node = *nextp; node; node = next) for (node = *nextp; node; node = next)
{ {
...@@ -869,8 +925,8 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify) ...@@ -869,8 +925,8 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify)
} }
} }
if (modify) if (modify)
clobber_variable_part (set, loc, decl, offset); clobber_variable_part (set, loc, decl, offset, set_src);
var_reg_set (set, loc); var_reg_set (set, loc, initialized, set_src);
} }
/* Delete current content of register LOC in dataflow set SET. If /* 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) ...@@ -890,7 +946,7 @@ var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
decl = var_debug_decl (decl); 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) for (node = *reg; node; node = next)
...@@ -924,14 +980,15 @@ var_regno_delete (dataflow_set *set, int regno) ...@@ -924,14 +980,15 @@ var_regno_delete (dataflow_set *set, int regno)
Adjust the address first if it is stack pointer based. */ Adjust the address first if it is stack pointer based. */
static void 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); tree decl = MEM_EXPR (loc);
HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0; HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
decl = var_debug_decl (decl); 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 /* Delete and set the location part of variable MEM_EXPR (LOC) in
...@@ -942,16 +999,20 @@ var_mem_set (dataflow_set *set, rtx loc) ...@@ -942,16 +999,20 @@ var_mem_set (dataflow_set *set, rtx loc)
Adjust the address first if it is stack pointer based. */ Adjust the address first if it is stack pointer based. */
static void 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); tree decl = MEM_EXPR (loc);
HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0; HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
decl = var_debug_decl (decl); decl = var_debug_decl (decl);
if (initialized == VAR_INIT_STATUS_UNKNOWN)
initialized = get_init_value (set, loc, decl);
if (modify) if (modify)
clobber_variable_part (set, NULL, decl, offset); clobber_variable_part (set, NULL, decl, offset, set_src);
var_mem_set (set, loc); var_mem_set (set, loc, initialized, set_src);
} }
/* Delete the location part LOC from dataflow set SET. If CLOBBER is /* 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) ...@@ -966,7 +1027,7 @@ var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
decl = var_debug_decl (decl); decl = var_debug_decl (decl);
if (clobber) if (clobber)
clobber_variable_part (set, NULL, decl, offset); clobber_variable_part (set, NULL, decl, offset, NULL);
delete_variable_part (set, loc, decl, offset); delete_variable_part (set, loc, decl, offset);
} }
...@@ -1078,7 +1139,14 @@ variable_union (void **slot, void *data) ...@@ -1078,7 +1139,14 @@ variable_union (void **slot, void *data)
} }
} }
if (k < src->n_var_parts) 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 else
*dstp = src; *dstp = src;
...@@ -1112,7 +1180,13 @@ variable_union (void **slot, void *data) ...@@ -1112,7 +1180,13 @@ variable_union (void **slot, void *data)
gcc_assert (k <= MAX_VAR_PARTS); gcc_assert (k <= MAX_VAR_PARTS);
if (dst->refcount > 1 && dst->n_var_parts != k) 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; i = src->n_var_parts - 1;
j = dst->n_var_parts - 1; j = dst->n_var_parts - 1;
...@@ -1145,10 +1219,12 @@ variable_union (void **slot, void *data) ...@@ -1145,10 +1219,12 @@ variable_union (void **slot, void *data)
&& REG_P (node->loc) && REG_P (node->loc)
&& REGNO (node2->loc) == REGNO (node->loc)) && REGNO (node2->loc) == REGNO (node->loc))
|| rtx_equal_p (node2->loc, node->loc))) || rtx_equal_p (node2->loc, node->loc)))
if (node2->init < node->init)
node2->init = node->init;
break; break;
} }
if (node || node2) if (node || node2)
dst = unshare_variable (set, dst); dst = unshare_variable (set, dst, VAR_INIT_STATUS_UNKNOWN);
} }
src_l = 0; src_l = 0;
...@@ -1194,6 +1270,11 @@ variable_union (void **slot, void *data) ...@@ -1194,6 +1270,11 @@ variable_union (void **slot, void *data)
/* Copy the location from SRC. */ /* Copy the location from SRC. */
new_node = pool_alloc (loc_chain_pool); new_node = pool_alloc (loc_chain_pool);
new_node->loc = node->loc; 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].lc = new_node;
vui[n].pos_src = ii; vui[n].pos_src = ii;
vui[n].pos_dst = src_l + dst_l; vui[n].pos_dst = src_l + dst_l;
...@@ -1240,6 +1321,11 @@ variable_union (void **slot, void *data) ...@@ -1240,6 +1321,11 @@ variable_union (void **slot, void *data)
new_lc = pool_alloc (loc_chain_pool); new_lc = pool_alloc (loc_chain_pool);
new_lc->next = NULL; 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; new_lc->loc = node->loc;
*nextp = new_lc; *nextp = new_lc;
...@@ -1258,6 +1344,18 @@ variable_union (void **slot, void *data) ...@@ -1258,6 +1344,18 @@ variable_union (void **slot, void *data)
dst->var_part[k].cur_loc = NULL; 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. */ /* Continue traversing the hash table. */
return 1; return 1;
} }
...@@ -1679,7 +1777,7 @@ add_stores (rtx loc, rtx expr, void *insn) ...@@ -1679,7 +1777,7 @@ add_stores (rtx loc, rtx expr, void *insn)
else else
mo->type = MO_SET; mo->type = MO_SET;
mo->u.loc = loc; mo->u.loc = loc;
mo->insn = NEXT_INSN ((rtx) insn); mo->insn = (rtx) insn;
} }
else if (MEM_P (loc) else if (MEM_P (loc)
&& MEM_EXPR (loc) && MEM_EXPR (loc)
...@@ -1700,10 +1798,99 @@ add_stores (rtx loc, rtx expr, void *insn) ...@@ -1700,10 +1798,99 @@ add_stores (rtx loc, rtx expr, void *insn)
else else
mo->type = MO_SET; mo->type = MO_SET;
mo->u.loc = loc; 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. */ /* Compute the changes of variable locations in the basic block BB. */
static bool static bool
...@@ -1733,33 +1920,65 @@ compute_bb_dataflow (basic_block bb) ...@@ -1733,33 +1920,65 @@ compute_bb_dataflow (basic_block bb)
case MO_USE: case MO_USE:
{ {
rtx loc = VTI (bb)->mos[i].u.loc; 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) if (GET_CODE (loc) == REG)
var_reg_set (out, loc); var_reg_set (out, loc, status, NULL);
else if (GET_CODE (loc) == MEM) else if (GET_CODE (loc) == MEM)
var_mem_set (out, loc); var_mem_set (out, loc, status, NULL);
} }
break; break;
case MO_SET: case MO_SET:
{ {
rtx loc = VTI (bb)->mos[i].u.loc; 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)) 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)) 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; break;
case MO_COPY: case MO_COPY:
{ {
rtx loc = VTI (bb)->mos[i].u.loc; 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)) 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)) 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; break;
...@@ -1932,6 +2151,8 @@ dump_variable (void **slot, void *data ATTRIBUTE_UNUSED) ...@@ -1932,6 +2151,8 @@ dump_variable (void **slot, void *data ATTRIBUTE_UNUSED)
for (node = var->var_part[i].loc_chain; node; node = node->next) for (node = var->var_part[i].loc_chain; node; node = node->next)
{ {
fprintf (dump_file, " "); fprintf (dump_file, " ");
if (node->init == VAR_INIT_STATUS_UNINITIALIZED)
fprintf (dump_file, "[uninit]");
print_rtl_single (dump_file, node->loc); print_rtl_single (dump_file, node->loc);
} }
} }
...@@ -2077,7 +2298,8 @@ find_variable_location_part (variable var, HOST_WIDE_INT offset, ...@@ -2077,7 +2298,8 @@ find_variable_location_part (variable var, HOST_WIDE_INT offset,
part's location by LOC. */ part's location by LOC. */
static void 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; int pos;
location_chain node, next; location_chain node, next;
...@@ -2119,13 +2341,19 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset) ...@@ -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 /* LOC is in the beginning of the chain so we have nothing
to do. */ to do. */
if (node->init < initialized)
node->init = initialized;
if (set_src != NULL)
node->set_src = set_src;
*slot = var;
return; return;
} }
else else
{ {
/* We have to make a copy of a shared variable. */ /* We have to make a copy of a shared variable. */
if (var->refcount > 1) if (var->refcount > 1)
var = unshare_variable (set, var); var = unshare_variable (set, var, initialized);
} }
} }
else else
...@@ -2134,7 +2362,7 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset) ...@@ -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. */ /* We have to make a copy of the shared variable. */
if (var->refcount > 1) 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 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
thus there are at most MAX_VAR_PARTS different offsets. */ 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) ...@@ -2161,6 +2389,12 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
&& REGNO (node->loc) == REGNO (loc)) && REGNO (node->loc) == REGNO (loc))
|| rtx_equal_p (node->loc, 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); pool_free (loc_chain_pool, node);
*nextp = next; *nextp = next;
break; break;
...@@ -2172,6 +2406,8 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset) ...@@ -2172,6 +2406,8 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
/* Add the location to the beginning. */ /* Add the location to the beginning. */
node = pool_alloc (loc_chain_pool); node = pool_alloc (loc_chain_pool);
node->loc = loc; node->loc = loc;
node->init = initialized;
node->set_src = set_src;
node->next = var->var_part[pos].loc_chain; node->next = var->var_part[pos].loc_chain;
var->var_part[pos].loc_chain = node; 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) ...@@ -2190,7 +2426,7 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
static void static void
clobber_variable_part (dataflow_set *set, rtx loc, tree decl, clobber_variable_part (dataflow_set *set, rtx loc, tree decl,
HOST_WIDE_INT offset) HOST_WIDE_INT offset, rtx set_src)
{ {
void **slot; void **slot;
...@@ -2213,7 +2449,11 @@ clobber_variable_part (dataflow_set *set, rtx loc, tree decl, ...@@ -2213,7 +2449,11 @@ clobber_variable_part (dataflow_set *set, rtx loc, tree decl,
for (node = next; node; node = next) for (node = next; node; node = next)
{ {
next = 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)) if (REG_P (node->loc))
{ {
...@@ -2278,7 +2518,10 @@ delete_variable_part (dataflow_set *set, rtx loc, tree decl, ...@@ -2278,7 +2518,10 @@ delete_variable_part (dataflow_set *set, rtx loc, tree decl,
&& REGNO (node->loc) == REGNO (loc)) && REGNO (node->loc) == REGNO (loc))
|| rtx_equal_p (node->loc, 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; break;
} }
} }
...@@ -2345,6 +2588,7 @@ emit_note_insn_var_location (void **varp, void *data) ...@@ -2345,6 +2588,7 @@ emit_note_insn_var_location (void **varp, void *data)
rtx note; rtx note;
int i, j, n_var_parts; int i, j, n_var_parts;
bool complete; bool complete;
enum var_init_status initialized = VAR_INIT_STATUS_UNINITIALIZED;
HOST_WIDE_INT last_limit; HOST_WIDE_INT last_limit;
tree type_size_unit; tree type_size_unit;
HOST_WIDE_INT offsets[MAX_VAR_PARTS]; HOST_WIDE_INT offsets[MAX_VAR_PARTS];
...@@ -2352,6 +2596,9 @@ emit_note_insn_var_location (void **varp, void *data) ...@@ -2352,6 +2596,9 @@ emit_note_insn_var_location (void **varp, void *data)
gcc_assert (var->decl); gcc_assert (var->decl);
if (! flag_var_tracking_uninit)
initialized = VAR_INIT_STATUS_INITIALIZED;
complete = true; complete = true;
last_limit = 0; last_limit = 0;
n_var_parts = 0; n_var_parts = 0;
...@@ -2369,6 +2616,7 @@ emit_note_insn_var_location (void **varp, void *data) ...@@ -2369,6 +2616,7 @@ emit_note_insn_var_location (void **varp, void *data)
offsets[n_var_parts] = var->var_part[i].offset; offsets[n_var_parts] = var->var_part[i].offset;
loc[n_var_parts] = var->var_part[i].loc_chain->loc; loc[n_var_parts] = var->var_part[i].loc_chain->loc;
mode = GET_MODE (loc[n_var_parts]); 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); last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
/* Attempt to merge adjacent registers or memory. */ /* Attempt to merge adjacent registers or memory. */
...@@ -2447,10 +2695,13 @@ emit_note_insn_var_location (void **varp, void *data) ...@@ -2447,10 +2695,13 @@ emit_note_insn_var_location (void **varp, void *data)
else else
note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn); note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
if (! flag_var_tracking_uninit)
initialized = VAR_INIT_STATUS_INITIALIZED;
if (!complete) if (!complete)
{ {
NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
NULL_RTX); NULL_RTX, (int) initialized);
} }
else if (n_var_parts == 1) else if (n_var_parts == 1)
{ {
...@@ -2458,7 +2709,8 @@ emit_note_insn_var_location (void **varp, void *data) ...@@ -2458,7 +2709,8 @@ emit_note_insn_var_location (void **varp, void *data)
= gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0])); = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0]));
NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
expr_list); expr_list,
(int) initialized);
} }
else if (n_var_parts) else if (n_var_parts)
{ {
...@@ -2471,7 +2723,8 @@ emit_note_insn_var_location (void **varp, void *data) ...@@ -2471,7 +2723,8 @@ emit_note_insn_var_location (void **varp, void *data)
parallel = gen_rtx_PARALLEL (VOIDmode, parallel = gen_rtx_PARALLEL (VOIDmode,
gen_rtvec_v (n_var_parts, loc)); gen_rtvec_v (n_var_parts, loc));
NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
parallel); parallel,
(int) initialized);
} }
htab_clear_slot (changed_variables, varp); htab_clear_slot (changed_variables, varp);
...@@ -2602,11 +2855,14 @@ emit_notes_in_bb (basic_block bb) ...@@ -2602,11 +2855,14 @@ emit_notes_in_bb (basic_block bb)
case MO_USE: case MO_USE:
{ {
rtx loc = VTI (bb)->mos[i].u.loc; 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) if (GET_CODE (loc) == REG)
var_reg_set (&set, loc); var_reg_set (&set, loc, status, NULL);
else else
var_mem_set (&set, loc); var_mem_set (&set, loc, status, NULL);
emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
} }
...@@ -2615,26 +2871,46 @@ emit_notes_in_bb (basic_block bb) ...@@ -2615,26 +2871,46 @@ emit_notes_in_bb (basic_block bb)
case MO_SET: case MO_SET:
{ {
rtx loc = VTI (bb)->mos[i].u.loc; 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)) 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 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; break;
case MO_COPY: case MO_COPY:
{ {
rtx loc = VTI (bb)->mos[i].u.loc; 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)) 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 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; break;
...@@ -2660,7 +2936,7 @@ emit_notes_in_bb (basic_block bb) ...@@ -2660,7 +2936,7 @@ emit_notes_in_bb (basic_block bb)
else else
var_mem_delete (&set, loc, true); 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; break;
...@@ -2776,10 +3052,12 @@ vt_add_function_parameters (void) ...@@ -2776,10 +3052,12 @@ vt_add_function_parameters (void)
gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER); gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
attrs_list_insert (&out->regs[REGNO (incoming)], attrs_list_insert (&out->regs[REGNO (incoming)],
parm, offset, 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)) else if (MEM_P (incoming))
set_variable_part (out, incoming, parm, offset); set_variable_part (out, incoming, parm, offset, VAR_INIT_STATUS_INITIALIZED,
NULL);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment