[patch] Set is_stmt flag to 0 in DWARF line number table for discriminators

Cary Coutant ccoutant@google.com
Wed Jun 17 22:38:00 GMT 2009


This is a followup to the patch I checked in recently to add
discriminators to the DWARF line number table:

  http://gcc.gnu.org/ml/gcc-patches/2009-06/msg00443.html

That patch caused a couple of gdb testsuite regressions because of
extra rows in the line number table that would not have been there
otherwise. The effect was that gdb would occasionally set extra
breakpoints or stop at unexpected places when single stepping because
of those extra rows. The solution is to mark the new rows with the
is_stmt flag set to 0, and to teach gdb to ignore any rows where
is_stmt == 0. This patch does the first part; I've submitted a patch
for the second part to the gdb-patches mailing list:

  http://sourceware.org/ml/gdb-patches/2009-06/msg00406.html

While I was at it, I converted the conditional compilation using
#ifdef HAVE_GAS_DISCRIMINATOR into a runtime test on
SUPPORTS_DISCRIMINATOR, to make things look a bit cleaner (as
suggested offline by Ian).

Bootstrapped and tested on x86_64-unknown-linux-gnu. Also tested with
the gdb testsuite, where it (with the gdb patch) fixes all regressions
that were caused by my original discriminator patch.

OK for trunk?

-cary


	* dbxout.c (dbxout_source_line): Add is_stmt parameter.
	Change caller.
	* debug.c (struct gcc_debug_hooks): Change placeholder for
	source_line hook.
	(debug_nothing_int_charstar_int): Replaced by...
	(debug_nothing_int_charstar_int_bool): ...this.
	* debug.h (struct gcc_debug_hooks): Add is_stmt parameter to
	source_line prototype.
	(debug_nothing_int_charstar_int): Replaced by...
	(debug_nothing_int_charstar_int_bool): ...this.
	* defaults.h (SUPPORTS_DISCRIMINATOR): New constant.
	* dwarf2out.c (dwarf2out_source_line): Add is_stmt parameter.
	Output is_stmt operand when necessary.
	* final.c (last_is_stmt): New variable.
	(final_start_function): Initialize last_is_stmt.
	(final_scan_insn): Pass is_stmt to source_line debug hook.
	(notice_source_line): Add is_stmt parameter.
	* sdbout.c (sdbout_source_line): Add is_stmt parameter.
	* vmsdbgout.c (vmsdbgout_source_line): Add is_stmt parameter.
	Change callers.
	* xcoffout.c (xcoffout_source_line): Add is_stmt parameter.
	* xcoffout.h (xcoffout_source_line): Add is_stmt parameter.
-------------- next part --------------
Index: dbxout.c
===================================================================
--- dbxout.c	(revision 148502)
+++ dbxout.c	(working copy)
@@ -333,7 +333,7 @@ static void dbxout_handle_pch (unsigned)
 /* The debug hooks structure.  */
 #if defined (DBX_DEBUGGING_INFO)
 
-static void dbxout_source_line (unsigned int, const char *, int);
+static void dbxout_source_line (unsigned int, const char *, int, bool);
 static void dbxout_begin_prologue (unsigned int, const char *);
 static void dbxout_source_file (const char *);
 static void dbxout_function_end (tree);
