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.
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