From dc68369ee2ed1530474d173cde39aa6439e96944 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 2 May 2016 14:30:53 -0400
Subject: [PATCH 25/36] FIXME: use libcpp in rtl/md reader

---
 gcc/Makefile.in                           |  27 +++---
 gcc/errors.h                              |  13 ---
 gcc/genattrtab.c                          |  13 +--
 gcc/genconstants.c                        |   4 +-
 gcc/genemit.c                             |  28 +++++--
 gcc/genenums.c                            |   4 +-
 gcc/genmddeps.c                           |   4 +-
 gcc/genoutput.c                           |   6 +-
 gcc/gensupport.c                          |   8 +-
 gcc/read-md.c                             | 132 ++++++++++++++++++++++++++++--
 gcc/read-md.h                             |  22 ++++-
 gcc/read-rtl-function.c                   |  21 +++--
 gcc/read-rtl.c                            |  11 ++-
 gcc/rtl/rtl-errors.c                      |   5 +-
 gcc/testsuite/rtl.dg/bad-include.rtl      |   5 ++
 gcc/testsuite/rtl.dg/bad-includee.md      |   5 ++
 gcc/testsuite/rtl.dg/missing-include.rtl  |   4 +
 gcc/testsuite/rtl.dg/unknown-insn-uid.rtl |   8 ++
 gcc/testsuite/rtl.dg/unknown-rtx-code.rtl |   4 +
 19 files changed, 257 insertions(+), 67 deletions(-)
 create mode 100644 gcc/testsuite/rtl.dg/bad-include.rtl
 create mode 100644 gcc/testsuite/rtl.dg/bad-includee.md

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 0382b62..a8e0a6f 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1059,7 +1059,7 @@ LDEXP_LIB = @LDEXP_LIB@
 
 # Likewise, for use in the tools that must run on this machine
 # even if we are cross-building GCC.
-BUILD_LIBS = $(BUILD_LIBIBERTY)
+BUILD_LIBS = $(BUILD_CPPLIB) $(BUILD_LIBIBERTY)
 
 BUILD_RTL = build/rtl.o build/read-rtl.o build/ggc-none.o \
 	    build/vec.o build/min-insn-modes.o build/gensupport.o \
@@ -2657,29 +2657,32 @@ build/gengtype.o: $(BCONFIG_H)
 CFLAGS-errors.o += -DHOST_GENERATOR_FILE
 
 build/genmddeps.o: genmddeps.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h	\
-  errors.h $(READ_MD_H)
+  errors.h $(READ_MD_H) $(BUILD_CPPLIB)
 build/genmodes.o : genmodes.c $(BCONFIG_H) $(SYSTEM_H) errors.h		\
-  $(HASHTAB_H) machmode.def $(extra_modes_file)
+  $(HASHTAB_H) machmode.def $(extra_modes_file) $(BUILD_CPPLIB)
 build/genopinit.o : genopinit.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)	\
-  coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H) optabs.def
+  coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H) optabs.def $(BUILD_CPPLIB)
 build/genoutput.o : genoutput.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)	\
-  coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+  coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) $(BUILD_CPPLIB)
 build/genpeep.o : genpeep.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)	\
-  coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H) toplev.h $(DIAGNOSTIC_CORE_H)
+  coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H) toplev.h $(DIAGNOSTIC_CORE_H) \
+  $(BUILD_CPPLIB)
 build/genpreds.o : genpreds.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)	\
-  coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) $(OBSTACK_H)
+  coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) $(OBSTACK_H) \
+  $(BUILD_CPPLIB)
 build/genrecog.o : genrecog.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)	\
   coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)		\
-  $(HASH_TABLE_H) inchash.h
+  $(HASH_TABLE_H) inchash.h $(BUILD_CPPLIB)
 build/genhooks.o : genhooks.c $(TARGET_DEF) $(C_TARGET_DEF)		\
-  $(COMMON_TARGET_DEF) $(BCONFIG_H) $(SYSTEM_H) errors.h
+  $(COMMON_TARGET_DEF) $(BCONFIG_H) $(SYSTEM_H) errors.h $(BUILD_CPPLIB)
 build/genmddump.o : genmddump.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)	\
