At the moment NOTE_INSN_FUNCTION_BEG is used for three different purposes. The first is as a marker just before the first insn coming from a "source code statement" of the function. Bug 88432 is due to the fact that the note does not accurately point to this logical position in a function -- in that case the stack protect prologue is directly after NOTE_INSN_FUNCTION_BEG.
The second is (I believe) to make assumptions about what values are in the parameter passing registers (in alias.c and calls.c). (I'm not sure about this second use, if I am correctly reading this code then it seems like a bug -- e.g. asan_emit_stack_protect inserts insns in the stream that break the assumption that seems to be made.) The third is as a marker to determine where to put extra code later in sjlj_emit_function_enter from except.c, where to insert profiling code for a function in final.c, and where to insert variable expansion code in pass_expand::execute from cfgexpand.c. These three uses seem to be at odds with each other -- insns that change the values in the parameter passing registers store can come from automatically inserted code like stack protection, and some requirements on where instructions should get inserted have moved the position of this NOTE (e.g. see bugzilla bug 81186). This patch splits the current note into two different notes, one to retain uses 2 and 3 above, and one for use in genrating debug information. The first two uses are still attached to NOTE_INSN_FUNCTION_BEG, while the debugging use is now implemented with NOTE_INSN_DEBUG_FUNCTION_BEG. These two notes are put into the functions' insn chain in different places during the expand pass, and can hence satisfy their respective uses. Bootstrapped and regtested on aarch64. TODO -- Manual tests done on resulting debug information -- yet to be automated. gcc/ChangeLog: 2019-01-10 Matthew Malcomson <matthew.malcom...@arm.com> PR debug/88432 * cfgexpand.c (pass_expand::execute): Insert NOTE_INSN_DEBUG_FUNCTION_BEG. * function.c (thread_prologue_and_epilogue_insns): Account for NOTE_INSN_DEBUG_FUNCTION_BEG. * cfgrtl.c (duplicate_insn_chain): Account for new NOTE. * doc/rtl.texi: Document new NOTE. * dwarf2out.c (dwarf2out_source_line): Change comment to reference new NOTE. * final.c (asm_show_source): As above. (final_scan_insn_1): Split action on NOTE_INSN_FUNCTION_BEG into two, and move debugging info action to trigger on NOTE_INSN_DEBUG_FUNCTION_BEG. * insn-notes.def (INSN_NOTE): Add new NOTE. ############### Attachment also inlined for ease of reply ############### diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 60c1cfb4556e1a659db19f6719adccc1dab0fe46..491f441d01de226ba5aff2af8c71680b78648a12 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -6476,6 +6476,12 @@ pass_expand::execute (function *fun) if (crtl->stack_protect_guard && targetm.stack_protect_runtime_enabled_p ()) stack_protect_prologue (); + /* Insert a NOTE that marks the end of "generated code" and the start of code + that comes from the user. This is the point which dwarf2out.c will treat + as the beginning of the users code in this function. e.g. GDB will stop + just after this note when breaking on entry to the function. */ + emit_note (NOTE_INSN_DEBUG_FUNCTION_BEG); + expand_phi_nodes (&SA); /* Release any stale SSA redirection data. */ diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 172bdf585d036e27bcf53dba89c1ffc1b6cb84c7..d0cbca84aa3f14002a568a65e70016c3e15d6b9c 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -4215,6 +4215,7 @@ duplicate_insn_chain (rtx_insn *from, rtx_insn *to) case NOTE_INSN_DELETED_DEBUG_LABEL: /* No problem to strip these. */ case NOTE_INSN_FUNCTION_BEG: + case NOTE_INSN_DEBUG_FUNCTION_BEG: /* There is always just single entry to function. */ case NOTE_INSN_BASIC_BLOCK: /* We should only switch text sections once. */ diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 583291018538722a19a9baf8c46c87cbdfe34216..a50d08483de0db84378e48c9334b48ff12548190 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -3954,6 +3954,18 @@ identifies which region is associated with these notes. Appears at the start of the function body, after the function prologue. +@findex NOTE_INSN_DEBUG_FUNCTION_BEG +@item NOTE_INSN_DEBUG_FUNCTION_BEG +This NOTE is inserted at the start of a function during RTL expansion. +It is inserted at the point in a function where code coming directly from the +"users source" starts. i.e. the first insn that appears after this note should +be generated from the user code (and not from automatic code generation to +support compiler features). +This NOTE is used to ensure the first debug line number after the start of any +function is the line number of the first source code statement in that +function. GDB typically determines where to first stop in a function based on +this first line number entry. + @findex NOTE_INSN_VAR_LOCATION @findex NOTE_VAR_LOCATION @item NOTE_INSN_VAR_LOCATION diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 8d9a3849fa4289e246a10a66252667dd4c6e0f75..10d05cd51fc679cb4acfc85f76df415d1d9b1f0d 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -27807,7 +27807,7 @@ dwarf2out_source_line (unsigned int line, unsigned int column, as the end_prologue debug hook. The NOTE_INSN_PROLOGUE_END note, to which the hook corresponds, follows the last insn that was emitted by gen_prologue. What we need is to precede the first insn - that had been emitted after NOTE_INSN_FUNCTION_BEG, i.e. the first + that had been emitted after NOTE_INSN_DEBUG_FUNCTION_BEG, i.e. the first insn that corresponds to something the user wrote. These may be very different locations once scheduling is enabled. */ diff --git a/gcc/final.c b/gcc/final.c index 6dc1cd1b0c8c4bd764a7a77cd4ed6a1fe95603c0..c80e5878feae21696d26b69c9f3013ac186b7231 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -2165,7 +2165,7 @@ asm_show_source (const char *filename, int linenum) SEEN is used to track the end of the prologue, for emitting debug information. We force the emission of a line note after - both NOTE_INSN_PROLOGUE_END and NOTE_INSN_FUNCTION_BEG. */ + both NOTE_INSN_PROLOGUE_END and NOTE_INSN_DEBUG_FUNCTION_BEG. */ static rtx_insn * final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, @@ -2299,6 +2299,9 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, need_profile_function = false; } + break; + + case NOTE_INSN_DEBUG_FUNCTION_BEG: app_disable (); if (!DECL_IGNORED_P (current_function_decl)) debug_hooks->end_prologue (last_linenum, last_filename); diff --git a/gcc/function.c b/gcc/function.c index cec344bdac8cd59ebca0364a165147d25f1e95cf..9e5950d712b9cf3142ddb0fc24b1188ee28539a7 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -6069,7 +6069,8 @@ thread_prologue_and_epilogue_insns (void) { next = NEXT_INSN (insn); if (NOTE_P (insn) - && (NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG)) + && ((NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG) + || (NOTE_KIND (insn) == NOTE_INSN_DEBUG_FUNCTION_BEG))) reorder_insns (insn, insn, PREV_INSN (epilogue_seq)); } } diff --git a/gcc/insn-notes.def b/gcc/insn-notes.def index 337e9df8a75659cb73e4a9934842fa504b56a12e..2cb7f792fa45554b1379c265fabd86285da594a5 100644 --- a/gcc/insn-notes.def +++ b/gcc/insn-notes.def @@ -51,6 +51,12 @@ INSN_NOTE (BLOCK_END) their homes, etc. */ INSN_NOTE (FUNCTION_BEG) +/* This note indicates the start of user code. + This is different to FUNCTION_BEG above as FUNCTION_BEG is put before the + stack protection prologue, the code saving the stack location for nonlocal + gotos, and the code profiling code. */ +INSN_NOTE (DEBUG_FUNCTION_BEG) + /* This marks the point immediately after the last prologue insn. */ INSN_NOTE (PROLOGUE_END)
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 60c1cfb4556e1a659db19f6719adccc1dab0fe46..491f441d01de226ba5aff2af8c71680b78648a12 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -6476,6 +6476,12 @@ pass_expand::execute (function *fun) if (crtl->stack_protect_guard && targetm.stack_protect_runtime_enabled_p ()) stack_protect_prologue (); + /* Insert a NOTE that marks the end of "generated code" and the start of code + that comes from the user. This is the point which dwarf2out.c will treat + as the beginning of the users code in this function. e.g. GDB will stop + just after this note when breaking on entry to the function. */ + emit_note (NOTE_INSN_DEBUG_FUNCTION_BEG); + expand_phi_nodes (&SA); /* Release any stale SSA redirection data. */ diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 172bdf585d036e27bcf53dba89c1ffc1b6cb84c7..d0cbca84aa3f14002a568a65e70016c3e15d6b9c 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -4215,6 +4215,7 @@ duplicate_insn_chain (rtx_insn *from, rtx_insn *to) case NOTE_INSN_DELETED_DEBUG_LABEL: /* No problem to strip these. */ case NOTE_INSN_FUNCTION_BEG: + case NOTE_INSN_DEBUG_FUNCTION_BEG: /* There is always just single entry to function. */ case NOTE_INSN_BASIC_BLOCK: /* We should only switch text sections once. */ diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 583291018538722a19a9baf8c46c87cbdfe34216..a50d08483de0db84378e48c9334b48ff12548190 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -3954,6 +3954,18 @@ identifies which region is associated with these notes. Appears at the start of the function body, after the function prologue. +@findex NOTE_INSN_DEBUG_FUNCTION_BEG +@item NOTE_INSN_DEBUG_FUNCTION_BEG +This NOTE is inserted at the start of a function during RTL expansion. +It is inserted at the point in a function where code coming directly from the +"users source" starts. i.e. the first insn that appears after this note should +be generated from the user code (and not from automatic code generation to +support compiler features). +This NOTE is used to ensure the first debug line number after the start of any +function is the line number of the first source code statement in that +function. GDB typically determines where to first stop in a function based on +this first line number entry. + @findex NOTE_INSN_VAR_LOCATION @findex NOTE_VAR_LOCATION @item NOTE_INSN_VAR_LOCATION diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 8d9a3849fa4289e246a10a66252667dd4c6e0f75..10d05cd51fc679cb4acfc85f76df415d1d9b1f0d 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -27807,7 +27807,7 @@ dwarf2out_source_line (unsigned int line, unsigned int column, as the end_prologue debug hook. The NOTE_INSN_PROLOGUE_END note, to which the hook corresponds, follows the last insn that was emitted by gen_prologue. What we need is to precede the first insn - that had been emitted after NOTE_INSN_FUNCTION_BEG, i.e. the first + that had been emitted after NOTE_INSN_DEBUG_FUNCTION_BEG, i.e. the first insn that corresponds to something the user wrote. These may be very different locations once scheduling is enabled. */ diff --git a/gcc/final.c b/gcc/final.c index 6dc1cd1b0c8c4bd764a7a77cd4ed6a1fe95603c0..c80e5878feae21696d26b69c9f3013ac186b7231 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -2165,7 +2165,7 @@ asm_show_source (const char *filename, int linenum) SEEN is used to track the end of the prologue, for emitting debug information. We force the emission of a line note after - both NOTE_INSN_PROLOGUE_END and NOTE_INSN_FUNCTION_BEG. */ + both NOTE_INSN_PROLOGUE_END and NOTE_INSN_DEBUG_FUNCTION_BEG. */ static rtx_insn * final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, @@ -2299,6 +2299,9 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, need_profile_function = false; } + break; + + case NOTE_INSN_DEBUG_FUNCTION_BEG: app_disable (); if (!DECL_IGNORED_P (current_function_decl)) debug_hooks->end_prologue (last_linenum, last_filename); diff --git a/gcc/function.c b/gcc/function.c index cec344bdac8cd59ebca0364a165147d25f1e95cf..9e5950d712b9cf3142ddb0fc24b1188ee28539a7 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -6069,7 +6069,8 @@ thread_prologue_and_epilogue_insns (void) { next = NEXT_INSN (insn); if (NOTE_P (insn) - && (NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG)) + && ((NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG) + || (NOTE_KIND (insn) == NOTE_INSN_DEBUG_FUNCTION_BEG))) reorder_insns (insn, insn, PREV_INSN (epilogue_seq)); } } diff --git a/gcc/insn-notes.def b/gcc/insn-notes.def index 337e9df8a75659cb73e4a9934842fa504b56a12e..2cb7f792fa45554b1379c265fabd86285da594a5 100644 --- a/gcc/insn-notes.def +++ b/gcc/insn-notes.def @@ -51,6 +51,12 @@ INSN_NOTE (BLOCK_END) their homes, etc. */ INSN_NOTE (FUNCTION_BEG) +/* This note indicates the start of user code. + This is different to FUNCTION_BEG above as FUNCTION_BEG is put before the + stack protection prologue, the code saving the stack location for nonlocal + gotos, and the code profiling code. */ +INSN_NOTE (DEBUG_FUNCTION_BEG) + /* This marks the point immediately after the last prologue insn. */ INSN_NOTE (PROLOGUE_END)