Hi,
since the switch to SSA form at -O0, the compiler generates wrong debug info
for something like:
void
foo (int i)
{
int j = 0;
i = 1;
j = j + 1; /* BREAK */
}
If you try to display the value of i after breaking in GDB, you don't get 1.
The reason is that there is no default def SSA_NAME for i in this case, so no
partitions get the RTL location of the parameter.
Tentative patch attached, it's admittedly a little heavy, but I don't see any
other solution. Tested on x86_64-suse-linux, OK for the mainline?
2013-11-11 Eric Botcazou <ebotca...@adacore.com>
* tree-outof-ssa.c (remove_ssa_form): For a parameter without default
def, pretend that the single partition that contains all the SSA_NAMEs
for this parameter, if it exists, also contains the default def.
2013-11-11 Eric Botcazou <ebotca...@adacore.com>
* gcc.dg/guality/param-4.c: New test.
--
Eric Botcazou
Index: tree-outof-ssa.c
===================================================================
--- tree-outof-ssa.c (revision 204444)
+++ tree-outof-ssa.c (working copy)
@@ -972,7 +972,10 @@ expand_phi_nodes (struct ssaexpand *sa)
static void
remove_ssa_form (bool perform_ter, struct ssaexpand *sa)
{
+ tree fndecl = current_function_decl, arg;
bitmap values = NULL;
+ bitmap parameter_has_default_def;
+ struct pointer_map_t *parameter_map;
var_map map;
unsigned i;
@@ -999,17 +1002,85 @@ remove_ssa_form (bool perform_ter, struc
sa->map = map;
sa->values = values;
+
+ /* Find out which partitions contain a default def. If, for a parameter, no
+ partitions contain a default def for this parameter, then we pretend that
+ the single partition that contains all the SSA_NAMEs for this parameter
+ also contains the (ghost) default def, if such a partition exists. This
+ makes it possible to have correct debug info, without optimization, for
+ parameters written to before being read. */
sa->partition_has_default_def = BITMAP_ALLOC (NULL);
+ parameter_has_default_def = BITMAP_ALLOC (NULL);
+ parameter_map = pointer_map_create ();
+
for (i = 1; i < num_ssa_names; i++)
{
- tree t = ssa_name (i);
- if (t && SSA_NAME_IS_DEFAULT_DEF (t))
+ tree t, var;
+
+ t = ssa_name (i);
+ if (t == NULL_TREE)
+ continue;
+
+ var = SSA_NAME_VAR (t);
+
+ /* If this is a default def in a partition, set the appropriate flag for
+ the partition and, if this is a SSA_NAME for a parameter, record that
+ there is a default def for the parameter. */
+ if (SSA_NAME_IS_DEFAULT_DEF (t))
+ {
+ int p = var_to_partition (map, t);
+ if (p != NO_PARTITION)
+ {
+ bitmap_set_bit (sa->partition_has_default_def, p);
+ if (var && TREE_CODE (var) == PARM_DECL)
+ bitmap_set_bit (parameter_has_default_def, DECL_UID (var));
+ }
+ }
+
+ /* Otherwise, if this is a SSA_NAME for a parameter without default def,
+ at least yet, and in a partition, record the partition as associated
+ with the parameter, unless there is already a different one recorded,
+ in which case record NO_PARTITION. */
+ else if (var && TREE_CODE (var) == PARM_DECL
+ && !bitmap_bit_p (parameter_has_default_def, DECL_UID (var)))
{
int p = var_to_partition (map, t);
if (p != NO_PARTITION)
- bitmap_set_bit (sa->partition_has_default_def, p);
+ {
+ void **slot = pointer_map_contains (parameter_map, var);
+ if (slot)
+ {
+ int oldp = (int) (intptr_t) *slot;
+ if (oldp != p)
+ *slot = (void *) (intptr_t) NO_PARTITION;
+ }
+ else
+ {
+ slot = pointer_map_insert (parameter_map, var);
+ *slot = (void *) (intptr_t) p;
+ }
+ }
}
}
+
+ /* Finally walk the scalar parameters without default def and mark that
+ the partition that contains all the SSA_NAMEs for a parameter, if it
+ exists, contains the (ghost) default def. */
+ for (arg = DECL_ARGUMENTS (fndecl); arg; arg = DECL_CHAIN (arg))
+ if (is_gimple_reg_type (TREE_TYPE (arg))
+ && !bitmap_bit_p (parameter_has_default_def, DECL_UID (arg)))
+ {
+ void **slot = pointer_map_contains (parameter_map, arg);
+ if (slot)
+ {
+ int p = (int) (intptr_t) *slot;
+ if (p != NO_PARTITION)
+ bitmap_set_bit (sa->partition_has_default_def, p);
+ }
+ }
+
+ pointer_map_destroy (parameter_map);
+ BITMAP_FREE (parameter_has_default_def);
}
/* { dg-do run } */
/* { dg-options "-g" } */
/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
void
foo (int i)
{
int j = 0;
i = 1;
j = j + 1; /* BREAK */
}
int
main (void)
{
foo (0);
return 0;
}
/* { dg-final { gdb-test 10 "i" "1" } } */