On 12 August 2016 at 02:04, David Malcolm <dmalc...@redhat.com> 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. I tried your example and it gave more or less a similar output (attached). However the source mapping with your patch looks better.
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 >
1 .file "foo.c" 2 .text 3 .Ltext0: 4 .section .text.unlikely,"ax",@progbits 5 .LCOLDB0: 6 .text 7 .LHOTB0: 8 .section .text.unlikely 9 .Ltext_cold0: 10 .text 11 .globl f 13 f: 14 .LFB0: 15 .file 1 "foo.c" 1:foo.c **** int f(int n) 2:foo.c **** { 16 .loc 1 2 0 17 .cfi_startproc 18 .LVL0: 19 .LBB2: 3:foo.c **** int total = 0; 4:foo.c **** for (int i = 0; i < n; i++) 20 .loc 1 4 0 21 0000 31D2 xorl %edx, %edx 22 .LBE2: 3:foo.c **** int total = 0; 23 .loc 1 3 0 24 0002 31C0 xorl %eax, %eax 25 .LVL1: 26 .L2: 27 .LBB3: 28 .loc 1 4 0 discriminator 1 29 0004 39FA cmpl %edi, %edx 30 0006 7D0B jge .L5 5:foo.c **** total += i * i; 31 .loc 1 5 0 discriminator 3 32 0008 89D1 movl %edx, %ecx 33 000a 0FAFCA imull %edx, %ecx 4:foo.c **** return total; 34 .loc 1 4 0 discriminator 3 35 000d FFC2 incl %edx 36 .LVL2: 37 .loc 1 5 0 discriminator 3 38 000f 01C8 addl %ecx, %eax 39 .LVL3: 40 0011 EBF1 jmp .L2 41 .L5: 42 .LBE3: 6:foo.c **** return total; 7:foo.c **** } 43 .loc 1 7 0 44 0013 C3 ret 45 .cfi_endproc 46 .LFE0: 48 .section .text.unlikely 49 .LCOLDE0: 50 .text 51 .LHOTE0: 52 .Letext0: 53 .section .text.unlikely 54 .Letext_cold0: