On Fri, 2016-08-12 at 11:00 +0530, Prathamesh Kulkarni wrote:
> On 12 August 2016 at 02:04, David Malcolm <[email protected]>
> wrote:
> > I sometimes find myself scouring assembler output from the compiler
> > and trying to figure out which instructions correspond to which
> > lines of source code; I believe this is a common activity for some
> > end-users.
> Hi David,
> I usually use gcc -g -Wa,-adhln to trace C source from the assembly.
If I'm reading that right, you're using the GNU assembler to emit a
listing file ("-a"), parsing the debuginfo with:
"d": omit debugging directives
"h": include high-level source
"l": include assembly
"n": omit forms processing
> I tried your example and it gave more or less a similar output
> (attached).
Thanks.
> However the source mapping with your patch looks better.
One specific goal of the patch is that the source information is in a
format that can be parsed by Emacs, and it can jump to the
corresponding location in the source file.
The do-it-in-gcc approach also doesn't rely on any smarts in the
assembler.
As Sandra noted, we already have -fverbose-asm, so I've posted an
updated patch to add the source-printing to that option, rather than as
a standalone option.
Dave
> Thanks,
> Prathamesh
> >
> > The following patch adds a new -fasm-show-source option, which
> > emits comments into the generated asm showing the pertinent
> > line of source code, whenever it changes. It uses the same logic
> > as debug_hooks->source_line for tracking this (for handling
> > line-based breakpoints).
> >
> > An example can be seen in the invoke.texi part of the patch. As
> > noted there, it's aimed at end-users, rather than gcc developers.
> > The example shows a relatively short function; the option is
> > likely to be much more useful for longer functions.
> >
> > I think it would further improve usability if this option were
> > enabled
> > by default when the final output is .s (either via -S, or by "-o
> > foo.s").
> > Ideas on how to implement that (in the driver) would be welcome - I
> > started looking at the spec-handling code, but thought I'd post the
> > idea here first, before diving in too deeply.
> >
> > Successfully bootstrapped®rtested on x86_64-pc-linux-gnu; adds
> > 2 PASS results to gcc.sum.
> >
> > Thoughts? OK for trunk as-is?
> >
> > gcc/ChangeLog:
> > * common.opt (fasm-show-source): New option.
> > * doc/invoke.texi (Code Generation Options): Add
> > -fasm-show-source.
> > (-fasm-show-source): New item.
> > * final.c (asm_show_source): New function.
> > (final_scan_insn): Call asm_show_source.
> >
> > gcc/testsuite/ChangeLog:
> > * gcc.dg/fasm-show-source-1.c: New test case.
> > ---
> > gcc/common.opt | 5 +++
> > gcc/doc/invoke.texi | 71
> > ++++++++++++++++++++++++++++++-
> > gcc/final.c | 29 ++++++++++++-
> > gcc/testsuite/gcc.dg/fasm-show-source-1.c | 15 +++++++
> > 4 files changed, 117 insertions(+), 3 deletions(-)
> > create mode 100644 gcc/testsuite/gcc.dg/fasm-show-source-1.c
> >
> > diff --git a/gcc/common.opt b/gcc/common.opt
> > index 8a292ed..56ce513 100644
> > --- a/gcc/common.opt
> > +++ b/gcc/common.opt
> > @@ -939,6 +939,11 @@ fargument-noalias-anything
> > Common Ignore
> > Does nothing. Preserved for backward compatibility.
> >
> > +fasm-show-source
> > +Common Var(flag_asm_show_source)
> > +Emit comments in the generated assembly code to show the source
> > code
> > +lines associated with the assembly instructions.
> > +
> > fsanitize=
> > Common Driver Report Joined
> > Select what to sanitize.
> > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > index 22001f9..dc3d3ad 100644
> > --- a/gcc/doc/invoke.texi
> > +++ b/gcc/doc/invoke.texi
> > @@ -486,7 +486,8 @@ Objective-C and Objective-C++ Dialects}.
> >
> > @item Code Generation Options
> > @xref{Code Gen Options,,Options for Code Generation Conventions}.
> > -@gccoptlist{-fcall-saved-@var{reg} -fcall-used-@var{reg} @gol
> > +@gccoptlist{-fasm-show-source @gol
> > +-fcall-saved-@var{reg} -fcall-used-@var{reg} @gol
> > -ffixed-@var{reg} -fexceptions @gol
> > -fnon-call-exceptions -fdelete-dead-exceptions -funwind-tables
> > @gol
> > -fasynchronous-unwind-tables @gol
> > @@ -11153,6 +11154,74 @@ can figure out the other form by either
> > removing @samp{no-} or adding
> > it.
> >
> > @table @gcctabopt
> > +@item -fasm-show-source
> > +@opindex fasm-show-source
> > +Emit comments in the generated assembly code to show the source
> > code
> > +lines associated with the assembly instructions. This option is
> > +aimed at end-users who wish to better understand the relationship
> > +between their source code and the generated machine code.
> > +
> > +The comments are of the form FILENAME:LINENUMBER:CONTENT OF LINE.
> > +
> > +For example, given this C source file:
> > +
> > +@smallexample
> > +int test (int n)
> > +@{
> > + int i;
> > + int total = 0;
> > +
> > + for (i = 0; i < n; i++)
> > + total += i * i;
> > +
> > + return total;
> > +@}
> > +@end smallexample
> > +
> > +compiling to (x86_64) assembly via @option{-S} and emitting the
> > result
> > +direct to stdout via @option{-o} @option{-}
> > +
> > +@smallexample
> > +gcc -S test.c -fasm-show-source -Os -o -
> > +@end smallexample
> > +
> > +gives output similar to this, highlighting which instructions
> > correspond
> > +to the various parts of the loop:
> > +
> > +@smallexample
> > + .file "test.c"
> > + .text
> > + .globl test
> > + .type test, @@function
> > +test:
> > +.LFB0:
> > + .cfi_startproc
> > +# test.c:4: int total = 0;
> > + xorl %eax, %eax
> > +# test.c:6: for (i = 0; i < n; i++)
> > + xorl %edx, %edx
> > +.L2:
> > +# test.c:6: for (i = 0; i < n; i++)
> > + cmpl %edi, %edx
> > + jge .L5
> > +# test.c:7: total += i * i;
> > + movl %edx, %ecx
> > + imull %edx, %ecx
> > +# test.c:6: for (i = 0; i < n; i++)
> > + incl %edx
> > +# test.c:7: total += i * i;
> > + addl %ecx, %eax
> > + jmp .L2
> > +.L5:
> > +# test.c:10: @}
> > + ret
> > + .cfi_endproc
> > +.LFE0:
> > + .size test, .-test
> > + .ident "GCC: (GNU) 7.0.0 20160809 (experimental)"
> > + .section .note.GNU-stack,"",@@progbits
> > +@end smallexample
> > +
> > @item -fstack-reuse=@var{reuse-level}
> > @opindex fstack_reuse
> > This option controls stack space reuse for user declared
> > local/auto variables
> > diff --git a/gcc/final.c b/gcc/final.c
> > index 5b04311..09bf0b7 100644
> > --- a/gcc/final.c
> > +++ b/gcc/final.c
> > @@ -2140,6 +2140,27 @@ call_from_call_insn (rtx_call_insn *insn)
> > return x;
> > }
> >
> > +/* Implementation of -fasm-show-source.
> > + Print a comment into the asm showing FILENAME, LINENUM, and the
> > + corresponding source line, if available. */
> > +
> > +static void
> > +asm_show_source (const char *filename, int linenum)
> > +{
> > + if (!filename)
> > + return;
> > +
> > + int line_size;
> > + const char *line = location_get_source_line (filename, linenum,
> > &line_size);
> > + if (!line)
> > + return;
> > +
> > + fprintf (asm_out_file, "%s %s:%i: ", ASM_COMMENT_START,
> > filename, linenum);
> > + /* "line" is not 0-terminated, so we must use line_size. */
> > + fwrite (line, 1, line_size, asm_out_file);
> > + fputc ('\n', asm_out_file);
> > +}
> > +
> > /* The final scan for one insn, INSN.
> > Args are same as in `final', except that INSN
> > is the insn being scanned.
> > @@ -2563,8 +2584,12 @@ final_scan_insn (rtx_insn *insn, FILE *file,
> > int optimize_p ATTRIBUTE_UNUSED,
> > note in a row. */
> > if (!DECL_IGNORED_P (current_function_decl)
> > && notice_source_line (insn, &is_stmt))
> > - (*debug_hooks->source_line) (last_linenum, last_filename,
> > - last_discriminator,
> > is_stmt);
> > + {
> > + if (flag_asm_show_source)
> > + asm_show_source (last_filename, last_linenum);
> > + (*debug_hooks->source_line) (last_linenum,
> > last_filename,
> > + last_discriminator,
> > is_stmt);
> > + }
> >
> > if (GET_CODE (body) == PARALLEL
> > && GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT)
> > diff --git a/gcc/testsuite/gcc.dg/fasm-show-source-1.c
> > b/gcc/testsuite/gcc.dg/fasm-show-source-1.c
> > new file mode 100644
> > index 0000000..3dd49e0
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/fasm-show-source-1.c
> > @@ -0,0 +1,15 @@
> > +/* Ensure that the generated asm contains FIXME */
> > +/* { dg-options "-fasm-show-source" } */
> > +
> > +int test (int n)
> > +{
> > + int i;
> > + int total = 0;
> > +
> > + for (i = 0; i < n; i++)
> > + total += i * i;
> > +
> > + return total;
> > +}
> > +
> > +/* { dg-final { scan-assembler "total = 0" } } */
> > --
> > 1.8.5.3
> >