aboutsummaryrefslogtreecommitdiff
path: root/gcc/var-tracking.c
diff options
context:
space:
mode:
authorCaroline Tice <ctice@apple.com>2007-07-13 23:11:15 +0000
committerCaroline Tice <ctice@gcc.gnu.org>2007-07-13 16:11:15 -0700
commit62760ffd155d4ff29cf8f3092d756016a953b99e (patch)
treeb87516d5c9ea7c2c70b26f837f1dada3f4c4d0f0 /gcc/var-tracking.c
parentf861f54dd7ac84b6266d7bed21f5e79885cc5003 (diff)
downloadgcc-62760ffd155d4ff29cf8f3092d756016a953b99e.zip
gcc-62760ffd155d4ff29cf8f3092d756016a953b99e.tar.gz
gcc-62760ffd155d4ff29cf8f3092d756016a953b99e.tar.bz2
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
Diffstat (limited to 'gcc/var-tracking.c')
-rw-r--r--gcc/var-tracking.c382
1 files changed, 330 insertions, 52 deletions
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 94a025a..56dcc19 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -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);
}
}