As part of some work I've been doing on improving debugging of
optimized code, I
have developed the following patch which, while tracking the
locations of variables,
also keeps track of whether the variables are initialized or not (it
makes conservative
assumptions where it can't be sure). For those places where it is
sure the variables
are unintialized, it adds an annotation to the var_location_note,
which the dwarf
writer later translates to a new DW_OP (an extension) that indicates
a variable is uninitialized
(DW_OP_GNU_uninit).
Since this work requires that GDB be able to read and do something
reasonable with
the new DW_OP, I have also created a GDB patch to deal with the new
op, and to
inform the user that a particular value is unintialized when the
user asks to see it.
As the two patches really go together, I am attaching both of them
to this message.
(I will also be sending the GDB patch to the gdb patches list).
Because using the new DW_OP is sensitive to whether or not the user
has a version of GDB
that can handle it, I have added a macro, TARGET_DWARF_UNINIT_VARS,
which defaults
to 0, and which controls whether the uninitialized variable tracking
is done.
I have bootstrapped and run the dejagnu testsuite on this patch,
with no regressions, on
a ppc running apple-darwin, an x86 running apple-darwin, and an x86
64 running 64-bit linux.
Is this patch okay to commit to mainline?
-- Caroline Tice
ctice@apple.com
2007-05-01 Caroline Tice <ctice@apple.com>
* defaults.h (TARGET_DWARF_UNINIT_VARS): New macro, to control
tracking uninitialized variables.
* 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.
* 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 target doesn't have correct gdb
(tested by
macro TARGET_DWARF_UNINIT_VARS), 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 target doesn't have correct gdb
(tested by
macro TARGET_DWARF_UNINIT_VARS), 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/i386/linux.h (TARGET_DWARF_UNINIT_VARS): New macro
definition
to control tracking uninitialized variables. Redefined from
defaults.h
* config/darwin.h (TARGET_DWARF_UNINIT_VARS): New macro
definition to
control tracking uninitialized variables. Redefined from
defaults.h.
<fsf-gcc-patch.txt>
GDB PATCH:
2007-05-01 Caroline Tice <ctice@apple.com>
* c-valprint.c (c_value_print): If the var_status field of the
value struct is 0, print out "[uninitialized]" before the
value.
* dwarf2expr.c (add_piece): Make function non-static.
(unsigned_address_type): Likewise.
(signed_address_type): Likewise.
(execute_stack_op): Initialize ctx->var_status field; allow
DW_OP_GNU_uninit as legal op following a DW_OP_reg op or a
DW_OP_regx op; add case for DW_OP_GNU_uninit and update
ctx->var_status appropriately.
* dwarf2expr.h (struct dwarf_expr_context): New field,
var_status.
(unsigned_address_type): Add extern declaration.
(signed_address_type): Likewise.
(add_piece): Likewise.
* dwarf2loc.c (dwarf2_evaluate_loc_desc): Add call to
set_var_status.
* dwarf2read.c (dwarf_stack_op_name): Add case for
DW_OP_GNU_uninit.
(decode_locdesc): Add case for DW_OP_GNU_uninit.
* value.c (struct value): New field, var_status.
(allocate_value): Initialize new field.
(set_var_status): New function.
(value_var_status): New function.
* value.h (value_var_status): New extern declaration.
(set_var_status): Likewise.
* include/elf/dwarf2.h: (enum dwarf_location_atom): Add new
DW_OP,
DW_OP_GNU_uninit.
<fsf-gdb-patch.txt>