-  coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+  coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) $(BUILD_CPPLIB)
 build/genmatch.o : genmatch.c $(BCONFIG_H) $(SYSTEM_H) \
   coretypes.h errors.h $(HASH_TABLE_H) hash-map.h $(GGC_H) is-a.h \
-  tree.def builtins.def internal-fn.def
+  tree.def builtins.def internal-fn.def $(BUILD_CPPLIB)
 build/gencfn-macros.o : gencfn-macros.c $(BCONFIG_H) $(SYSTEM_H)	\
-  coretypes.h errors.h $(HASH_TABLE_H) hash-set.h builtins.def internal-fn.def
+  coretypes.h errors.h $(HASH_TABLE_H) hash-set.h builtins.def internal-fn.def \
+  $(BUILD_CPPLIB)
 
 # Compile the programs that generate insn-* from the machine description.
 # They are compiled with $(COMPILER_FOR_BUILD), and associated libraries,
diff --git a/gcc/errors.h b/gcc/errors.h
index c63f06b..a6973f3 100644
--- a/gcc/errors.h
+++ b/gcc/errors.h
@@ -28,21 +28,8 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ERRORS_H
 #define GCC_ERRORS_H
 
-/* Records a position in the file.  */
-struct file_location {
-  file_location () {}
-  file_location (const char *, int);
-
-  const char *filename;
-  int lineno;
-};
-
-inline file_location::file_location (const char *filename_in, int lineno_in)
-  : filename (filename_in), lineno (lineno_in) {}
-
 extern void warning (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
 extern void error (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
-extern void error_at (file_location, const char *, ...) ATTRIBUTE_PRINTF_2 ATTRIBUTE_COLD;
 extern void fatal (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
 extern void internal_error (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
 extern const char *trim_filename (const char *);
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index 1668e71..1fe3742 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -4252,9 +4252,12 @@ write_insn_cases (FILE *outf, struct insn_ent *ie, int indent)
       {
 	write_indent (outf, indent);
 	if (GET_CODE (ie->def->def) == DEFINE_PEEPHOLE)
-	  fprintf (outf, "case %d:  /* define_peephole, %s:%d */\n",
-		   ie->def->insn_code, ie->def->loc.filename,
-		   ie->def->loc.lineno);
+	  {
+	    expanded_location xloc
+	      = linemap_client_expand_location_to_spelling_point (ie->def->loc);
+	    fprintf (outf, "case %d:  /* define_peephole, %s:%d */\n",
+		     ie->def->insn_code, xloc.file, xloc.line);
+	  }
 	else
 	  fprintf (outf, "case %d:  /* %s */\n",
 		   ie->def->insn_code, XSTR (ie->def->def, 0));
@@ -4655,7 +4658,7 @@ make_internal_attr (const char *name, rtx value, int special)
   attr->is_numeric = 1;
   attr->is_const = 0;
   attr->is_special = (special & ATTR_SPECIAL) != 0;
-  attr->default_val = get_attr_value (file_location ("<internal>", 0),
+  attr->default_val = get_attr_value (GENERATOR_BUILTINS_LOCATION,
 				      value, attr, -2);
 }
 
@@ -5277,7 +5280,7 @@ main (int argc, const char **argv)
       md_rtx_info info;
       info.def = rtx_alloc (DEFINE_ASM_ATTRIBUTES);
       XVEC (info.def, 0) = rtvec_alloc (0);
-      info.loc = file_location ("<internal>", 0);
+      info.loc = GENERATOR_BUILTINS_LOCATION;
       info.index = -1;
       gen_insn (&info);
     }
diff --git a/gcc/genconstants.c b/gcc/genconstants.c
index e8be5b6..c785d31 100644
--- a/gcc/genconstants.c
+++ b/gcc/genconstants.c
@@ -79,7 +79,9 @@ main (int argc, const char **argv)
 {
   progname = "genconstants";
 
-  noop_reader reader;
+  line_maps line_table;
+  generator_linemap_init (&line_table);
+  noop_reader reader (&line_table);
   if (!reader.read_md_files (argc, argv, NULL))
     return (FATAL_EXIT_CODE);
 
diff --git a/gcc/genemit.c b/gcc/genemit.c
index 33040aa..d28e2e2 100644
--- a/gcc/genemit.c
+++ b/gcc/genemit.c
@@ -397,7 +397,9 @@ gen_insn (md_rtx_info *info)
   if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*')
     return;
 
-  printf ("/* %s:%d */\n", info->loc.filename, info->loc.lineno);
+  expanded_location xloc
+    = linemap_client_expand_location_to_spelling_point (info->loc);
+  printf ("/* %s:%d */\n", xloc.file, xloc.line);
 
   /* Find out how many operands this function has.  */
   get_pattern_stats (&stats, XVEC (insn, 1));
@@ -808,18 +810,30 @@ from the machine description file `md'.  */\n\n");
 	break;
 
       case DEFINE_EXPAND:
-	printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno);
-	gen_expand (&info);
+	{
+	  expanded_location xloc
+	    = linemap_client_expand_location_to_spelling_point (info.loc);
+	  printf ("/* %s:%d */\n", xloc.file, xloc.line);
+	  gen_expand (&info);
+	}
 	break;
 
       case DEFINE_SPLIT:
-	printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno);
-	gen_split (&info);
+	{
+	  expanded_location xloc
+	    = linemap_client_expand_location_to_spelling_point (info.loc);
+	  printf ("/* %s:%d */\n", xloc.file, xloc.line);
+	  gen_split (&info);
+	}
 	break;
 
       case DEFINE_PEEPHOLE2:
-	printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno);
-	gen_split (&info);
+	{
+	  expanded_location xloc
+	    = linemap_client_expand_location_to_spelling_point (info.loc);
+	  printf ("/* %s:%d */\n", xloc.file, xloc.line);
+	  gen_split (&info);
+	}
 	break;
 
       default:
diff --git a/gcc/genenums.c b/gcc/genenums.c
index 8af8d9a..22f8110 100644
--- a/gcc/genenums.c
+++ b/gcc/genenums.c
@@ -49,7 +49,9 @@ main (int argc, const char **argv)
 {
   progname = "genenums";
 
-  noop_reader reader;
+  line_maps line_table;
+  generator_linemap_init (&line_table);
+  noop_reader reader (&line_table);
   if (!reader.read_md_files (argc, argv, NULL))
     return (FATAL_EXIT_CODE);
 
diff --git a/gcc/genmddeps.c b/gcc/genmddeps.c
index e3d229d..9b5eafc 100644
--- a/gcc/genmddeps.c
+++ b/gcc/genmddeps.c
@@ -47,7 +47,9 @@ main (int argc, const char **argv)
   progname = "genmddeps";
   include_callback = add_filedep;
 
-  noop_reader reader;
+  line_maps line_table;
+  generator_linemap_init (&line_table);
+  noop_reader reader (&line_table);
   if (!reader.read_md_files (argc, argv, NULL))
     return FATAL_EXIT_CODE;
 
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index f8c25ac..3241115 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -292,7 +292,9 @@ output_insn_data (void)
 
   for (d = idata; d; d = d->next)
     {
-      printf ("  /* %s:%d */\n", d->loc.filename, d->loc.lineno);
+      expanded_location xloc
+	= linemap_client_expand_location_to_spelling_point (d->loc);
+      printf ("  /* %s:%d */\n", xloc.file, xloc.line);
       printf ("  {\n");
 
       if (d->name)
@@ -979,7 +981,7 @@ init_insn_for_nothing (void)
   idata = XCNEW (struct data);
   new (idata) data ();
   idata->name = "*placeholder_for_nothing";
-  idata->loc = file_location ("<internal>", 0);
+  idata->loc = GENERATOR_BUILTINS_LOCATION;
   idata_end = &idata->next;
 }
 
diff --git a/gcc/gensupport.c b/gcc/gensupport.c
index 378e0bf..16fa3ff 100644
--- a/gcc/gensupport.c
+++ b/gcc/gensupport.c
@@ -446,7 +446,7 @@ add_define_attr (const char *name)
   XEXP (t1, 2) = rtx_alloc (CONST_STRING);
   XSTR (XEXP (t1, 2), 0) = "yes";
   e->data = t1;
-  e->loc = file_location ("built-in", -1);
+  e->loc = GENERATOR_BUILTINS_LOCATION;
   e->next = define_attr_queue;
   define_attr_queue = e;
 
@@ -2234,7 +2234,7 @@ process_define_subst (void)
 class gen_reader : public rtx_reader
 {
  public:
-  gen_reader () : rtx_reader (NULL) {}
+  gen_reader (line_maps *line_table) : rtx_reader (line_table, NULL) {}
   void handle_unknown_directive (file_location, const char *);
 };
 
@@ -2526,7 +2526,9 @@ init_rtx_reader_args_cb (int argc, const char **argv,
   split_sequence_num = 1;
   peephole2_sequence_num = 1;
 
-  gen_reader *reader = new gen_reader ();
+  line_maps *line_table = XCNEW (struct line_maps);
+  generator_linemap_init (line_table);
+  gen_reader *reader = new gen_reader (line_table);
   reader->read_md_files (argc, argv, parse_opt);
 
   if (define_attr_queue != NULL)
diff --git a/gcc/read-md.c b/gcc/read-md.c
index 8051774..a7f6a9c 100644
--- a/gcc/read-md.c
+++ b/gcc/read-md.c
@@ -22,6 +22,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "errors.h"
 #include "read-md.h"
+#ifndef GENERATOR_FILE
+#include "diagnostic.h"
+#endif
 
 /* Associates PTR (which can be a string, etc.) with the file location
    specified by FILENAME and LINENO.  */
@@ -220,7 +223,9 @@ print_c_condition (const char *cond)
 static void ATTRIBUTE_PRINTF(2,0)
 message_at_1 (file_location loc, const char *msg, va_list ap)
 {
-  fprintf (stderr, "%s:%d: ", loc.filename, loc.lineno);
+  expanded_location xloc
+    = linemap_client_expand_location_to_spelling_point (loc);
+  fprintf (stderr, "%s:%d: ", xloc.file, xloc.line);
   vfprintf (stderr, msg, ap);
   fputc ('\n', stderr);
 }
@@ -239,6 +244,8 @@ message_at (file_location loc, const char *msg, ...)
 
 /* Like message_at, but treat the condition as an error.  */
 
+#ifdef GENERATOR_FILE
+
 void
 error_at (file_location loc, const char *msg, ...)
 {
@@ -250,6 +257,8 @@ error_at (file_location loc, const char *msg, ...)
   have_error = 1;
 }
 
+#endif /* #ifdef GENERATOR_FILE */
+
 /* Like message_at, but treat the condition as a fatal error.  */
 
 void
@@ -269,6 +278,7 @@ fatal_at (file_location loc, const char *msg, ...)
 void
 fatal_with_file_and_line (const char *msg, ...)
 {
+#ifdef GENERATOR_FILE
   char context[64];
   size_t i;
   int c;
@@ -276,7 +286,7 @@ fatal_with_file_and_line (const char *msg, ...)
 
   va_start (ap, msg);
 
-  fprintf (stderr, "%s:%d: error: ", rtx_reader_ptr->get_filename (),
+  fprintf (stderr, "%s:%d: ", rtx_reader_ptr->get_filename (),
 	   rtx_reader_ptr->get_lineno ());
   vfprintf (stderr, msg, ap);
   putc ('\n', stderr);
@@ -296,11 +306,22 @@ fatal_with_file_and_line (const char *msg, ...)
     }
   context[i] = '\0';
 
-  fprintf (stderr, "%s:%d: note: following context is `%s'\n",
+  fprintf (stderr, "%s:%d: following context is `%s'\n",
 	   rtx_reader_ptr->get_filename (), rtx_reader_ptr->get_lineno (),
 	   context);
 
   va_end (ap);
+#else /* #ifdef GENERATOR_FILE */
+  diagnostic_info diagnostic;
+  va_list ap;
+  file_location loc = rtx_reader_ptr->get_current_location ();
+  rich_location richloc (line_table, loc);
+  va_start (ap, msg);
+  diagnostic_set_info (&diagnostic, msg, &ap, &richloc, DK_ERROR);
+  report_diagnostic (&diagnostic);
+  va_end (ap);
+#endif  /* #else of #ifdef GENERATOR_FILE */
+
   exit (1);
 }
 
@@ -406,6 +427,22 @@ void require_word_ws (const char *expected)
     fatal_with_file_and_line ("missing '%s'", expected);
 }
 
+/* FIXME.  */
+
+file_location
+rtx_reader::make_location (file_location caret, file_location start,
+			   file_location finish) const
+{
+  source_range src_range;
+  src_range.m_start = start;
+  src_range.m_finish = finish;
+  file_location combined_loc = COMBINE_LOCATION_DATA (m_line_table,
+						      caret,
+						      src_range,
+						      NULL);
+  return combined_loc;
+}
+
 /* Read the next character from the file.  */
 
 int
@@ -422,7 +459,9 @@ rtx_reader::read_char (void)
   else
     m_read_md_colno++;
 
+
   LOG_SCOPE1 ("read_char: '%c'", ch);
+  update_location (true);
 
   return ch;
 }
@@ -432,10 +471,12 @@ rtx_reader::read_char (void)
 void
 rtx_reader::unread_char (int ch)
 {
+  /* FIXME: what about colno when unreading a '\n'? */
   if (ch == '\n')
     m_read_md_lineno--;
   else
     m_read_md_colno--;
+  update_location (false);
   ungetc (ch, m_read_md_file);
 
   LOG_SCOPE1 ("unread_char: '%c'", ch);
@@ -466,6 +507,8 @@ read_name_1 (struct md_name *name, file_location *out_loc)
 
   c = read_skip_spaces ();
 
+  file_location start = rtx_reader_ptr->get_current_location ();
+
   i = 0;
   angle_bracket_depth = 0;
   while (1)
@@ -497,8 +540,9 @@ read_name_1 (struct md_name *name, file_location *out_loc)
     }
 
   unread_char (c);
-  *out_loc = rtx_reader_ptr->get_current_location ();
+  file_location end = rtx_reader_ptr->get_current_location ();
   read_char ();
+  *out_loc = rtx_reader_ptr->make_location (start, start, end);
 
   if (i == 0)
     return false;
@@ -1014,11 +1058,16 @@ traverse_enum_types (htab_trav callback, void *info)
   htab_traverse (enum_types, callback, info);
 }
 
+/* FIXME.  */
+
+static line_maps *rtx_reader_line_table;
 
 /* Constructor for rtx_reader.  */
 
-rtx_reader::rtx_reader (rtl_reader_policy *policy)
-: m_toplevel_fname (NULL),
+rtx_reader::rtx_reader (line_maps *line_table, rtl_reader_policy *policy)
+: m_line_table (line_table),
+  m_current_linemap (NULL),
+  m_toplevel_fname (NULL),
   m_read_md_filename (NULL),
   m_read_md_lineno (0),
   m_read_md_colno (0),
@@ -1027,6 +1076,8 @@ rtx_reader::rtx_reader (rtl_reader_policy *policy)
   m_policy (policy),
   m_log_indent (0)
 {
+  rtx_reader_line_table = m_line_table;
+
   /* Set the global singleton pointer.  */
   rtx_reader_ptr = this;
 }
@@ -1056,6 +1107,10 @@ rtx_reader::~rtx_reader ()
 
   obstack_free (&string_obstack, NULL);
 
+#if 0
+  rtx_reader_line_table = NULL;
+#endif
+
   /* Clear the global singleton pointer.  */
   rtx_reader_ptr = NULL;
 }
