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

---
 gcc/Makefile.in                           |  27 ++++---
 gcc/errors.h                              |  14 ----
 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                             | 122 +++++++++++++++++++++++++++++-
 gcc/read-md.h                             |  23 +++++-
 gcc/read-rtl-function.c                   |  20 +++--
 gcc/read-rtl.c                            |   5 +-
 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 |   6 ++
 gcc/testsuite/rtl.dg/unknown-rtx-code.rtl |   3 +
 19 files changed, 241 insertions(+), 65 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 078d56d..ec7dd6a 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1064,7 +1064,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 \
@@ -2667,29 +2667,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 ebafa77..a6973f3 100644
--- a/gcc/errors.h
+++ b/gcc/errors.h
@@ -28,22 +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, int);
-
-  const char *filename;
-  int lineno;
-  int colno;
-};
-
-inline file_location::file_location (const char *filename_in, int lineno_in, int colno_in)
-: filename (filename_in), lineno (lineno_in), colno (colno_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 ccfcdfd..3e90df0 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -4254,9 +4254,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));
@@ -4657,7 +4660,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, 0),
+  attr->default_val = get_attr_value (GENERATOR_BUILTINS_LOCATION,
 				      value, attr, -2);
 }
 
@@ -5279,7 +5282,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, 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 d5e07a9..b204b01 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));
@@ -809,18 +811,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 f792cb4..6f35b2e 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -293,7 +293,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)
@@ -980,7 +982,7 @@ init_insn_for_nothing (void)
   idata = XCNEW (struct data);
   new (idata) data ();
   idata->name = "*placeholder_for_nothing";
-  idata->loc = file_location ("<internal>", 0, 0);
+  idata->loc = GENERATOR_BUILTINS_LOCATION;
   idata_end = &idata->next;
 }
 
diff --git a/gcc/gensupport.c b/gcc/gensupport.c
index cb74aea..68aa4d8 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, -1);
+  e->loc = GENERATOR_BUILTINS_LOCATION;
   e->next = define_attr_queue;
   define_attr_queue = e;
 
@@ -2231,7 +2231,7 @@ process_define_subst (void)
 class gen_reader : public rtx_reader
 {
  public:
-  gen_reader () : rtx_reader () {}
+  gen_reader (line_maps *line_table) : rtx_reader (line_table) {}
   void handle_unknown_directive (file_location, const char *);
 };
 
@@ -2523,7 +2523,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 34b1b55..536ecf4 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:%d: ", loc.filename, loc.lineno, loc.colno);
+  expanded_location xloc
+    = linemap_client_expand_location_to_spelling_point (loc);
+  fprintf (stderr, "%s:%d:%d: ", xloc.file, xloc.line, xloc.col);
   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;
@@ -303,6 +313,17 @@ fatal_with_file_and_line (const char *msg, ...)
 	   base_rtx_reader_ptr->get_colno (), 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);
 }
 
@@ -408,6 +429,22 @@ void require_word_ws (const char *expected)
     fatal_with_file_and_line ("missing '%s'", expected);
 }
 
+/* FIXME.  */
+
+file_location
+base_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
@@ -425,7 +462,9 @@ base_rtx_reader::read_char (void)
   else
     m_read_md_colno++;
 
+
   LOG_SCOPE1 ("read_char: '%c'", ch);
+  update_location (true);
 
   /* If we're filtering lines, treat everything outside the
      range of interest as a space.  */
@@ -452,6 +491,7 @@ base_rtx_reader::unread_char (int ch)
     }
   else
     m_read_md_colno--;
+  update_location (false);
   ungetc (ch, m_read_md_file);
 
   LOG_SCOPE1 ("unread_char: '%c'", ch);
@@ -482,6 +522,8 @@ read_name_1 (struct md_name *name, file_location *out_loc)
 
   c = read_skip_spaces ();
 
+  file_location start = base_rtx_reader_ptr->get_current_location ();
+
   i = 0;
   angle_bracket_depth = 0;
   while (1)
@@ -513,8 +555,9 @@ read_name_1 (struct md_name *name, file_location *out_loc)
     }
 
   unread_char (c);
-  *out_loc = base_rtx_reader_ptr->get_current_location ();
+  file_location end = base_rtx_reader_ptr->get_current_location ();
   read_char ();
+  *out_loc = base_rtx_reader_ptr->make_location (start, start, end);
 
   if (i == 0)
     return false;
@@ -1030,11 +1073,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 base_rtx_reader.  */
 
-base_rtx_reader::base_rtx_reader ()
+base_rtx_reader::base_rtx_reader (line_maps *line_table)
 : m_verbose (false),
+  m_line_table (line_table),
+  m_current_linemap (NULL),
   m_toplevel_fname (NULL),
   m_base_dir (NULL),
   m_read_md_file (NULL),
