I may be missing an obvious workaround, but it seems we currently emit
a #line directive when including lines from machine description files
in C files, but never emit a second directive when switching back to
the generated C file. This makes stepping through the backend in gdb
somewhat painful, because gdb thinks it should display lines from the
md file even after leaving the included fragment.

The attached patch is a proof of concept which unconditionally emits a
line containing "/* #unline */" after such fragments, and runs all
generated C files through a trivial filter which replaces those lines
by #line directives pointing back to the original file. It appears to
work.
From c1c85da2b5d029b730f98906abda6c73bb7352d3 Mon Sep 17 00:00:00 2001
From: Pip Cet <pip...@gmail.com>
Date: Thu, 27 Aug 2020 22:02:40 +0000
Subject: [PATCH] Add paired #line directives pointing back to the generated C
 file.

---
 gcc/Makefile.in | 15 ++++++++-------
 gcc/genemit.c   |  1 +
 gcc/genline.c   | 36 ++++++++++++++++++++++++++++++++++++
 gcc/read-md.c   | 19 +++++++++++++++++++
 gcc/read-md.h   |  2 ++
 5 files changed, 66 insertions(+), 7 deletions(-)
 create mode 100644 gcc/genline.c

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 79e854aa938..fb03031d038 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2354,16 +2354,16 @@ $(simple_rtl_generated_c:insn-%.c=s-%): s-%: insn-conditions.md
 
 $(simple_generated_h): insn-%.h: s-%; @true
 
-$(simple_generated_h:insn-%.h=s-%): s-%: build/gen%$(build_exeext)
+$(simple_generated_h:insn-%.h=s-%): s-%: build/gen%$(build_exeext) build/genline$(build_exeext)
 	$(RUN_GEN) build/gen$*$(build_exeext) $(md_file) \
-	  $(filter insn-conditions.md,$^) > tmp-$*.h
+	  $(filter insn-conditions.md,$^) | $(RUN_GEN) build/genline insn-$*.h > tmp-$*.h
 	$(SHELL) $(srcdir)/../move-if-change tmp-$*.h insn-$*.h
 	$(STAMP) s-$*
 
 $(simple_generated_c): insn-%.c: s-%; @true
-$(simple_generated_c:insn-%.c=s-%): s-%: build/gen%$(build_exeext)
+$(simple_generated_c:insn-%.c=s-%): s-%: build/gen%$(build_exeext) build/genline
 	$(RUN_GEN) build/gen$*$(build_exeext) $(md_file) \
-	  $(filter insn-conditions.md,$^) > tmp-$*.c
+	  $(filter insn-conditions.md,$^) | $(RUN_GEN) build/genline insn-$*.c > tmp-$*.c
 	$(SHELL) $(srcdir)/../move-if-change tmp-$*.c insn-$*.c
 	$(STAMP) s-$*
 
@@ -2397,8 +2397,8 @@ s-opinit: $(MD_DEPS) build/genopinit$(build_exeext) insn-conditions.md
 
 # gencondmd doesn't use the standard naming convention.
 build/gencondmd.c: s-conditions; @true
-s-conditions: $(MD_DEPS) build/genconditions$(build_exeext)
-	$(RUN_GEN) build/genconditions$(build_exeext) $(md_file) > tmp-condmd.c
+s-conditions: $(MD_DEPS) build/genconditions$(build_exeext) build/genline$(build_exeext)
+	$(RUN_GEN) build/genconditions$(build_exeext) $(md_file) | $(RUN_GEN) build/genline$(build_exeext) gencondmd.c > tmp-condmd.c
 	$(SHELL) $(srcdir)/../move-if-change tmp-condmd.c build/gencondmd.c
 	$(STAMP) s-conditions
 
@@ -2783,6 +2783,7 @@ build/genextract.o : genextract.c $(RTL_BASE_H) $(BCONFIG_H)		\
   $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
 build/genflags.o : genflags.c $(RTL_BASE_H) $(OBSTACK_H) $(BCONFIG_H)	\
   $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+build/genline.o : genline.c
 build/gentarget-def.o : gentarget-def.c $(BCONFIG_H) $(SYSTEM_H)	\
   $(CORETYPES_H) $(GTM_H) $(RTL_BASE_H) errors.h $(READ_MD_H)		\
   $(GENSUPPORT_H) $(HASH_TABLE_H) target-insns.def