@@ -1071,6 +1126,7 @@ rtx_reader::handle_include (file_location loc)
   const char *filename;
   const char *old_filename;
   int old_lineno;
+  int old_colno;
   char *pathname;
   FILE *input_file, *old_file;
 
@@ -1119,12 +1175,16 @@ rtx_reader::handle_include (file_location loc)
   old_file = m_read_md_file;
   old_filename = m_read_md_filename;
   old_lineno = m_read_md_lineno;
+  old_colno = m_read_md_colno;
 
   if (include_callback)
     include_callback (pathname);
 
   m_read_md_file = input_file;
   m_read_md_filename = pathname;
+  m_current_linemap =
+    linemap_check_ordinary (linemap_add (m_line_table, LC_ENTER, 0,
+					 pathname, 1));
 
   handle_file ();
 
@@ -1132,6 +1192,11 @@ rtx_reader::handle_include (file_location loc)
   m_read_md_file = old_file;
   m_read_md_filename = old_filename;
   m_read_md_lineno = old_lineno;
+  m_read_md_colno = old_colno;
+
+  m_current_linemap =
+    linemap_check_ordinary (linemap_add (m_line_table, LC_LEAVE, 0,
+					 NULL, 0));
 
   /* Do not free the pathname.  It is attached to the various rtx
      queue elements.  */
