This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Line info in the presence of __main, and NOTE_INSN_FUNCTION_BEG after scheduling.


Hi all,

(
This is a follow up of the discussion starting here:
http://sources.redhat.com/ml/gdb/2006-11/msg00134.html
Ending up with Daniel's response here:
http://sources.redhat.com/ml/gdb/2006-11/msg00140.html
)

Currently, in Cygwin, or in any other target that emits calls to __main in main, when
the user requests a break on main in gdb, gdb will put the break on the opening {, instead of
on the first statement, eg: on printf below.


#include <stdio.h>

int
main ()
{
  printf ("hello world\n");
  return 0;
}

The problem is that gdb, in the presence of debug info, uses the second line number
marker to mark the end of the prologue, and as you can see below,
there is a .loc before __main, confusing gdb.
Snipped from running 'gcc main.c -g -gdwarf-2 -O3 -o main.s -S' :


.globl _main
       .def    _main;  .scl    2;      .type   32;     .endef
_main:
LFB3:
       .file 1 "main.c"
       .loc 1 5 0
       leal    4(%esp), %ecx
LCFI0:
       andl    $-16, %esp
       pushl   -4(%ecx)
LCFI1:
       pushl   %ebp
LCFI2:
       movl    %esp, %ebp
LCFI3:
       pushl   %ecx
LCFI4:
       subl    $4, %esp
LCFI5:
       .loc 1 5 0
       call    ___main
       .loc 1 6 0
       movl    $LC0, (%esp)
       call    _puts
       .loc 1 7 0
       movl    $0, %eax
       .loc 1 8 0
       addl    $4, %esp
       popl    %ecx
       popl    %ebp
       leal    -4(%ecx), %esp
       ret

---

The attached patch fixes the gcc part by doing two things:

- Move the expand_main_function call to before NOTE_INSN_FUNCTION_BEG note is emitted,
so the __main call is not considered part of the user function body;
- Preserve NOTE_INSN_FUNCTION_BEG/NOTE_INSN_FUNCTION_END across scheduler runs. It does that
using the REG_SAVE_NOTE mechanism. There where also some old comments around this mechanism that
were no longer true. The patch also fixes them.
(It also makes final.c:final_scan_insn output some more -dA comments, to easily track the changes.)


This is the result of gcc main.c -o main.s -dA -O3 -S with the patched compiler:

$cat main.s
       .file   "main.c"
       .def    ___main;        .scl    2;      .type   32;     .endef
       .section .rdata,"dr"
LC0:
       .ascii "hello world\0"
       .text
       .p2align 4,,15
.globl _main
       .def    _main;  .scl    2;      .type   32;     .endef
_main:
        # basic block 2
       leal    4(%esp), %ecx
       andl    $-16, %esp
       pushl   -4(%ecx)
       pushl   %ebp
       movl    %esp, %ebp
       pushl   %ecx
       subl    $4, %esp
        # prologue end
       call    ___main
        # function beg
       movl    $LC0, (%esp)
       call    _puts
        # epilogue beg
       addl    $4, %esp
        # function end
       xorl    %eax, %eax
       popl    %ecx
       popl    %ebp
       leal    -4(%ecx), %esp
       ret
       .def    _puts;  .scl    2;      .type   32;     .endef

Notice the '# function beg' after 'call ___main'.

Bootstrapped and tested with no regressions on native Cygwin for --enable-languages=c,c++.
With a gdb patch to make i386 targets skip the prologue using the symbol table
like most other targets do (currently i386 targets always scan the prologue the hard way), this fixes all
the GDB testsuite failures (a few dozens) related to setting a breakpoint on main and running to it (runto_main) on Cygwin.


:ADDPATCH:

Cheers,
Pedro Alves

---

gcc/ChangeLog

2006-12-09 Pedro Alves <pedro_alves@portugalmail.pt>

       * cfgexpand.c (tree_expand_cfg): Move expand_main_function and
       stack_protect_prologue calls to ...
       * function.c (expand_function_start): ... here.
       (expand_main_function): Make it static.
       * tree.h (expand_main_function): Remove declaration.
       * sched-deps.c (sched_analyze): Save NOTE_INSN_FUNCTION_BEG and
       NOTE_INSN_FUNCTION_END using REG_SAVE_NOTE.
       * haifa-sched.c: Update NOTES handling comment.
       (unlink_other_notes): Don't handle NOTE_INSN_FUNCTION_BEG and
       NOTE_INSN_FUNCTION_END here.
       Update comment.
       * final.c (final_scan_insn): Output asm debug comments on
       NOTE_INSN_PROLOGUE_BEG, NOTE_INSN_PROLOGUE_END, NOTE_INSN_EPILOGUE_BEG,
       NOTE_INSN_FUNCTION_BEG, NOTE_INSN_FUNCTION_END, NOTE_INSN_BLOCK_BEG
       and NOTE_INSN_BLOCK_END.



Index: cfgexpand.c
===================================================================
--- cfgexpand.c	(revision 119115)
+++ cfgexpand.c	(working copy)
@@ -1623,18 +1623,6 @@ tree_expand_cfg (void)
   /* Set up parameters and prepare for return, for the function.  */
   expand_function_start (current_function_decl);
 
-  /* If this function is `main', emit a call to `__main'
-     to run global initializers, etc.  */
-  if (DECL_NAME (current_function_decl)
-      && MAIN_NAME_P (DECL_NAME (current_function_decl))
-      && DECL_FILE_SCOPE_P (current_function_decl))
-    expand_main_function ();
-
-  /* Initialize the stack_protect_guard field.  This must happen after the
-     call to __main (if any) so that the external decl is initialized.  */
-  if (cfun->stack_protect_guard)
-    stack_protect_prologue ();
-
   /* Register rtl specific functions for cfg.  */
   rtl_register_cfg_hooks ();
 
Index: function.c
===================================================================
--- function.c	(revision 119115)
+++ function.c	(working copy)
@@ -3927,7 +3927,7 @@ struct tree_opt_pass pass_init_function 
 };
 
 