@@ -2867,7 +2868,7 @@ genprogerr = $(genprogmd) genrtl modes gtype hooks cfn-macros condmd
 $(genprogerr:%=build/gen%$(build_exeext)): $(BUILD_ERRORS)
 
 # Remaining build programs.
-genprog = $(genprogerr) check checksum match
+genprog = $(genprogerr) check checksum line match
 
 # These programs need libs over and above what they get from the above list.
 build/genautomata$(build_exeext) : BUILD_LIBS += -lm
diff --git a/gcc/genemit.c b/gcc/genemit.c
index 84d07d388ee..5e4b82fe3de 100644
--- a/gcc/genemit.c
+++ b/gcc/genemit.c
@@ -310,6 +310,7 @@ emit_c_code (const char *code, bool can_fail_p, const char *name)
 
   rtx_reader_ptr->print_md_ptr_loc (code);
   printf ("%s\n", code);
+  rtx_reader_ptr->print_md_ptr_unloc (code);
 
   printf ("#undef DONE\n");
   printf ("#undef FAIL\n");
diff --git a/gcc/genline.c b/gcc/genline.c
new file mode 100644
index 00000000000..49ecf27a76c
--- /dev/null
+++ b/gcc/genline.c
@@ -0,0 +1,36 @@
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+  if (argc < 2)
+    return -1;
+
+  const char *state = "/* #unline */\n";
+  const char *p = state;
+  int line = 1;
+
+  int c;
+  do
+    {
+      c = getchar ();
+      if (c == '\n')
+	line++;
+      if (!*p)
+	{
+	  printf ("#line %d \"%s\"\n", line, argv[1]);
+	  p = state;
+	}
+      if (*p == c)
+	p++;
+      else
+	{
+	  printf ("%.*s", (int)(p - state), state);
+	  p = state;
+	  if (c != EOF)
+	    putchar (c);
+	}
+    }
+  while (c != EOF);
+
+  return 0;
+}
diff --git a/gcc/read-md.c b/gcc/read-md.c
index 40690a86dbc..c935d152b80 100644
--- a/gcc/read-md.c
+++ b/gcc/read-md.c
@@ -137,6 +137,24 @@ md_reader::print_md_ptr_loc (const void *ptr)
   fprint_md_ptr_loc (stdout, ptr);
 }
 
+/* If PTR is associated with a known file position, print an #unline
+   comment to OUTF.  */
+
+void
+md_reader::fprint_md_ptr_unloc (FILE *outf, const void *ptr)
+{
+  const struct ptr_loc *loc = get_md_ptr_loc (ptr);
+  if (loc != 0)
+    fprintf (outf, "\n/* #unline */\n");
+}
+
+/* Special fprint_md_ptr_unloc for writing to STDOUT.  */
+void
+md_reader::print_md_ptr_unloc (const void *ptr)
+{
+  fprint_md_ptr_unloc (stdout, ptr);
+}
+
 /* Return a condition that satisfies both COND1 and COND2.  Either string
    may be null or empty.  */
 
@@ -186,6 +204,7 @@ md_reader::fprint_c_condition (FILE *outf, const char *cond)
       fputc ('\n', outf);
       fprint_md_ptr_loc (outf, cond);
       fprintf (outf, "(%s)", cond);
+      fprint_md_ptr_unloc (outf, cond);
     }
 }
 
diff --git a/gcc/read-md.h b/gcc/read-md.h
index b43afb9be86..937b1697d24 100644
--- a/gcc/read-md.h
+++ b/gcc/read-md.h
@@ -195,6 +195,8 @@ class md_reader
   void copy_md_ptr_loc (const void *new_ptr, const void *old_ptr);
   void fprint_md_ptr_loc (FILE *outf, const void *ptr);
   void print_md_ptr_loc (const void *ptr);
+  void fprint_md_ptr_unloc (FILE *outf, const void *ptr);
+  void print_md_ptr_unloc (const void *ptr);
 
   struct enum_type *lookup_enum_type (const char *name);
   void traverse_enum_types (htab_trav callback, void *info);
-- 
2.28.0

Reply via email to