@@ -1187,13 +1252,34 @@ rtx_reader::handle_toplevel_file ()
   else
     m_base_dir = xstrndup (m_toplevel_fname, base - m_toplevel_fname);
 
+  m_current_linemap
+    = linemap_check_ordinary (linemap_add (m_line_table, LC_ENTER, 0,
+					   m_toplevel_fname, 1));
+
   handle_file ();
 }
 
 file_location
 rtx_reader::get_current_location () const
 {
-  return file_location (m_read_md_filename, m_read_md_lineno);
+  return linemap_position_for_line_and_column (m_line_table,
+					       m_current_linemap,
+					       m_read_md_lineno,
+					       m_read_md_colno);
+}
+
+/* FIXME.  */
+
+void
+rtx_reader::update_location (bool advancing)
+{
+  if (advancing)
+    {
+      if (m_read_md_lineno == 0)
+	linemap_line_start (m_line_table, m_read_md_lineno,
+			    1024 /* max_column_hint */);
+      linemap_position_for_column (m_line_table, m_read_md_colno);
+    }
 }
 
 /* Parse a -I option with argument ARG.  */
@@ -1354,3 +1440,35 @@ rtx_reader::log (const char *fmt, ...)
 	fputc ('\n', stderr);
       }
 }
+
+#ifdef GENERATOR_FILE
+
+expanded_location
+linemap_client_expand_location_to_spelling_point (source_location loc)
+{
+  const struct line_map_ordinary *map;
+  loc = linemap_resolve_location (rtx_reader_line_table, loc,
+				  LRK_SPELLING_LOCATION, &map);
+  return linemap_expand_location (rtx_reader_line_table, map, loc);
+}
+
+#endif
+
+/* Helper for the linemap code.  */
+
+static size_t
+round_alloc_size (size_t s)
+{
+  return s;
+}
+
+/* FIXME.  */
+
+void
+generator_linemap_init (line_maps *line_table)
+{
+  linemap_init (line_table, 1);
+  line_table->reallocator = xrealloc;
+  line_table->round_alloc_size = round_alloc_size;
+  line_table->default_range_bits = 0;
+}
diff --git a/gcc/read-md.h b/gcc/read-md.h
index 204df10..2c5357c 100644
--- a/gcc/read-md.h
+++ b/gcc/read-md.h
@@ -21,7 +21,9 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_READ_MD_H
 
 #include "obstack.h"