-void
+static void
 expand_main_function (void)
 {
 #if (defined(INVOKE__main)				\
@@ -4170,6 +4170,18 @@ expand_function_start (tree subr)
       update_nonlocal_goto_save_area ();
     }
 
+  /* If this function is `main', emit a call to `__main'
+     to run global initializers, etc.  */
+  if (DECL_NAME (current_function_decl)
+      && MAIN_NAME_P (DECL_NAME (current_function_decl))
+      && DECL_FILE_SCOPE_P (current_function_decl))
+    expand_main_function ();
+
+  /* Initialize the stack_protect_guard field.  This must happen after the
+     call to __main (if any) so that the external decl is initialized.  */
+  if (cfun->stack_protect_guard)
+    stack_protect_prologue ();
+
   /* The following was moved from init_function_start.
      The move is supposed to make sdb output more accurate.  */
   /* Indicate the beginning of the function body,
Index: tree.h
===================================================================
--- tree.h	(revision 119115)
+++ tree.h	(working copy)
@@ -4354,7 +4354,6 @@ extern bool fields_compatible_p (tree, t
 extern tree find_compatible_field (tree, tree);
 
 /* In function.c */
-extern void expand_main_function (void);
 extern void init_dummy_function_start (void);
 extern void expand_dummy_function_end (void);
 extern unsigned int init_function_for_compilation (void);
