diff options
author | ctice <ctice@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-07-13 23:11:15 +0000 |
---|---|---|
committer | ctice <ctice@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-07-13 23:11:15 +0000 |
commit | d53bb22673261b227d5045c435bd2acd4c87c236 (patch) | |
tree | b87516d5c9ea7c2c70b26f837f1dada3f4c4d0f0 /gcc/var-tracking.c | |
parent | aa9311a1b831d7e2f0575a09def64eff0dac9f6a (diff) | |
download | gcc-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.c | 382 |
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); } } |