-#include "errors.h"
+#include "line-map.h"
+
+typedef source_location file_location;
 
 /* Holds one symbol or number in the .md file.  */
 struct md_name {
@@ -114,7 +116,7 @@ struct rtl_reader_policy
 class rtx_reader
 {
  public:
-  rtx_reader (rtl_reader_policy *policy);
+  rtx_reader (line_maps *line_table, rtl_reader_policy *policy);
   virtual ~rtx_reader ();
 
   bool read_md_files (int, const char **, bool (*) (const char *));
@@ -168,6 +170,12 @@ class rtx_reader
 
   file_location get_current_location () const;
 
+  void update_location (bool advancing);
+
+  file_location
+  make_location (file_location caret, file_location start,
+		 file_location finish) const;
+
   int read_char (void);
   void unread_char (int ch);
 
@@ -195,6 +203,10 @@ class rtx_reader
   void add_include_path (const char *arg);
 
  private:
+  /* FIXME.  */
+  line_maps *m_line_table;
+  const line_map_ordinary *m_current_linemap;
+
   /* The name of the toplevel file that indirectly included
      m_read_md_file.  */
   const char *m_toplevel_fname;
@@ -211,6 +223,7 @@ class rtx_reader
 
   /* The current line number in m_read_md_file.  */
   int m_read_md_lineno;
+  int m_read_md_colno;
 
   int m_read_md_colno;
 
@@ -248,7 +261,7 @@ class log_scope
 class noop_reader : public rtx_reader
 {
  public:
-  noop_reader () : rtx_reader (NULL) {}
+  noop_reader (line_maps *line_table) : rtx_reader (line_table, NULL) {}
 
   /* A dummy implementation which skips unknown directives.  */
   void handle_unknown_directive (file_location, const char *);
@@ -304,4 +317,7 @@ extern void traverse_md_constants (htab_trav, void *);
 extern void traverse_enum_types (htab_trav, void *);
 extern struct enum_type *lookup_enum_type (const char *);
 
+#define GENERATOR_BUILTINS_LOCATION ((file_location) 1)
+extern void generator_linemap_init (line_maps *line_table);
+
 #endif /* GCC_READ_MD_H */
diff --git a/gcc/read-rtl-function.c b/gcc/read-rtl-function.c
index 363010a..db1ba7c 100644
--- a/gcc/read-rtl-function.c
+++ b/gcc/read-rtl-function.c
@@ -213,7 +213,7 @@ class fixup_expr : public fixup
 class function_reader : public rtx_reader
 {
  public:
-  function_reader (rtl_reader_policy *policy);
+  function_reader (line_maps *set, rtl_reader_policy *policy);
   ~function_reader ();
 
   void handle_unknown_directive (file_location, const char *);
@@ -294,7 +294,7 @@ fixup_insn_uid::apply (function_reader *reader) const
       const char *op_name = get_operand_name (m_rtx, m_operand_idx);
       if (op_name)
 	error_at (m_loc,
-		  "insn with UID %i not found for operand %i (`%s') of insn %i",
+		  "insn with UID %i not found for operand %i (%qs) of insn %i",
 		  m_insn_uid, m_operand_idx, op_name, INSN_UID (m_rtx));
       else
 	error_at (m_loc,
@@ -418,8 +418,8 @@ fixup_expr::apply (function_reader *reader) const
 
 /* function_reader's constructor.  */
 
-function_reader::function_reader (rtl_reader_policy *policy)
-: rtx_reader (policy),
+function_reader::function_reader (line_maps *set, rtl_reader_policy *policy)
+: rtx_reader (set, policy),
   m_first_insn (NULL)
 {
   bitmap_initialize (&m_bb_indices, NULL);
@@ -442,7 +442,7 @@ function_reader::~function_reader ()
    set_first_insn and set_last_insn as appropriate.  */
 
 void
-function_reader::handle_unknown_directive (file_location /*start_loc*/,
+function_reader::handle_unknown_directive (file_location start_loc,
 					   const char *name)
 {
   rtx x = read_rtx_code (name);
@@ -455,6 +455,15 @@ function_reader::handle_unknown_directive (file_location /*start_loc*/,
       m_first_insn = insn;
       set_first_insn (insn);
     }
+  int c = read_char ();
+  location_t end_loc = get_current_location ();
+  unread_char (c);
+  location_t insn_loc = make_location (start_loc, start_loc, end_loc);
+  if (0)
+    {
+      inform (insn_loc, "input insn");
+      debug (insn);
+    }
   m_insns_by_uid.put (INSN_UID (insn), insn);
 }
 
@@ -843,7 +852,7 @@ read_rtl_function_body (int argc, const char **argv,
   init_emit ();
   init_varasm_status ();
 
-  function_reader reader (policy);
+  function_reader reader (line_table, policy);
   if (!reader.read_md_files (argc, argv, parse_opt))
     return false;
 
diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c
index 87a914f..0f58906 100644
--- a/gcc/read-rtl.c
+++ b/gcc/read-rtl.c
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GENERATOR_FILE
 #include "function.h"
 #include "emit-rtl.h"
+#include "diagnostic-core.h"
 #endif
 
 /* One element in a singly-linked list of (integer, string) pairs.  */
@@ -1450,6 +1451,9 @@ read_rtx_code (const char *code_name)
 	       is before the enum specifying which kind of note we have
 	       (operand 4).  */
 #ifndef GENERATOR_FILE
+	    if (0)
+	      inform (rtx_reader_ptr->get_current_location (),
+		      "note-specific data here");
 	    c = read_skip_spaces ();
 	    if (c == '[')
 	      {
@@ -1457,8 +1461,8 @@ read_rtx_code (const char *code_name)
 		   [bb %d].  */
 		file_location bb_loc = read_name (&name);
 		if (strcmp (name.string, "bb"))
-		  error_at (bb_loc, "was expecting `%s'", "bb");
-		read_name (&name);
+		  error_at (bb_loc, "was expecting %qs", "bb");
+		file_location bb_idx_loc = read_name (&name);
 		int bb_idx = atoi (name.string);
 		rtx_reader_ptr->add_fixup_note_insn_basic_block (bb_loc,
 								 return_rtx, i,
@@ -1472,6 +1476,9 @@ read_rtx_code (const char *code_name)
 	else if (i == 7 && JUMP_P (return_rtx))
 	  {
 #ifndef GENERATOR_FILE
+	    if (0)
+	      inform (rtx_reader_ptr->get_current_location (),
+		      "jump_insn-specific data here");
 	    c = read_skip_spaces ();
 	    if (c != '-')
 	      {
diff --git a/gcc/rtl/rtl-errors.c b/gcc/rtl/rtl-errors.c
index 0c6d4ab..106295f 100644
--- a/gcc/rtl/rtl-errors.c
+++ b/gcc/rtl/rtl-errors.c
@@ -22,10 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "errors.h"
 
-/* FIXME.  */
-
-void
-fatal (const char *, ...)
+void fatal (const char *, ...)
 {
   // TODO
   abort ();
diff --git a/gcc/testsuite/rtl.dg/bad-include.rtl b/gcc/testsuite/rtl.dg/bad-include.rtl
new file mode 100644
index 0000000..5bd1580
--- /dev/null
+++ b/gcc/testsuite/rtl.dg/bad-include.rtl
@@ -0,0 +1,5 @@
+/* Verify that we get sane error messages if errors occur in
+   an included file.
+   We give the included file a .md suffix to avoid it being
+   run by rtl.exp.  */
+(include "bad-includee.md")
diff --git a/gcc/testsuite/rtl.dg/bad-includee.md b/gcc/testsuite/rtl.dg/bad-includee.md
new file mode 100644
index 0000000..907b378
--- /dev/null
+++ b/gcc/testsuite/rtl.dg/bad-includee.md
@@ -0,0 +1,5 @@
+(not-a-valid-kind-of-insn 1 0 0) /* { dg-error "unknown rtx code" } */
+/* { dg-begin-multiline-output "" }
+ (not-a-valid-kind-of-insn 1 0 0)
+                          ^
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/rtl.dg/missing-include.rtl b/gcc/testsuite/rtl.dg/missing-include.rtl
index f99f3ef..441f929 100644
--- a/gcc/testsuite/rtl.dg/missing-include.rtl
+++ b/gcc/testsuite/rtl.dg/missing-include.rtl
@@ -1 +1,5 @@
 (include "does-not-exist.rtl") /* { dg-error "include file .does-not-exist.rtl. not found" } */
+/* { dg-begin-multiline-output "" }
+ (include "does-not-exist.rtl")
+ ^
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/rtl.dg/unknown-insn-uid.rtl b/gcc/testsuite/rtl.dg/unknown-insn-uid.rtl
index c91bf4a..b5dae35 100644
--- a/gcc/testsuite/rtl.dg/unknown-insn-uid.rtl
+++ b/gcc/testsuite/rtl.dg/unknown-insn-uid.rtl
@@ -1,3 +1,11 @@
 (note 6 1 0 2 [bb 2] NOTE_INSN_BASIC_BLOCK) ;; { dg-error "insn with UID 1 not found for operand 0 ..PREV_INSN.. of insn 6" }
+/* { dg-begin-multiline-output "" }
+ (note 6 1 0 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
+         ^
+   { dg-end-multiline-output "" } */
 
 (note 7 0 3 2 [bb 2] NOTE_INSN_BASIC_BLOCK) ;; { dg-error "insn with UID 3 not found for operand 1 ..NEXT_INSN.. of insn 7" }
+/* { dg-begin-multiline-output "" }
+ (note 7 0 3 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
+           ^
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/rtl.dg/unknown-rtx-code.rtl b/gcc/testsuite/rtl.dg/unknown-rtx-code.rtl
index 7a66767..173c172 100644
--- a/gcc/testsuite/rtl.dg/unknown-rtx-code.rtl
+++ b/gcc/testsuite/rtl.dg/unknown-rtx-code.rtl
@@ -1 +1,5 @@
 (not-a-valid-kind-of-insn 1 0 0) ;; { dg-error "unknown rtx code" }
+/* { dg-begin-multiline-output "" }
+ (not-a-valid-kind-of-insn 1 0 0)
+                          ^
+   { dg-end-multiline-output "" } */
-- 
1.8.5.3