@@ -1265,7 +1265,7 @@ dbxout_begin_prologue (unsigned int line
   /* pre-increment the scope counter */
   scope_labelno++;
 
-  dbxout_source_line (lineno, filename, 0);
+  dbxout_source_line (lineno, filename, 0, true);
   /* Output function begin block at function scope, referenced 
      by dbxout_block, dbxout_source_line and dbxout_function_end.  */
   emit_pending_bincls_if_required ();
@@ -1277,7 +1277,8 @@ dbxout_begin_prologue (unsigned int line
 
 static void
 dbxout_source_line (unsigned int lineno, const char *filename,
-                    int discriminator ATTRIBUTE_UNUSED)
+                    int discriminator ATTRIBUTE_UNUSED,
+                    bool is_stmt ATTRIBUTE_UNUSED)
 {
   dbxout_source_file (filename);
 
Index: debug.c
===================================================================
--- debug.c	(revision 148502)
+++ debug.c	(working copy)
@@ -34,7 +34,7 @@ const struct gcc_debug_hooks do_nothing_
   debug_nothing_int_int,	         /* begin_block */
   debug_nothing_int_int,	         /* end_block */
   debug_true_const_tree,	         /* ignore_block */
-  debug_nothing_int_charstar_int,	 /* source_line */
+  debug_nothing_int_charstar_int_bool,	 /* source_line */
   debug_nothing_int_charstar,	         /* begin_prologue */
   debug_nothing_int_charstar,	         /* end_prologue */
   debug_nothing_int_charstar,	         /* end_epilogue */
@@ -104,9 +104,10 @@ debug_nothing_int_charstar (unsigned int
 }
 
 void
-debug_nothing_int_charstar_int (unsigned int line ATTRIBUTE_UNUSED,
-			        const char *text ATTRIBUTE_UNUSED,
-			        int discriminator ATTRIBUTE_UNUSED)
+debug_nothing_int_charstar_int_bool (unsigned int line ATTRIBUTE_UNUSED,
+			             const char *text ATTRIBUTE_UNUSED,
+			             int discriminator ATTRIBUTE_UNUSED,
+			             bool is_stmt ATTRIBUTE_UNUSED)
 {
 }
 
Index: debug.h
===================================================================
--- debug.h	(revision 148502)
+++ debug.h	(working copy)
@@ -61,11 +61,10 @@ struct gcc_debug_hooks
 
   /* Record a source file location at (FILE, LINE, DISCRIMINATOR).  */
   void (* source_line) (unsigned int line, const char *file,
-                        int discriminator);
+                        int discriminator, bool is_stmt);
 
   /* Called at start of prologue code.  LINE is the first line in the
-     function.  This has been given the same prototype as source_line,
-     so that the source_line hook can be substituted if appropriate.  */
+     function.  */
   void (* begin_prologue) (unsigned int line, const char *file);
 
   /* Called at end of prologue code.  LINE is the first line in the
@@ -142,7 +141,8 @@ extern const struct gcc_debug_hooks *deb
 extern void debug_nothing_void (void);
 extern void debug_nothing_charstar (const char *);
 extern void debug_nothing_int_charstar (unsigned int, const char *);
-extern void debug_nothing_int_charstar_int (unsigned int, const char *, int);
+extern void debug_nothing_int_charstar_int_bool (unsigned int, const char *,
+                                                 int, bool);
 extern void debug_nothing_int (unsigned int);
 extern void debug_nothing_int_int (unsigned int, unsigned int);
 extern void debug_nothing_tree (tree);
Index: defaults.h
===================================================================
--- defaults.h	(revision 148502)
+++ defaults.h	(working copy)
@@ -255,6 +255,16 @@ see the files COPYING3 and COPYING.RUNTI
 #endif
 #endif
 
+/* This determines whether or not we support the discriminator
+   attribute in the .loc directive.  */
+#ifndef SUPPORTS_DISCRIMINATOR
+#ifdef HAVE_GAS_DISCRIMINATOR
+#define SUPPORTS_DISCRIMINATOR 1
+#else
+#define SUPPORTS_DISCRIMINATOR 0
+#endif
+#endif
+
 /* This determines whether or not we support link-once semantics.  */
 #ifndef SUPPORTS_ONE_ONLY
 #ifdef MAKE_DECL_ONE_ONLY
Index: dwarf2out.c
===================================================================
--- dwarf2out.c	(revision 148502)
+++ dwarf2out.c	(working copy)
@@ -91,7 +91,7 @@ along with GCC; see the file COPYING3.  
 #include "input.h"
 
 #ifdef DWARF2_DEBUGGING_INFO
-static void dwarf2out_source_line (unsigned int, const char *, int);
+static void dwarf2out_source_line (unsigned int, const char *, int, bool);
 
 static rtx last_var_location_insn;
 #endif
@@ -3637,7 +3637,7 @@ dwarf2out_begin_prologue (unsigned int l
      prologue case, not the eh frame case.  */
 #ifdef DWARF2_DEBUGGING_INFO
   if (file)
-    dwarf2out_source_line (line, file, 0);
+    dwarf2out_source_line (line, file, 0, true);
 #endif
 
   if (dwarf2out_do_cfi_asm ())
@@ -16283,8 +16283,10 @@ dwarf2out_begin_function (tree fun)
 
 static void
 dwarf2out_source_line (unsigned int line, const char *filename,
-                       int discriminator ATTRIBUTE_UNUSED)
+                       int discriminator, bool is_stmt)
 {
+  static bool last_is_stmt = true;
+
   if (debug_info_level >= DINFO_LEVEL_NORMAL
       && line != 0)
     {
@@ -16301,10 +16303,13 @@ dwarf2out_source_line (unsigned int line
 	{
 	  /* Emit the .loc directive understood by GNU as.  */
 	  fprintf (asm_out_file, "\t.loc %d %d 0", file_num, line);
-#ifdef HAVE_GAS_DISCRIMINATOR
-	  if (discriminator != 0)
+	  if (is_stmt != last_is_stmt)
+	    {
+	      fprintf (asm_out_file, " is_stmt %d", is_stmt ? 1 : 0);
+	      last_is_stmt = is_stmt;
+	    }
+	  if (SUPPORTS_DISCRIMINATOR && discriminator != 0)
 	    fprintf (asm_out_file, " discriminator %d", discriminator);
-#endif /* HAVE_GAS_DISCRIMINATOR */
 	  fputc ('\n', asm_out_file);
 
 	  /* Indicate that line number info exists.  */
Index: final.c
===================================================================
--- final.c	(revision 148502)
+++ final.c	(working copy)
@@ -136,6 +136,9 @@ static int last_discriminator;
 /* Discriminator of current block.  */
 static int discriminator;
 
+/* Last is_stmt flag written to assembly (for line number table).  */
+static int last_is_stmt;
+
 /* Highest line number in current block.  */
 static int high_block_linenum;
 
@@ -213,7 +216,7 @@ static int asm_insn_count (rtx);
 #endif
 static void profile_function (FILE *);
 static void profile_after_prologue (FILE *);
-static bool notice_source_line (rtx);
+static bool notice_source_line (rtx, bool *);
 static rtx walk_alter_subreg (rtx *, bool *);
 static void output_asm_name (void);
 static void output_alternate_entry_point (FILE *, rtx);
@@ -1503,6 +1506,7 @@ final_start_function (rtx first ATTRIBUT
   last_filename = locator_file (prologue_locator);
   last_linenum = locator_line (prologue_locator);
   last_discriminator = discriminator = 0;
+  last_is_stmt = true;
 
   high_block_linenum = high_function_linenum = last_linenum;
 
@@ -2089,6 +2093,7 @@ final_scan_insn (rtx insn, FILE *file, i
 	rtx body = PATTERN (insn);
 	int insn_code_number;
 	const char *templ;
+	bool is_stmt;
 
 #ifdef HAVE_conditional_execution
 	/* Reset this early so it is correct for ASM statements.  */
@@ -2190,11 +2195,12 @@ final_scan_insn (rtx insn, FILE *file, i
 	  }
 	/* Output this line note if it is the first or the last line
 	   note in a row.  */
-	if (notice_source_line (insn))
+	if (notice_source_line (insn, &is_stmt))
 	  {
 	    (*debug_hooks->source_line) (last_linenum,
 	                                 last_filename,
-	                                 last_discriminator);
+	                                 last_discriminator,
+	                                 is_stmt);
 	  }
 
 	if (GET_CODE (body) == ASM_INPUT)
@@ -2698,10 +2704,12 @@ final_scan_insn (rtx insn, FILE *file, i
   return NEXT_INSN (insn);
 }
 

-/* Return whether a source line note needs to be emitted before INSN.  */
+/* Return whether a source line note needs to be emitted before INSN.
+   Sets IS_STMT to TRUE if the line should be marked as a possible
+   breakpoint location.  */
 
 static bool
-notice_source_line (rtx insn)
+notice_source_line (rtx insn, bool *is_stmt)
 {
   const char *filename;
   int linenum;
@@ -2717,20 +2725,33 @@ notice_source_line (rtx insn)
       linenum = insn_line (insn);
     }
 
-  if (filename
-      && (force_source_line
-	  || filename != last_filename
-	  || last_linenum != linenum
-	  || last_discriminator != discriminator))
+  if (filename == NULL)
+    return false;
+
+  if (force_source_line
+      || filename != last_filename
+      || last_linenum != linenum)
     {
       force_source_line = false;
       last_filename = filename;
       last_linenum = linenum;
       last_discriminator = discriminator;
+      *is_stmt = true;
       high_block_linenum = MAX (last_linenum, high_block_linenum);
       high_function_linenum = MAX (last_linenum, high_function_linenum);
       return true;
     }
+
+  if (SUPPORTS_DISCRIMINATOR && last_discriminator != discriminator)
+    {
+      /* If the discriminator changed, but the line number did not,
+         output the line table entry with is_stmt false so the
+         debugger does not treat this as a breakpoint location.  */
+      last_discriminator = discriminator;
+      *is_stmt = false;
+      return true;
+    }
+
   return false;
 }
 

Index: sdbout.c
===================================================================
--- sdbout.c	(revision 148502)
+++ sdbout.c	(working copy)
@@ -117,7 +117,7 @@ static void sdbout_start_source_file	(un
 static void sdbout_end_source_file	(unsigned int);
 static void sdbout_begin_block		(unsigned int, unsigned int);
 static void sdbout_end_block		(unsigned int, unsigned int);
-static void sdbout_source_line		(unsigned int, const char *, int);
+static void sdbout_source_line		(unsigned int, const char *, int, bool);
 static void sdbout_end_epilogue		(unsigned int, const char *);
 static void sdbout_global_decl		(tree);
 #ifndef MIPS_DEBUGGING_INFO
@@ -1542,7 +1542,8 @@ sdbout_end_block (unsigned int line, uns
 
 static void
 sdbout_source_line (unsigned int line, const char *filename ATTRIBUTE_UNUSED,
-                    int discriminator ATTRIBUTE_UNUSED)
+                    int discriminator ATTRIBUTE_UNUSED,
+                    bool is_stmt ATTRIBUTE_UNUSED)
 {
   /* COFF relative line numbers must be positive.  */
   if ((int) line > sdb_begin_function_line)
Index: vmsdbgout.c
===================================================================
--- vmsdbgout.c	(revision 148502)
+++ vmsdbgout.c	(working copy)
@@ -173,7 +173,7 @@ static void vmsdbgout_end_source_file (u
 static void vmsdbgout_begin_block (unsigned int, unsigned int);
 static void vmsdbgout_end_block (unsigned int, unsigned int);
 static bool vmsdbgout_ignore_block (const_tree);
-static void vmsdbgout_source_line (unsigned int, const char *, int);
+static void vmsdbgout_source_line (unsigned int, const char *, int, bool);
 static void vmsdbgout_begin_prologue (unsigned int, const char *);
 static void vmsdbgout_end_prologue (unsigned int, const char *);
 static void vmsdbgout_end_function (unsigned int);
@@ -1297,7 +1297,7 @@ vmsdbgout_end_prologue (unsigned int lin
       ASM_OUTPUT_LABEL (asm_out_file, label);
 
       /* VMS PCA expects every PC range to correlate to some line and file.  */
-      vmsdbgout_source_line (line, file, 0);
+      vmsdbgout_source_line (line, file, 0, true);
     }
 }
 
@@ -1331,7 +1331,7 @@ vmsdbgout_end_epilogue (unsigned int lin
       ASM_OUTPUT_LABEL (asm_out_file, label);
 
       /* VMS PCA expects every PC range to correlate to some line and file.  */
-      vmsdbgout_source_line (line, file, 0);
+      vmsdbgout_source_line (line, file, 0, true);
     }
 }
 
@@ -1534,10 +1534,10 @@ lookup_filename (const char *file_name)
 
 static void
 vmsdbgout_source_line (register unsigned line, register const char *filename,
-                       int discriminator)
+                       int discriminator, bool is_stmt)
 {
   if (write_symbols == VMS_AND_DWARF2_DEBUG)
-    (*dwarf2_debug_hooks.source_line) (line, filename, discriminator);
+    (*dwarf2_debug_hooks.source_line) (line, filename, discriminator, is_stmt);
 
   if (debug_info_level >= DINFO_LEVEL_TERSE)
     {
Index: xcoffout.c
===================================================================
--- xcoffout.c	(revision 148502)
+++ xcoffout.c	(working copy)
@@ -322,7 +322,8 @@ xcoffout_source_file (FILE *file, const 
 
 void
 xcoffout_source_line (unsigned int line, const char *filename,
-                      int discriminator ATTRIBUTE_UNUSED)
+                      int discriminator ATTRIBUTE_UNUSED,
+                      bool is_stmt ATTRIBUTE_UNUSED)
 {
   bool inline_p = (strcmp (xcoff_current_function_file, filename) != 0
 		   || (int) line < xcoff_begin_function_line);
Index: xcoffout.h
===================================================================
--- xcoffout.h	(revision 148502)
+++ xcoffout.h	(working copy)
@@ -182,4 +182,4 @@ extern void xcoffout_end_function (unsig
 extern void xcoffout_end_block (unsigned, unsigned);
 extern int xcoff_assign_fundamental_type_number (tree);
 extern void xcoffout_declare_function (FILE *, tree, const char *);
-extern void xcoffout_source_line (unsigned int, const char *, int);
+extern void xcoffout_source_line (unsigned int, const char *, int, bool);


More information about the Gcc-patches mailing list