@@ -1047,6 +1095,8 @@ base_rtx_reader::base_rtx_reader ()
   m_last_line (0),
   m_log_indent (0)
 {
+  rtx_reader_line_table = m_line_table;
+
   /* Set the global singleton pointer.  */
   base_rtx_reader_ptr = this;
 
@@ -1090,6 +1140,10 @@ base_rtx_reader::~base_rtx_reader ()
 
   obstack_free (&string_obstack, NULL);
 
+#if 0
+  rtx_reader_line_table = NULL;
+#endif
+
   /* Clear the global singleton pointer.  */
   base_rtx_reader_ptr = NULL;
 }
@@ -1160,6 +1214,9 @@ base_rtx_reader::handle_include (file_location loc)
 
   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 ();
 
@@ -1169,6 +1226,10 @@ base_rtx_reader::handle_include (file_location loc)
   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.  */
 }
@@ -1223,13 +1284,34 @@ base_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
 base_rtx_reader::get_current_location () const
 {
-  return file_location (m_read_md_filename, m_read_md_lineno, m_read_md_colno);
+  return linemap_position_for_line_and_column (m_line_table,
+					       m_current_linemap,
+					       m_read_md_lineno,
+					       m_read_md_colno);
+}
+
+/* FIXME.  */
+
+void
+base_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.  */
@@ -1395,3 +1477,35 @@ base_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 69748aa..e90a70b 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 {
@@ -88,7 +90,7 @@ struct enum_type {
 class base_rtx_reader
 {
  public:
-  base_rtx_reader ();
+  base_rtx_reader (line_maps *line_table);
   virtual ~base_rtx_reader ();
 
   bool read_md_files (int, const char **, bool (*) (const char *));
@@ -107,6 +109,12 @@ class base_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);
 
@@ -138,6 +146,10 @@ class base_rtx_reader
   bool m_verbose;
 
  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;
@@ -201,7 +213,7 @@ class log_scope
 class noop_reader : public base_rtx_reader
 {
  public:
-  noop_reader () : base_rtx_reader () {}
+  noop_reader (line_maps *line_table) : base_rtx_reader (line_table) {}
 
   /* A dummy implementation which skips unknown directives.  */
   void handle_unknown_directive (file_location, const char *);
@@ -213,7 +225,7 @@ class noop_reader : public base_rtx_reader
 class rtx_reader : public base_rtx_reader
 {
  public:
-  rtx_reader ();
+  rtx_reader (line_maps *line_table);
   ~rtx_reader ();
 
   rtx read_rtx_code (const char *);
@@ -281,4 +293,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 449745b..6d877c1 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 (function_reader_policy *policy);
+  function_reader (line_maps *set, function_reader_policy *policy);
   ~function_reader ();
 
   rtx read_rtx_operand (rtx return_rtx, int idx) FINAL OVERRIDE;
@@ -320,7 +320,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,
@@ -683,8 +683,9 @@ fixup_expr::apply (function_reader *reader) const
 
 /* function_reader's constructor.  */
 
-function_reader::function_reader (function_reader_policy *policy)
-: rtx_reader (),
+function_reader::function_reader (line_maps *set,
+				  function_reader_policy *policy)
+: rtx_reader (set),
   m_policy (policy),
   m_first_insn (NULL),
   m_name (NULL),
@@ -1166,6 +1167,15 @@ function_reader::parse_insn (file_location start_loc, const char *name)
       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);
 }
 
@@ -1715,7 +1725,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 cb04ff6..1fc1cdb 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.  */
@@ -1629,8 +1630,8 @@ rtx_reader::read_rtx_variadic (rtx form)
 
 /* FIXME.  */
 
-rtx_reader::rtx_reader ()
-: base_rtx_reader ()
+rtx_reader::rtx_reader (line_maps *line_table)
+: base_rtx_reader (line_table)
 {
   /* Set the global singleton pointer.  */
   rtx_reader_ptr = this;
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 8e63ace..00df2f6 100644
--- a/gcc/testsuite/rtl.dg/unknown-insn-uid.rtl
+++ b/gcc/testsuite/rtl.dg/unknown-insn-uid.rtl
@@ -1,6 +1,12 @@
 (function "test"
   (insn-chain
     (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 "" }
+   { 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 "" }
+   { dg-end-multiline-output "" } */
+
   ) ;; insn-chain
 ) ;; function
diff --git a/gcc/testsuite/rtl.dg/unknown-rtx-code.rtl b/gcc/testsuite/rtl.dg/unknown-rtx-code.rtl
index 9930677..c77a5a4 100644
--- a/gcc/testsuite/rtl.dg/unknown-rtx-code.rtl
+++ b/gcc/testsuite/rtl.dg/unknown-rtx-code.rtl
@@ -1,5 +1,8 @@
 (function "test"
   (insn-chain
     (not-a-valid-kind-of-insn 1 0 0) ;; { dg-error "unknown rtx code" }
+/* { dg-begin-multiline-output "" }
+   { dg-end-multiline-output "" } */
+
   ) ;; insn-chain
 ) ;; function
-- 
1.8.5.3

