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)
 

Reply via email to