Hello world,
I have struggled with debugging the GENERIC generated by the
Fortran front end because it is only possible to look at the
code via -fdump-tree-original, but it is not possible to
inspect the values; additionally, the D.3456 form makes it
hard to read which variable is which.
This patch adds a flag which gives all variables generated by
Fortran a name and makes them visible to debuggers. As an
example, compiler-generated variables now look like this
(for a "Hello, world" program):
{
struct __st_parameter_dt dt_parm:0;
dt_parm:0.common.filename = &"hello.f90"[1]{lb: 1 sz: 1};
dt_parm:0.common.line = 2;
dt_parm:0.common.flags = 128;
dt_parm:0.common.unit = 6;
_gfortran_st_write (&dt_parm:0);
_gfortran_transfer_character_write (&dt_parm:0, &"Hello,
world"[1]{lb: 1 sz: 1}, 12);
_gfortran_st_write_done (&dt_parm:0);
}
Note the colon in the variable name, which I chose because it is
not in the user's namespace, and gdb does not choke on it.
In order to inspect the variables, you usually have to step
a bit through the generated assembly code, but you can then
print the values, manipulate them etc (and sometimes also hit
an internal error in gdb).
Example of a debugging session:
(gdb) b _gfortran_st_write
Breakpoint 1 at 0x4005f0
(gdb) r
Starting program: /tmp/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Breakpoint 1, _gfortran_st_write (dtp=0x7fffffffd9f0) at
../../../coarray_native/libgfortran/io/transfer.c:4398
4398 {
(gdb) fin
Run till exit from #0 _gfortran_st_write (dtp=0x7fffffffd9f0) at
../../../coarray_native/libgfortran/io/transfer.c:4398
0x0000000000400719 in MAIN__ () at hello.f90:2
2 print *,"Hello, world"
(gdb) info local
dt_parm:0 = ( common = ( flags = 128, unit = 6, filename = 0x400810,
line = 2, iomsg_len = 0, iomsg = 0x0, iostat = 0x0 ), rec = 0, size =
0x0, iolength = 0x0, internal_unit_desc = 0x0, format = 0x0, format_len
= 0, advance_len = 0, advance = 0x0, internal_unit = 0x0,
internal_unit_len = 0, namelist_name_len = 0, namelist_name = 0x0, id =
0x2, pos = -9223372036854775802, asynchronous = 0x0, asynchronous_len =
4569374499253603072, blank_len = 0, blank = 0x3f69ade5c1bd4b00, decimal
= 0x7ffff79490f0 <_gfortrani_backtrace_handler>, decimal_len =
140737335317407, delim_len = 140737347096816, delim = 0x1000000, pad =
0x0, pad_len = 0, round_len = 0, round = 0x0, sign = 0x0, sign_len = 0,
u =
'`&\270\367\377\177\000\000\060H`\000\000\000\000\000\000\000\000\000\001',
'\000' <repeats 35 times>, '\002', '\000' <repeats 71 times>,
'\377\377\377\377\377\377\377\377', '\000' <repeats 81 times>... )
(gdb) p dt_parm:0%common
$1 = ( flags = 128, unit = 6, filename = 0x400810, line = 2, iomsg_len =
0, iomsg = 0x0, iostat = 0x0 )
(gdb) p dt_parm:0%common%filename
$2 = (PTR TO -> ( character(kind=1) )) 0x400810
There is no user impact (only developers will use this), so it is not
surprising that there is no regression. So, OK for trunk?
Best regards
Thomas
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 8bdc8a6b038..58e4e50b315 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -1227,6 +1227,17 @@ compiler itself. The output generated by this option might change
between releases. This option may also generate internal compiler
errors for features which have only recently been added.
+@item -fdebug-aux-vars
+@opindex @code{debug-aux-vars}
+Make internal variables generated by the gfortran front end visible to a
+debugger. This option also renames these internal variables shown by
+@code{-fdump-tree-original} to a form @code{string:number} and enables
+compiler warnings on them.
+
+This option is only really useful when debugging the gfortran compiler
+itself together with @code{-g} or @code{-ggdb3} and
+@code{-fdump-tree-original}.
+
@item -ffpe-trap=@var{list}
@opindex @code{ffpe-trap=}@var{list}
Specify a list of floating point exception traps to enable. On most
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 96ed208cb85..57b0264458e 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -452,6 +452,10 @@ fd-lines-as-comments
Fortran RejectNegative
Treat lines with 'D' in column one as comments.
+fdebug-aux-vars
+Fortran Var(flag_debug_aux_vars)
+Issue debug information for compiler-generated auxiliary variables.
+
fdec
Fortran Var(flag_dec)
Enable all DEC language extensions.
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 025abe38985..1d5f6c28c7a 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -73,6 +73,40 @@ gfc_advance_chain (tree t, int n)
return t;
}
+static int num_var;
+
+#define MAX_PREFIX_LEN 20
+
+static tree
+create_var_debug_raw (tree type, const char *prefix)
+{
+ /* Space for prefix + @ + 9-digit-number + \0. */
+ char name_buf[MAX_PREFIX_LEN + 1 + 9 + 1];
+ tree t;
+
+ if (prefix == NULL)
+ prefix = "gfc";
+ else
+ gcc_assert (strlen(prefix) <= MAX_PREFIX_LEN);
+
+ snprintf (name_buf, sizeof(name_buf), "%s:%d", prefix, num_var++);
+ t = build_decl (input_location, VAR_DECL, get_identifier (name_buf), type);
+
+ /* We want debug info for it. */
+ DECL_IGNORED_P (t) = 0;
+ /* It should not be nameless. */
+ DECL_NAMELESS (t) = 0;
+
+ /* Make the variable writable. */
+ TREE_READONLY (t) = 0;
+
+ DECL_EXTERNAL (t) = 0;
+ TREE_STATIC (t) = 0;
+ TREE_USED (t) = 1;
+
+ return t;
+}
+
/* Creates a variable declaration with a given TYPE. */
tree
@@ -80,6 +114,9 @@ gfc_create_var_np (tree type, const char *prefix)
{
tree t;
+ if (flag_debug_aux_vars)
+ return create_var_debug_raw (type, prefix);
+
t = create_tmp_var_raw (type, prefix);
/* No warnings for anonymous variables. */