summaryrefslogtreecommitdiff
path: root/gcc/var-tracking.c
diff options
context:
space:
mode:
authorctice <ctice@138bc75d-0d04-0410-961f-82ee72b054a4>2007-07-13 23:11:15 +0000
committerctice <ctice@138bc75d-0d04-0410-961f-82ee72b054a4>2007-07-13 23:11:15 +0000
commitd53bb22673261b227d5045c435bd2acd4c87c236 (patch)
treeb87516d5c9ea7c2c70b26f837f1dada3f4c4d0f0 /gcc/var-tracking.c
parentaa9311a1b831d7e2f0575a09def64eff0dac9f6a (diff)
downloadgcc-d53bb22673261b227d5045c435bd2acd4c87c236.tar.gz
Add ability to track uninitialized variables, and mark uninitialized
variables in the Dwarf debug info. Controlled by compile option -fvar-tracking-uninit git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@126630 138bc75d-0d04-0410-961f-82ee72b054a4
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 94a025a002b..56dcc198d7d 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);
}
}