Index: sched-deps.c
===================================================================
--- sched-deps.c	(revision 119115)
+++ sched-deps.c	(working copy)
@@ -1457,6 +1457,7 @@ void
 sched_analyze (struct deps *deps, rtx head, rtx tail)
 {
   rtx insn;
+  rtx reg_note = NULL_RTX;
 
   if (current_sched_info->use_cselib)
     cselib_init (true);
@@ -1491,6 +1492,12 @@ sched_analyze (struct deps *deps, rtx he
 		  = alloc_INSN_LIST (insn, deps->last_pending_memory_flush);
 	    }
 	  sched_analyze_insn (deps, PATTERN (insn), insn);
+	  if (reg_note)
+	    {
+	      XEXP (reg_note, 1) = REG_NOTES (insn);
+	      REG_NOTES (insn) = reg_note;
+	      reg_note = NULL_RTX;
+	    }
 	}
       else if (CALL_P (insn))
 	{
@@ -1545,6 +1552,12 @@ sched_analyze (struct deps *deps, rtx he
 					REG_DEP_ANTI);
 
 	  sched_analyze_insn (deps, PATTERN (insn), insn);
+	  if (reg_note)
+	    {
+	      XEXP (reg_note, 1) = REG_NOTES (insn);
+	      REG_NOTES (insn) = reg_note;
+	      reg_note = NULL_RTX;
+	    }
 
 	  /* In the absence of interprocedural alias analysis, we must flush
 	     all pending reads and writes, and start new dependencies starting
@@ -1568,6 +1581,15 @@ sched_analyze (struct deps *deps, rtx he
 	gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
 		    && NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_END);
 
+      if (NOTE_P (insn)
+          && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG
+              || NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END))
+        {
+          reg_note = alloc_EXPR_LIST (REG_SAVE_NOTE,
+                        GEN_INT (NOTE_LINE_NUMBER (insn)),
+                        reg_note);
+        }
+
       if (current_sched_info->use_cselib)
 	cselib_process_insn (insn);
 
Index: haifa-sched.c
===================================================================
--- haifa-sched.c	(revision 119115)
+++ haifa-sched.c	(working copy)
@@ -511,7 +511,7 @@ static void advance_one_cycle (void);
    Generally, NOTES are saved before scheduling and restored after scheduling.
    The scheduler distinguishes between three types of notes:
 
-   (1) LOOP_BEGIN, LOOP_END, SETJMP, EHREGION_BEG, EHREGION_END notes:
+   (1) NOTE_INSN_FUNCTION_BEG, NOTE_INSN_FUNCTION_BEG notes:
    Before scheduling a region, a pointer to the note is added to the insn
    that follows or precedes it.  (This happens as part of the data dependence
    computation).  After scheduling an insn, the pointer contained in it is
@@ -1254,7 +1254,9 @@ unlink_other_notes (rtx insn, rtx tail)
 
       /* See sched_analyze to see how these are handled.  */
       if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
-	  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_END)
+	  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_END
+	  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG
+	  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)
 	{
 	  /* Insert the note at the end of the notes list.  */
 	  PREV_INSN (insn) = note_list;
@@ -1775,11 +1777,9 @@ debug_ready_list (struct ready_list *rea
   fprintf (sched_dump, "\n");
 }
 
-/* Search INSN for REG_SAVE_NOTE note pairs for
-   NOTE_INSN_EHREGION_{BEG,END}; and convert them back into
-   NOTEs.  The REG_SAVE_NOTE note following first one is contains the
-   saved value for NOTE_BLOCK_NUMBER which is useful for
-   NOTE_INSN_EH_REGION_{BEG,END} NOTEs.  */
+/* Search INSN for REG_SAVE_NOTE notes for
+   NOTE_INSN_FUNCTION_{BEG,END}; and convert them back into
+   NOTEs.  */
 
 static void
 reemit_notes (rtx insn)
Index: final.c
===================================================================
--- final.c	(revision 119115)
+++ final.c	(working copy)
@@ -1697,9 +1697,7 @@ final_scan_insn (rtx insn, FILE *file, i
       switch (NOTE_LINE_NUMBER (insn))
 	{
 	case NOTE_INSN_DELETED:
-	case NOTE_INSN_FUNCTION_END:
 	  break;
-
 	case NOTE_INSN_SWITCH_TEXT_SECTIONS:
 	  in_cold_section_p = !in_cold_section_p;
 	  (*debug_hooks->switch_text_section) ();
@@ -1739,6 +1737,9 @@ final_scan_insn (rtx insn, FILE *file, i
 	  targetm.asm_out.function_end_prologue (file);
 	  profile_after_prologue (file);
 
+	  if (flag_debug_asm)
+	    fprintf (asm_out_file, "\t%s prologue end\n", ASM_COMMENT_START);
+
 	  if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
 	    {
 	      *seen |= SEEN_EMITTED;
@@ -1751,12 +1752,17 @@ final_scan_insn (rtx insn, FILE *file, i
 
 	case NOTE_INSN_EPILOGUE_BEG:
 	  targetm.asm_out.function_begin_epilogue (file);
+	  if (flag_debug_asm)
+	    fprintf (asm_out_file, "\t%s epilogue beg\n", ASM_COMMENT_START);
 	  break;
 
 	case NOTE_INSN_FUNCTION_BEG:
 	  app_disable ();
 	  (*debug_hooks->end_prologue) (last_linenum, last_filename);
 
+	  if (flag_debug_asm)
+	    fprintf (asm_out_file, "\t%s function beg\n", ASM_COMMENT_START);
+
 	  if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
 	    {
 	      *seen |= SEEN_EMITTED;
@@ -1767,7 +1773,15 @@ final_scan_insn (rtx insn, FILE *file, i
 
 	  break;
 
+	case NOTE_INSN_FUNCTION_END:
+	  if (flag_debug_asm)
+	    fprintf (asm_out_file, "\t%s function end\n", ASM_COMMENT_START);
+	  break;
+
 	case NOTE_INSN_BLOCK_BEG:
+        if (flag_debug_asm)
+            fprintf (asm_out_file, "\t%s insn block beg\n", ASM_COMMENT_START);
+
 	  if (debug_info_level == DINFO_LEVEL_NORMAL
 	      || debug_info_level == DINFO_LEVEL_VERBOSE
 	      || write_symbols == DWARF2_DEBUG
@@ -1789,6 +1803,8 @@ final_scan_insn (rtx insn, FILE *file, i
 	  break;
 
 	case NOTE_INSN_BLOCK_END:
+        if (flag_debug_asm)
+            fprintf (asm_out_file, "\t%s insn block end\n", ASM_COMMENT_START);
 	  if (debug_info_level == DINFO_LEVEL_NORMAL
 	      || debug_info_level == DINFO_LEVEL_VERBOSE
 	      || write_symbols == DWARF2_DEBUG

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]