diff mbox

[committed] Rework read_md_rtx interface

Message ID 87h9p4i502.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford July 16, 2015, 1:52 p.m. UTC
This patch gets read_md_rtx to return a structure that describes the rtx rather
than separate fields.  This includes the location of the start of the rtx as
a file_location.  A follow-on patch will use this to remove define_split and
define_peephole2 from the insn_code numbering.

This removes the last cases where diagnostics were reported against a line
rather than a file_location.

Series bootstrapped & regression-tested on x86_64-linux-gnu.  I built gcc
before and after the series for one target per CPU directory and checked
that the output was the same (except for some filename fixes later in
the series.)  Applied.

Thanks,
Richard


gcc/
	* read-md.h (message_with_line, error_with_line): Delete.
	* read-md.c (message_with_line, error_with_line): Delete.
	* gensupport.h: Include read-md.h.
	(md_rtx_info): New structure.
	(read_md_rtx): Use it.  Return a bool success value.
	* gensupport.c (read_md_rtx): Likewise.
	* genattr-common.c (gen_attr): Take an md_rtx_info rather than an rtx.
	(main): Update after interface changes.
	* genattr.c (gen_attr): Take an md_rtx_info rather than an rtx.
	(main): Update after interface changes.
	* genattrtab.c (insn_code_number): Delete.
	(optimize_attrs): Add a max_insn_code parameter and use it instead
	of insn_code_number.
	(gen_attr): Take an md_rtx_info rather than an rtx and lineno.
	Use *_at rather than *_with_line functions.
	(gen_insn): Likewise.
	(gen_delay): Likewise.
	(gen_insn_reserv): Likewise.
	(gen_bypass): Take an md_rtx_info rather than an rtx.
	(main): Update after interface changes.  Use a local max_insn_code
	variable instead of insn_code_number.
	* genautomata.c (gen_cpu_unit): Take an md_rtx_info rather than
	an rtx.  Use fatal_at rather than fatal.
	(gen_query_cpu_unit, gen_bypass, gen_excl_set)
	(gen_presence_absence_set, gen_presence_set, gen_final_presence_set)
	(gen_absence_set, gen_final_absence_set, gen_automaton)
	(gen_automata_option, gen_reserv, gen_insn_reserv): Likewise.
	(main): Update after interface changes.
	* gencodes.c (gen_insn): Take an md_rtx_info rather than an rtx
	and code number.
	(main): Update after interface changes.
	* genconditions.c (main): Use new read_md_rtx interface.
	* genconfig.c (gen_insn): Take an md_rtx_info rather than an rtx.
	(gen_expand, gen_split, gen_peephole, gen_peephole2): Likewise.
	(main): Update after interface changes.
	* genemit.c (insn_code_number, insn_index_number): Delete.
	(gen_insn): Take an md_rtx_info rather than an rtx and lineno.
	Use fatal_at rather than fatal.
	(gen_expand): Take an md_rtx_info rather than an rtx.  Use fatal_at
	rather than fatal.
	(gen_split): Likewise.
	(main): Update after interface changes.
	* genextract.c (line_no): Delete.
	(gen_insn): Take an md_rtx_info rather than an rtx and lineno.
	Update call to walk_rtx.
	(VEC_safe_set_locstr): Add an md_rtx_info argument.  Use message_at
	rather than message_with_line.
	(walk_rtx): Add an md_rtx_info argument.  Update call to
	VEC_safe_set_locstr.
	(main): Update after interface changes.
	* genflags.c (gen_insn): Take an md_rtx_info rather than an rtx
	and lineno.  Use error_at rather than separate message_with_line
	calls and have_error assignments.
	(main): Update after interface changes.
	* genmddump.c (main): Use new read_md_rtx interface.
	* genopinit.c (insn): Take an md_rtx_info rather than an rtx.
	(main): Update after interface changes.
	* genoutput.c (next_code_number): Delete.
	(gen_insn): Take an md_rtx_info rather than an rtx and lineno.
	(gen_peephole, gen_expand, gen_split): Likewise.
	(note_constraint): Likewise.  Use *_at rather than *_with_line
	functions.
	(main): Update after interface changes.
	* genpeep.c (gen_peephole): Take an md_rtx_info rather than an
	rtx and lineno.
	(main): Update after interface changes.
	* genpreds.c (process_define_predicate): Take an md_rtx_info rather
	than an rtx and lineno.
	(process_define_constraint): Likewise.
	(process_define_register_constraint): Likewise.
	(main): Update after interface changes.
	* genrecog.c (next_insn_code, pattern_lineno): Delete.
	(validate_pattern): Replace top-level rtx with an md_rtx_info.
	Use *_at rather than *_with_line functions.
	(match_pattern_2): Likewise.
	(match_pattern_1, match_pattern): Add an md_rtx_info parameter.
	(get_peephole2_pattern): Take an md_rtx_info rather than an rtvec.
	Use *_at rather than *_with_line functions.
	* gentarget-def.c (add_insn): New function.
	(main): Use it.  Use new read_md_rtx interface.
diff mbox

Patch

Index: gcc/read-md.h
===================================================================
--- gcc/read-md.h	2015-07-12 14:18:26.650113562 +0100
+++ gcc/read-md.h	2015-07-12 14:18:26.682112145 +0100
@@ -137,8 +137,6 @@  extern void fprint_c_condition (FILE *,
 extern void message_at (file_location, const char *, ...) ATTRIBUTE_PRINTF_2;
 extern void error_at (file_location, const char *, ...) ATTRIBUTE_PRINTF_2;
 extern void fatal_at (file_location, const char *, ...) ATTRIBUTE_PRINTF_2;
-extern void message_with_line (int, const char *, ...) ATTRIBUTE_PRINTF_2;
-extern void error_with_line (int, const char *, ...) ATTRIBUTE_PRINTF_2;
 extern void fatal_with_file_and_line (const char *, ...)
   ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
 extern void fatal_expected_char (int, int) ATTRIBUTE_NORETURN;
Index: gcc/read-md.c
===================================================================
--- gcc/read-md.c	2015-07-12 14:18:26.650113562 +0100
+++ gcc/read-md.c	2015-07-12 14:18:26.682112145 +0100
@@ -290,32 +290,6 @@  fatal_at (file_location loc, const char
   exit (1);
 }
 
-/* A printf-like function for reporting an error against line LINENO
-   in the current MD file.  */
-
-void
-message_with_line (int lineno, const char *msg, ...)
-{
-  va_list ap;
-
-  va_start (ap, msg);
-  message_at_1 (file_location (read_md_filename, lineno), msg, ap);
-  va_end (ap);
-}
-
-/* Like message_with_line, but treat the condition as an error.  */
-
-void
-error_with_line (int lineno, const char *msg, ...)
-{
-  va_list ap;
-
-  va_start (ap, msg);
-  message_at_1 (file_location (read_md_filename, lineno), msg, ap);
-  va_end (ap);
-  have_error = 1;
-}
-
 /* A printf-like function for reporting an error against the current
    position in the MD file.  */
 
Index: gcc/gensupport.h
===================================================================
--- gcc/gensupport.h	2015-07-12 14:18:26.668112765 +0100
+++ gcc/gensupport.h	2015-07-12 20:29:24.030447077 +0100
@@ -20,13 +20,29 @@  Software Foundation; either version 3, o
 #ifndef GCC_GENSUPPORT_H
 #define GCC_GENSUPPORT_H
 
+#include "read-md.h"
+
 struct obstack;
 extern struct obstack *rtl_obstack;
 
+/* Information about an .md define_* rtx.  */
+struct md_rtx_info {
+  /* The rtx itself.  */
+  rtx def;
+
+  /* The location of the first line of the rtx.  */
+  file_location loc;
+
+  /* The unique number attached to the rtx.  Currently all define_insns,
+     define_expands, define_splits, define_peepholes and define_peephole2s
+     share the same insn_code index space.  */
+  int index;
+};
+
 extern rtx add_implicit_parallel (rtvec);
 extern bool init_rtx_reader_args_cb (int, char **, bool (*)(const char *));
 extern bool init_rtx_reader_args (int, char **);
-extern rtx read_md_rtx (int *, int *);
+extern bool read_md_rtx (md_rtx_info *);
 
 /* Set this to 0 to disable automatic elision of insn patterns which
    can never be used in this configuration.  See genconditions.c.
Index: gcc/gensupport.c
===================================================================
--- gcc/gensupport.c	2015-07-12 14:18:26.668112765 +0100
+++ gcc/gensupport.c	2015-07-12 14:18:26.681112189 +0100
@@ -2529,14 +2529,11 @@  init_rtx_reader_args (int argc, char **a
   return init_rtx_reader_args_cb (argc, argv, 0);
 }
 
-/* The entry point for reading a single rtx from an md file.  Return
-   the rtx, or NULL if the md file has been fully processed.
-   Return the line where the rtx was found in LINENO.
-   Return the number of code generating rtx'en read since the start
-   of the md file in SEQNR.  */
+/* Try to read a single rtx from the file.  Return true on success,
+   describing it in *INFO.  */
 
-rtx
-read_md_rtx (int *lineno, int *seqnr)
+bool
+read_md_rtx (md_rtx_info *info)
 {
   struct queue_elem **queue, *elem;
   rtx desc;
@@ -2553,14 +2550,13 @@  read_md_rtx (int *lineno, int *seqnr)
   else if (other_queue != NULL)
     queue = &other_queue;
   else
-    return NULL_RTX;
+    return false;
 
   elem = *queue;
   *queue = elem->next;
-  desc = elem->data;
-  read_md_filename = elem->loc.filename;
-  *lineno = elem->loc.lineno;
-  *seqnr = sequence_num;
+  info->def = elem->data;
+  info->loc = elem->loc;
+  info->index = sequence_num;
 
   free (elem);
 
@@ -2570,6 +2566,7 @@  read_md_rtx (int *lineno, int *seqnr)
      elided patterns are never counted by the sequence numbering; it
      is the caller's responsibility, when insn_elision is false, not
      to use elided pattern numbers for anything.  */
+  desc = info->def;
   switch (GET_CODE (desc))
     {
     case DEFINE_INSN:
@@ -2580,9 +2577,9 @@  read_md_rtx (int *lineno, int *seqnr)
       else if (insn_elision)
 	goto discard;
 
-      /* *seqnr is used here so the name table will match caller's
+      /* info->index is used here so the name table will match caller's
 	 idea of insn numbering, whether or not elision is active.  */
-      record_insn_name (*seqnr, XSTR (desc, 0));
+      record_insn_name (info->index, XSTR (desc, 0));
       break;
 
     case DEFINE_SPLIT:
@@ -2591,14 +2588,14 @@  read_md_rtx (int *lineno, int *seqnr)
       if (maybe_eval_c_test (XSTR (desc, 1)) != 0)
 	sequence_num++;
       else if (insn_elision)
-	    goto discard;
+	goto discard;
       break;
 
     default:
       break;
     }
 
-  return desc;
+  return true;
 }
 
 /* Helper functions for insn elision.  */
Index: gcc/genattr-common.c
===================================================================
--- gcc/genattr-common.c	2015-07-12 14:18:07.691911409 +0100
+++ gcc/genattr-common.c	2015-07-12 14:18:26.676112411 +0100
@@ -37,10 +37,11 @@  write_upcase (const char *str)
 }
 
 static void
-gen_attr (rtx attr)
+gen_attr (md_rtx_info *info)
 {
   const char *p, *tag;
 
+  rtx attr = info->def;
   p = XSTR (attr, 1);
   if (*p != '\0')
     {
@@ -62,7 +63,6 @@  gen_attr (rtx attr)
 int
 main (int argc, char **argv)
 {
-  rtx desc;
   bool have_delay = false;
   bool have_sched = false;
 
@@ -78,34 +78,33 @@  main (int argc, char **argv)
 
   /* Read the machine description.  */
 
-  while (1)
-    {
-      int line_no, insn_code_number;
+  md_rtx_info info;
+  while (read_md_rtx (&info))
+    switch (GET_CODE (info.def))
+      {
+      case DEFINE_ATTR:
+	gen_attr (&info);
+	break;
 
-      desc = read_md_rtx (&line_no, &insn_code_number);
-      if (desc == NULL)
+      case DEFINE_DELAY:
+	if (!have_delay)
+	  {
+	    printf ("#define DELAY_SLOTS\n");
+	    have_delay = true;
+	  }
 	break;
 
-      if (GET_CODE (desc) == DEFINE_ATTR)
-	gen_attr (desc);
+      case DEFINE_INSN_RESERVATION:
+	if (!have_sched)
+	  {
+	    printf ("#define INSN_SCHEDULING\n");
+	    have_sched = true;
+	  }
+	break;
 
-      if (GET_CODE (desc) == DEFINE_DELAY)
-        {
-	  if (!have_delay)
-	    {
-	      printf ("#define DELAY_SLOTS\n");
-	      have_delay = true;
-	    }
-	}
-      else if (GET_CODE (desc) == DEFINE_INSN_RESERVATION)
-	{
-	  if (!have_sched)
-	    {
-	      printf ("#define INSN_SCHEDULING\n");
-	      have_sched = true;
-	    }
-	}
-    }
+      default:
+	break;
+      }
   puts ("\n#endif /* GCC_INSN_ATTR_COMMON_H */");
 
   if (ferror (stdout) || fflush (stdout) || fclose (stdout))
Index: gcc/genattr.c
===================================================================
--- gcc/genattr.c	2015-07-12 14:18:07.691911409 +0100
+++ gcc/genattr.c	2015-07-12 14:18:26.677112366 +0100
@@ -29,15 +29,14 @@  Software Foundation; either version 3, o
 #include "gensupport.h"
 
 
-static void gen_attr (rtx);
-
 static vec<rtx> const_attrs, reservations;
 
 
 static void
-gen_attr (rtx attr)
+gen_attr (md_rtx_info *info)
 {
   const char *p;
+  rtx attr = info->def;
   int is_const = GET_CODE (XEXP (attr, 2)) == CONST;
 
   if (is_const)
@@ -141,7 +140,6 @@  find_tune_attr (rtx exp)
 int
 main (int argc, char **argv)
 {
-  rtx desc;
   int have_delay = 0;
   int have_annul_true = 0;
   int have_annul_false = 0;
@@ -162,20 +160,18 @@  main (int argc, char **argv)
 
   /* Read the machine description.  */
 
-  while (1)
+  md_rtx_info info;
+  while (read_md_rtx (&info))
     {
-      int line_no, insn_code_number;
-
-      desc = read_md_rtx (&line_no, &insn_code_number);
-      if (desc == NULL)
-	break;
-
-      if (GET_CODE (desc) == DEFINE_ATTR
-	  || GET_CODE (desc) == DEFINE_ENUM_ATTR)
-	gen_attr (desc);
+      rtx def = info.def;
+      switch (GET_CODE (def))
+	{
+	case DEFINE_ATTR:
+	case DEFINE_ENUM_ATTR:
+	  gen_attr (&info);
+	  break;
 
-      else if (GET_CODE (desc) == DEFINE_DELAY)
-        {
+	case DEFINE_DELAY:
 	  if (! have_delay)
 	    {
 	      printf ("extern int num_delay_slots (rtx_insn *);\n");
@@ -184,28 +180,31 @@  main (int argc, char **argv)
 	      have_delay = 1;
 	    }
 
-	  for (i = 0; i < XVECLEN (desc, 1); i += 3)
+	  for (i = 0; i < XVECLEN (def, 1); i += 3)
 	    {
-	      if (XVECEXP (desc, 1, i + 1) && ! have_annul_true)
+	      if (XVECEXP (def, 1, i + 1) && ! have_annul_true)
 		{
 		  printf ("#define ANNUL_IFTRUE_SLOTS\n");
 		  printf ("extern int eligible_for_annul_true (rtx_insn *, int, rtx_insn *, int);\n");
 		  have_annul_true = 1;
 		}
 
-	      if (XVECEXP (desc, 1, i + 2) && ! have_annul_false)
+	      if (XVECEXP (def, 1, i + 2) && ! have_annul_false)
 		{
 		  printf ("#define ANNUL_IFFALSE_SLOTS\n");
 		  printf ("extern int eligible_for_annul_false (rtx_insn *, int, rtx_insn *, int);\n");
 		  have_annul_false = 1;
 		}
 	    }
-        }
+	  break;
 
-      else if (GET_CODE (desc) == DEFINE_INSN_RESERVATION)
-	{
+	case DEFINE_INSN_RESERVATION:
 	  num_insn_reservations++;
-	  reservations.safe_push (desc);
+	  reservations.safe_push (def);
+	  break;
+
+	default:
+	  break;
 	}
     }
 
Index: gcc/genattrtab.c
===================================================================
--- gcc/genattrtab.c	2015-07-12 14:18:26.650113562 +0100
+++ gcc/genattrtab.c	2015-07-12 20:41:32.084579584 +0100
@@ -211,7 +211,6 @@  struct attr_value_list **insn_code_value
 
 /* Other variables.  */
 
-static int insn_code_number;
 static int insn_index_number;
 static int got_define_asm_attributes;
 static int must_extract;
@@ -1016,7 +1015,7 @@  check_attr_value (rtx exp, struct attr_d
 	struct attr_desc *attr2 = find_attr (&XSTR (exp, 0), 0);
 	if (attr2 == NULL)
 	  error_at (attr->loc, "unknown attribute `%s' in ATTR",
-			   XSTR (exp, 0));
+		    XSTR (exp, 0));
 	else if (attr->is_const && ! attr2->is_const)
 	  error_at (attr->loc,
 		    "non-constant attribute `%s' referenced from `%s'",
@@ -2950,10 +2949,11 @@  get_attr_order (struct attr_desc ***ret)
 
 /* Optimize the attribute lists by seeing if we can determine conditional
    values from the known values of other attributes.  This will save subroutine
-   calls during the compilation.  */
+   calls during the compilation.  MAX_INSN_CODE is the number of unique
+   instruction codes.  */
 
 static void
-optimize_attrs (void)
+optimize_attrs (int max_insn_code)
 {
   struct attr_desc *attr;
   struct attr_value *av;
@@ -2972,7 +2972,7 @@  optimize_attrs (void)
     return;
 
   /* Make 2 extra elements, for "code" values -2 and -1.  */
-  insn_code_values = XCNEWVEC (struct attr_value_list *, insn_code_number + 2);
+  insn_code_values = XCNEWVEC (struct attr_value_list *, max_insn_code + 2);
 
   /* Offset the table address so we can index by -2 or -1.  */
   insn_code_values += 2;
@@ -3000,7 +3000,7 @@  optimize_attrs (void)
   gcc_assert (iv == ivbuf + num_insn_ents);
 
   /* Process one insn code at a time.  */
-  for (i = -2; i < insn_code_number; i++)
+  for (i = -2; i < max_insn_code; i++)
     {
       /* Clear the ATTR_CURR_SIMPLIFIED_P flag everywhere relevant.
 	 We use it to mean "already simplified for this insn".  */
@@ -3126,63 +3126,64 @@  add_attr_value (struct attr_desc *attr,
 /* Create table entries for DEFINE_ATTR or DEFINE_ENUM_ATTR.  */
 
 static void
-gen_attr (rtx exp, int lineno)
+gen_attr (md_rtx_info *info)
 {
   struct enum_type *et;
   struct enum_value *ev;
   struct attr_desc *attr;
   const char *name_ptr;
   char *p;
+  rtx def = info->def;
 
   /* Make a new attribute structure.  Check for duplicate by looking at
      attr->default_val, since it is initialized by this routine.  */
-  attr = find_attr (&XSTR (exp, 0), 1);
+  attr = find_attr (&XSTR (def, 0), 1);
   if (attr->default_val)
     {
-      error_with_line (lineno, "duplicate definition for attribute %s",
-		       attr->name);
+      error_at (info->loc, "duplicate definition for attribute %s",
+		attr->name);
       message_at (attr->loc, "previous definition");
       return;
     }
-  attr->loc = file_location (read_md_filename, lineno);
+  attr->loc = info->loc;
 
-  if (GET_CODE (exp) == DEFINE_ENUM_ATTR)
+  if (GET_CODE (def) == DEFINE_ENUM_ATTR)
     {
-      attr->enum_name = XSTR (exp, 1);
-      et = lookup_enum_type (XSTR (exp, 1));
+      attr->enum_name = XSTR (def, 1);
+      et = lookup_enum_type (XSTR (def, 1));
       if (!et || !et->md_p)
-	error_with_line (lineno, "No define_enum called `%s' defined",
-			 attr->name);
+	error_at (info->loc, "No define_enum called `%s' defined",
+		  attr->name);
       if (et)
 	for (ev = et->values; ev; ev = ev->next)
 	  add_attr_value (attr, ev->name);
     }
-  else if (*XSTR (exp, 1) == '\0')
+  else if (*XSTR (def, 1) == '\0')
     attr->is_numeric = 1;
   else
     {
-      name_ptr = XSTR (exp, 1);
+      name_ptr = XSTR (def, 1);
       while ((p = next_comma_elt (&name_ptr)) != NULL)
 	add_attr_value (attr, p);
     }
 
-  if (GET_CODE (XEXP (exp, 2)) == CONST)
+  if (GET_CODE (XEXP (def, 2)) == CONST)
     {
       attr->is_const = 1;
       if (attr->is_numeric)
-	error_with_line (lineno,
-			 "constant attributes may not take numeric values");
+	error_at (info->loc,
+		  "constant attributes may not take numeric values");
 
       /* Get rid of the CONST node.  It is allowed only at top-level.  */
-      XEXP (exp, 2) = XEXP (XEXP (exp, 2), 0);
+      XEXP (def, 2) = XEXP (XEXP (def, 2), 0);
     }
 
   if (! strcmp_check (attr->name, length_str) && ! attr->is_numeric)
-    error_with_line (lineno, "`length' attribute must take numeric values");
+    error_at (info->loc, "`length' attribute must take numeric values");
 
   /* Set up the default value.  */
-  XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
-  attr->default_val = get_attr_value (XEXP (exp, 2), attr, -2);
+  XEXP (def, 2) = check_attr_value (XEXP (def, 2), attr);
+  attr->default_val = get_attr_value (XEXP (def, 2), attr, -2);
 }
 
 /* Given a pattern for DEFINE_PEEPHOLE or DEFINE_INSN, return the number of
@@ -3258,31 +3259,32 @@  compares_alternatives_p (rtx exp)
 /* Process DEFINE_PEEPHOLE, DEFINE_INSN, and DEFINE_ASM_ATTRIBUTES.  */
 
 static void
-gen_insn (rtx exp, int lineno)
+gen_insn (md_rtx_info *info)
 {
   struct insn_def *id;
+  rtx def = info->def;
 
   id = oballoc (struct insn_def);
   id->next = defs;
   defs = id;
-  id->def = exp;
-  id->loc = file_location (read_md_filename, lineno);
+  id->def = def;
+  id->loc = info->loc;
 
-  switch (GET_CODE (exp))
+  switch (GET_CODE (def))
     {
     case DEFINE_INSN:
-      id->insn_code = insn_code_number;
+      id->insn_code = info->index;
       id->insn_index = insn_index_number;
-      id->num_alternatives = count_alternatives (exp);
+      id->num_alternatives = count_alternatives (def);
       if (id->num_alternatives == 0)
 	id->num_alternatives = 1;
       id->vec_idx = 4;
       break;
 
     case DEFINE_PEEPHOLE:
-      id->insn_code = insn_code_number;
+      id->insn_code = info->index;
       id->insn_index = insn_index_number;
-      id->num_alternatives = count_alternatives (exp);
+      id->num_alternatives = count_alternatives (def);
       if (id->num_alternatives == 0)
 	id->num_alternatives = 1;
       id->vec_idx = 3;
@@ -3305,16 +3307,16 @@  gen_insn (rtx exp, int lineno)
    true or annul false is specified, and make a `struct delay_desc'.  */
 
 static void
-gen_delay (rtx def, int lineno)
+gen_delay (md_rtx_info *info)
 {
   struct delay_desc *delay;
   int i;
 
+  rtx def = info->def;
   if (XVECLEN (def, 1) % 3 != 0)
     {
-      error_with_line (lineno,
-		       "number of elements in DEFINE_DELAY must"
-		       " be multiple of three");
+      error_at (info->loc, "number of elements in DEFINE_DELAY must"
+		" be multiple of three");
       return;
     }
 
@@ -3330,7 +3332,7 @@  gen_delay (rtx def, int lineno)
   delay->def = def;
   delay->num = ++num_delays;
   delay->next = delays;
-  delay->loc = file_location (read_md_filename, lineno);
+  delay->loc = info->loc;
   delays = delay;
 }
 
@@ -4723,14 +4725,14 @@  static struct insn_reserv **last_insn_re
 /* Store information from a DEFINE_INSN_RESERVATION for future
    attribute generation.  */
 static void
-gen_insn_reserv (rtx def, int lineno)
+gen_insn_reserv (md_rtx_info *info)
 {
   struct insn_reserv *decl = oballoc (struct insn_reserv);
-  file_location loc (read_md_filename, lineno);
+  rtx def = info->def;
 
   decl->name            = DEF_ATTR_STRING (XSTR (def, 0));
   decl->default_latency = XINT (def, 1);
-  decl->condexp         = check_attr_test (XEXP (def, 2), 0, loc);
+  decl->condexp         = check_attr_test (XEXP (def, 2), 0, info->loc);
   decl->insn_num        = n_insn_reservs;
   decl->bypassed	= false;
   decl->next            = 0;
@@ -4776,10 +4778,11 @@  gen_bypass_1 (const char *s, size_t len)
 }
 
 static void
-gen_bypass (rtx def)
+gen_bypass (md_rtx_info *info)
 {
   const char *p, *base;
 
+  rtx def = info->def;
   for (p = base = XSTR (def, 1); *p; p++)
     if (*p == ',')
       {
@@ -5150,11 +5153,10 @@  handle_arg (const char *arg)
 int
 main (int argc, char **argv)
 {
-  rtx desc;
   struct attr_desc *attr;
   struct insn_def *id;
-  rtx tem;
   int i;
+  int max_insn_code = 0;
 
   progname = "genattrtab";
 
@@ -5184,57 +5186,56 @@  main (int argc, char **argv)
 
   /* Read the machine description.  */
 
-  while (1)
+  md_rtx_info info;
+  while (read_md_rtx (&info))
     {
-      int lineno;
-
-      desc = read_md_rtx (&lineno, &insn_code_number);
-      if (desc == NULL)
-	break;
-
-      switch (GET_CODE (desc))
+      switch (GET_CODE (info.def))
 	{
 	case DEFINE_INSN:
 	case DEFINE_PEEPHOLE:
 	case DEFINE_ASM_ATTRIBUTES:
-	  gen_insn (desc, lineno);
+	  gen_insn (&info);
 	  break;
 
 	case DEFINE_ATTR:
 	case DEFINE_ENUM_ATTR:
-	  gen_attr (desc, lineno);
+	  gen_attr (&info);
 	  break;
 
 	case DEFINE_DELAY:
-	  gen_delay (desc, lineno);
+	  gen_delay (&info);
 	  break;
 
 	case DEFINE_INSN_RESERVATION:
-	  gen_insn_reserv (desc, lineno);
+	  gen_insn_reserv (&info);
 	  break;
 
 	case DEFINE_BYPASS:
-	  gen_bypass (desc);
+	  gen_bypass (&info);
 	  break;
 
 	default:
 	  break;
 	}
-      if (GET_CODE (desc) != DEFINE_ASM_ATTRIBUTES)
+      if (GET_CODE (info.def) != DEFINE_ASM_ATTRIBUTES)
 	insn_index_number++;
+      max_insn_code = info.index;
     }
 
   if (have_error)
     return FATAL_EXIT_CODE;
 
-  insn_code_number++;
+  max_insn_code++;
 
   /* If we didn't have a DEFINE_ASM_ATTRIBUTES, make a null one.  */
   if (! got_define_asm_attributes)
     {
-      tem = rtx_alloc (DEFINE_ASM_ATTRIBUTES);
-      XVEC (tem, 0) = rtvec_alloc (0);
-      gen_insn (tem, 0);
+      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.index = -1;
+      gen_insn (&info);
     }
 
   /* Expand DEFINE_DELAY information into new attribute.  */
@@ -5242,14 +5243,14 @@  main (int argc, char **argv)
     expand_delays ();
 
   /* Make `insn_alternatives'.  */
-  insn_alternatives = oballocvec (uint64_t, insn_code_number);
+  insn_alternatives = oballocvec (uint64_t, max_insn_code);
   for (id = defs; id; id = id->next)
     if (id->insn_code >= 0)
       insn_alternatives[id->insn_code]
 	= (((uint64_t) 1) << id->num_alternatives) - 1;
 
   /* Make `insn_n_alternatives'.  */
-  insn_n_alternatives = oballocvec (int, insn_code_number);
+  insn_n_alternatives = oballocvec (int, max_insn_code);
   for (id = defs; id; id = id->next)
     if (id->insn_code >= 0)
       insn_n_alternatives[id->insn_code] = id->num_alternatives;
@@ -5278,7 +5279,7 @@  main (int argc, char **argv)
   make_length_attrs ();
 
   /* Perform any possible optimizations to speed up compilation.  */
-  optimize_attrs ();
+  optimize_attrs (max_insn_code);
 
   /* Now write out all the `gen_attr_...' routines.  Do these before the
      special routines so that they get defined before they are used.  */
Index: gcc/genautomata.c
===================================================================
--- gcc/genautomata.c	2015-07-12 14:18:21.153357004 +0100
+++ gcc/genautomata.c	2015-07-12 20:41:11.300433721 +0100
@@ -1243,16 +1243,18 @@  get_str_vect (const char *str, int *els_
    This gives information about a unit contained in CPU.  We fill a
    struct unit_decl with information used later by `expand_automata'.  */
 static void
-gen_cpu_unit (rtx def)
+gen_cpu_unit (md_rtx_info *info)
 {
   decl_t decl;
   char **str_cpu_units;
   int vect_length;
   int i;
 
+  rtx def = info->def;
   str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
   if (str_cpu_units == NULL)
-    fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
+    fatal_at (info->loc, "invalid string `%s' in %s",
+	      XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
   for (i = 0; i < vect_length; i++)
     {
       decl = XCREATENODE (struct decl);
@@ -1272,17 +1274,19 @@  gen_cpu_unit (rtx def)
    This gives information about a unit contained in CPU.  We fill a
    struct unit_decl with information used later by `expand_automata'.  */
 static void
-gen_query_cpu_unit (rtx def)
+gen_query_cpu_unit (md_rtx_info *info)
 {
   decl_t decl;
   char **str_cpu_units;
   int vect_length;
   int i;
 
+  rtx def = info->def;
   str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
 				FALSE);
   if (str_cpu_units == NULL)
-    fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
+    fatal_at (info->loc, "invalid string `%s' in %s",
+	      XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
   for (i = 0; i < vect_length; i++)
     {
       decl = XCREATENODE (struct decl);
@@ -1301,7 +1305,7 @@  gen_query_cpu_unit (rtx def)
    in a struct bypass_decl with information used later by
    `expand_automata'.  */
 static void
-gen_bypass (rtx def)
+gen_bypass (md_rtx_info *info)
 {
   decl_t decl;
   char **out_patterns;
@@ -1310,12 +1314,15 @@  gen_bypass (rtx def)
   int in_length;
   int i, j;
 
+  rtx def = info->def;
   out_patterns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
   if (out_patterns == NULL)
-    fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
+    fatal_at (info->loc, "invalid string `%s' in %s",
+	      XSTR (def, 1), GET_RTX_NAME (GET_CODE (def)));
   in_patterns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
   if (in_patterns == NULL)
-    fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
+    fatal_at (info->loc, "invalid string `%s' in %s",
+	      XSTR (def, 2), GET_RTX_NAME (GET_CODE (def)));
   for (i = 0; i < out_length; i++)
     for (j = 0; j < in_length; j++)
       {
@@ -1336,7 +1343,7 @@  gen_bypass (rtx def)
    struct excl_rel_decl (excl) with information used later by
    `expand_automata'.  */
 static void
-gen_excl_set (rtx def)
+gen_excl_set (md_rtx_info *info)
 {
   decl_t decl;
   char **first_str_cpu_units;
@@ -1345,16 +1352,20 @@  gen_excl_set (rtx def)
   int length;
   int i;
 
+  rtx def = info->def;
   first_str_cpu_units
     = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
   if (first_str_cpu_units == NULL)
-    fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
+    fatal_at (info->loc, "invalid string `%s' in %s",
+	      XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
   second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
 				       FALSE);
   if (second_str_cpu_units == NULL)
-    fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
+    fatal_at (info->loc, "invalid string `%s' in %s",
+	      XSTR (def, 1), GET_RTX_NAME (GET_CODE (def)));
   length += first_vect_length;
-  decl = XCREATENODEVAR (struct decl, sizeof (struct decl) + (length - 1) * sizeof (char *));
+  decl = XCREATENODEVAR (struct decl, (sizeof (struct decl)
+				       + (length - 1) * sizeof (char *)));
   decl->mode = dm_excl;
   decl->pos = 0;
   DECL_EXCL (decl)->all_names_num = length;
@@ -1375,7 +1386,7 @@  gen_excl_set (rtx def)
    We fill a struct unit_pattern_rel_decl with information used later
    by `expand_automata'.  */
 static void
-gen_presence_absence_set (rtx def, int presence_p, int final_p)
+gen_presence_absence_set (md_rtx_info *info, int presence_p, int final_p)
 {
   decl_t decl;
   char **str_cpu_units;
@@ -1386,27 +1397,17 @@  gen_presence_absence_set (rtx def, int p
   int patterns_length;
   int i;
 
+  rtx def = info->def;
   str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
 				FALSE);
   if (str_cpu_units == NULL)
-    fatal ((presence_p
-	    ? (final_p
-	       ? "invalid first string `%s' in final_presence_set"
-	       : "invalid first string `%s' in presence_set")
-	    : (final_p
-	       ? "invalid first string `%s' in final_absence_set"
-	       : "invalid first string `%s' in absence_set")),
-	   XSTR (def, 0));
+    fatal_at (info->loc, "invalid string `%s' in %s",
+	      XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
   str_pattern_lists = get_str_vect (XSTR (def, 1),
 				    &patterns_length, ',', FALSE);
   if (str_pattern_lists == NULL)
-    fatal ((presence_p
-	    ? (final_p
-	       ? "invalid second string `%s' in final_presence_set"
-	       : "invalid second string `%s' in presence_set")
-	    : (final_p
-	       ? "invalid second string `%s' in final_absence_set"
-	       : "invalid second string `%s' in absence_set")), XSTR (def, 1));
+    fatal_at (info->loc, "invalid string `%s' in %s",
+	      XSTR (def, 1), GET_RTX_NAME (GET_CODE (def)));
   str_patterns = XOBNEWVEC (&irp, char **, patterns_length);
   for (i = 0; i < patterns_length; i++)
     {
@@ -1439,13 +1440,13 @@  gen_presence_absence_set (rtx def, int p
 
 /* Process a PRESENCE_SET.
 
-    This gives information about a cpu unit reservation requirements.
+   This gives information about a cpu unit reservation requirements.
    We fill a struct unit_pattern_rel_decl (presence) with information
    used later by `expand_automata'.  */
 static void
-gen_presence_set (rtx def)
+gen_presence_set (md_rtx_info *info)
 {
-  gen_presence_absence_set (def, TRUE, FALSE);
+  gen_presence_absence_set (info, TRUE, FALSE);
 }
 
 /* Process a FINAL_PRESENCE_SET.
@@ -1454,9 +1455,9 @@  gen_presence_set (rtx def)
    We fill a struct unit_pattern_rel_decl (presence) with information
    used later by `expand_automata'.  */
 static void
-gen_final_presence_set (rtx def)
+gen_final_presence_set (md_rtx_info *info)
 {
-  gen_presence_absence_set (def, TRUE, TRUE);
+  gen_presence_absence_set (info, TRUE, TRUE);
 }
 
 /* Process an ABSENCE_SET.
@@ -1465,9 +1466,9 @@  gen_final_presence_set (rtx def)
    We fill a struct unit_pattern_rel_decl (absence) with information
    used later by `expand_automata'.  */
 static void
-gen_absence_set (rtx def)
+gen_absence_set (md_rtx_info *info)
 {
-  gen_presence_absence_set (def, FALSE, FALSE);
+  gen_presence_absence_set (info, FALSE, FALSE);
 }
 
 /* Process a FINAL_ABSENCE_SET.
@@ -1476,9 +1477,9 @@  gen_absence_set (rtx def)
    We fill a struct unit_pattern_rel_decl (absence) with information
    used later by `expand_automata'.  */
 static void
-gen_final_absence_set (rtx def)
+gen_final_absence_set (md_rtx_info *info)
 {
-  gen_presence_absence_set (def, FALSE, TRUE);
+  gen_presence_absence_set (info, FALSE, TRUE);
 }
 
 /* Process a DEFINE_AUTOMATON.
@@ -1487,16 +1488,18 @@  gen_final_absence_set (rtx def)
    recognizing pipeline hazards.  We fill a struct automaton_decl
    with information used later by `expand_automata'.  */
 static void
-gen_automaton (rtx def)
+gen_automaton (md_rtx_info *info)
 {
   decl_t decl;
   char **str_automata;
   int vect_length;
   int i;
 
+  rtx def = info->def;
   str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
   if (str_automata == NULL)
-    fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
+    fatal_at (info->loc, "invalid string `%s' in %s",
+	      XSTR (def, 0), GET_RTX_NAME (GET_CODE (def)));
   for (i = 0; i < vect_length; i++)
     {
       decl = XCREATENODE (struct decl);
@@ -1512,28 +1515,30 @@  gen_automaton (rtx def)
    This gives information how to generate finite state automaton used
    for recognizing pipeline hazards.  */
 static void
-gen_automata_option (rtx def)
+gen_automata_option (md_rtx_info *info)
 {
-  if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
+  const char *option = XSTR (info->def, 0);
+  if (strcmp (option, NO_MINIMIZATION_OPTION + 1) == 0)
     no_minimization_flag = 1;
-  else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
+  else if (strcmp (option, TIME_OPTION + 1) == 0)
     time_flag = 1;
-  else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
+  else if (strcmp (option, STATS_OPTION + 1) == 0)
     stats_flag = 1;
-  else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
+  else if (strcmp (option, V_OPTION + 1) == 0)
     v_flag = 1;
-  else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
+  else if (strcmp (option, W_OPTION + 1) == 0)
     w_flag = 1;
-  else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
+  else if (strcmp (option, NDFA_OPTION + 1) == 0)
     ndfa_flag = 1;
-  else if (strcmp (XSTR (def, 0), COLLAPSE_OPTION + 1) == 0)
+  else if (strcmp (option, COLLAPSE_OPTION + 1) == 0)
     collapse_flag = 1;
-  else if (strcmp (XSTR (def, 0), NO_COMB_OPTION + 1) == 0)
+  else if (strcmp (option, NO_COMB_OPTION + 1) == 0)
     no_comb_flag = 1;
-  else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
+  else if (strcmp (option, PROGRESS_OPTION + 1) == 0)
     progress_flag = 1;
   else
-    fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
+    fatal_at (info->loc, "invalid option `%s' in %s",
+	      option, GET_RTX_NAME (GET_CODE (info->def)));
 }
 
 /* Name in reservation to denote absence reservation.  */
@@ -1703,10 +1708,11 @@  gen_regexp (const char *str)
    in a struct reserv_decl with information used later by
    `expand_automata'.  */
 static void
-gen_reserv (rtx def)
+gen_reserv (md_rtx_info *info)
 {
   decl_t decl;
 
+  rtx def = info->def;
   decl = XCREATENODE (struct decl);
   decl->mode = dm_reserv;
   decl->pos = 0;
@@ -1721,10 +1727,11 @@  gen_reserv (rtx def)
    insn.  We fill a struct insn_reserv_decl with information used
    later by `expand_automata'.  */
 static void
-gen_insn_reserv (rtx def)
+gen_insn_reserv (md_rtx_info *info)
 {
   decl_t decl;
 
+  rtx def = info->def;
   decl = XCREATENODE (struct decl);
   decl->mode = dm_insn_reserv;
   decl->pos = 0;
@@ -9587,77 +9594,67 @@  write_automata (void)
 int
 main (int argc, char **argv)
 {
-  rtx desc;
-
   progname = "genautomata";
 
   if (!init_rtx_reader_args_cb (argc, argv, parse_automata_opt))
     return (FATAL_EXIT_CODE);
 
   initiate_automaton_gen (argv);
-  while (1)
-    {
-      int lineno;
-      int insn_code_number;
-
-      desc = read_md_rtx (&lineno, &insn_code_number);
-      if (desc == NULL)
+  md_rtx_info info;
+  while (read_md_rtx (&info))
+    switch (GET_CODE (info.def))
+      {
+      case DEFINE_CPU_UNIT:
+	gen_cpu_unit (&info);
 	break;
 
-      switch (GET_CODE (desc))
-	{
-	case DEFINE_CPU_UNIT:
-	  gen_cpu_unit (desc);
-	  break;
-
-	case DEFINE_QUERY_CPU_UNIT:
-	  gen_query_cpu_unit (desc);
-	  break;
+      case DEFINE_QUERY_CPU_UNIT:
+	gen_query_cpu_unit (&info);
+	break;
 
-	case DEFINE_BYPASS:
-	  gen_bypass (desc);
-	  break;
+      case DEFINE_BYPASS:
+	gen_bypass (&info);
+	break;
 
-	case EXCLUSION_SET:
-	  gen_excl_set (desc);
-	  break;
+      case EXCLUSION_SET:
+	gen_excl_set (&info);
+	break;
 
-	case PRESENCE_SET:
-	  gen_presence_set (desc);
-	  break;
+      case PRESENCE_SET:
+	gen_presence_set (&info);
+	break;
 
-	case FINAL_PRESENCE_SET:
-	  gen_final_presence_set (desc);
-	  break;
+      case FINAL_PRESENCE_SET:
+	gen_final_presence_set (&info);
+	break;
 
-	case ABSENCE_SET:
-	  gen_absence_set (desc);
-	  break;
+      case ABSENCE_SET:
+	gen_absence_set (&info);
+	break;
 
-	case FINAL_ABSENCE_SET:
-	  gen_final_absence_set (desc);
-	  break;
+      case FINAL_ABSENCE_SET:
+	gen_final_absence_set (&info);
+	break;
 
-	case DEFINE_AUTOMATON:
-	  gen_automaton (desc);
-	  break;
+      case DEFINE_AUTOMATON:
+	gen_automaton (&info);
+	break;
 
-	case AUTOMATA_OPTION:
-	  gen_automata_option (desc);
-	  break;
+      case AUTOMATA_OPTION:
+	gen_automata_option (&info);
+	break;
 
-	case DEFINE_RESERVATION:
-	  gen_reserv (desc);
-	  break;
+      case DEFINE_RESERVATION:
+	gen_reserv (&info);
+	break;
 
-	case DEFINE_INSN_RESERVATION:
-	  gen_insn_reserv (desc);
-	  break;
+      case DEFINE_INSN_RESERVATION:
+	gen_insn_reserv (&info);
+	break;
 
-	default:
-	  break;
-	}
-    }
+      default:
+	break;
+      }
 
   if (have_error)
     return FATAL_EXIT_CODE;
Index: gcc/gencodes.c
===================================================================
--- gcc/gencodes.c	2015-07-12 14:18:07.691911409 +0100
+++ gcc/gencodes.c	2015-07-12 14:18:26.678112322 +0100
@@ -29,10 +29,10 @@  Software Foundation; either version 3, o
 #include "gensupport.h"
 
 static void
-gen_insn (rtx insn, int code)
+gen_insn (md_rtx_info *info)
 {
-  const char *name = XSTR (insn, 0);
-  int truth = maybe_eval_c_test (XSTR (insn, 2));
+  const char *name = XSTR (info->def, 0);
+  int truth = maybe_eval_c_test (XSTR (info->def, 2));
 
   /* Don't mention instructions whose names are the null string
      or begin with '*'.  They are in the machine description just
@@ -42,14 +42,13 @@  gen_insn (rtx insn, int code)
       if (truth == 0)
 	printf ("#define CODE_FOR_%s CODE_FOR_nothing\n", name);
       else
-	printf ("  CODE_FOR_%s = %d,\n", name, code);
+	printf ("  CODE_FOR_%s = %d,\n", name, info->index);
     }
 }
 
 int
 main (int argc, char **argv)
 {
-  rtx desc;
   int last = 1;
 
   progname = "gencodes";
@@ -73,20 +72,18 @@  enum insn_code {\n\
 
   /* Read the machine description.  */
 
-  while (1)
-    {
-      int line_no;
-      int insn_code_number;
-
-      desc = read_md_rtx (&line_no, &insn_code_number);
-      if (desc == NULL)
+  md_rtx_info info;
+  while (read_md_rtx (&info))
+    switch (GET_CODE (info.def))
+      {
+      case DEFINE_INSN:
+      case DEFINE_EXPAND:
+	gen_insn (&info);
+	last = info.index + 1;
 	break;
 
-      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
-	{
-	  gen_insn (desc, insn_code_number);
-	  last = insn_code_number + 1;
-	}
+      default:
+	break;
     }
 
   printf ("  LAST_INSN_CODE = %d\n\
Index: gcc/genconditions.c
===================================================================
--- gcc/genconditions.c	2015-07-12 14:18:22.160312408 +0100
+++ gcc/genconditions.c	2015-07-12 14:18:26.678112322 +0100
@@ -212,42 +212,36 @@  write_writer (void)
 int
 main (int argc, char **argv)
 {
-  rtx desc;
-  int pattern_lineno; /* not used */
-  int code;
-
   progname = "genconditions";
 
   if (!init_rtx_reader_args (argc, argv))
     return (FATAL_EXIT_CODE);
 
   /* Read the machine description.  */
-  while (1)
+  md_rtx_info info;
+  while (read_md_rtx (&info))
     {
-      desc = read_md_rtx (&pattern_lineno, &code);
-      if (desc == NULL)
-	break;
-
+      rtx def = info.def;
       /* N.B. define_insn_and_split, define_cond_exec are handled
 	 entirely within read_md_rtx; we never see them.  */
-      switch (GET_CODE (desc))
+      switch (GET_CODE (def))
 	{
-	default:
-	  break;
-
 	case DEFINE_INSN:
 	case DEFINE_EXPAND:
-	  add_c_test (XSTR (desc, 2), -1);
+	  add_c_test (XSTR (def, 2), -1);
 	  /* except.h needs to know whether there is an eh_return
 	     pattern in the machine description.  */
-	  if (!strcmp (XSTR (desc, 0), "eh_return"))
+	  if (!strcmp (XSTR (def, 0), "eh_return"))
 	    saw_eh_return = 1;
 	  break;
 
 	case DEFINE_SPLIT:
 	case DEFINE_PEEPHOLE:
 	case DEFINE_PEEPHOLE2:
-	  add_c_test (XSTR (desc, 1), -1);
+	  add_c_test (XSTR (def, 1), -1);
+	  break;
+
+	default:
 	  break;
 	}
     }
Index: gcc/genconfig.c
===================================================================
--- gcc/genconfig.c	2015-07-12 14:18:07.691911409 +0100
+++ gcc/genconfig.c	2015-07-12 14:18:26.679112278 +0100
@@ -51,11 +51,6 @@  static int max_insns_per_split = 1;
 static int dup_operands_seen_this_insn;
 
 static void walk_insn_part (rtx, int, int);
-static void gen_insn (rtx);
-static void gen_expand (rtx);
-static void gen_split (rtx);
-static void gen_peephole (rtx);
-static void gen_peephole2 (rtx);
 
 /* RECOG_P will be nonzero if this pattern was seen in a context where it will
    be used to recognize, rather than just generate an insn.
@@ -179,11 +174,12 @@  walk_insn_part (rtx part, int recog_p, i
 }
 
 static void
-gen_insn (rtx insn)
+gen_insn (md_rtx_info *info)
 {
   int i;
 
   /* Walk the insn pattern to gather the #define's status.  */
+  rtx insn = info->def;
   clobbers_seen_this_insn = 0;
   dup_operands_seen_this_insn = 0;
   if (XVEC (insn, 1) != 0)
@@ -199,7 +195,7 @@  gen_insn (rtx insn)
 /* Similar but scan a define_expand.  */
 
 static void
-gen_expand (rtx insn)
+gen_expand (md_rtx_info *info)
 {
   int i;
 
@@ -207,6 +203,7 @@  gen_expand (rtx insn)
 
   /* Note that we don't bother recording the number of MATCH_DUPs
      that occur in a gen_expand, because only reload cares about that.  */
+  rtx insn = info->def;
   if (XVEC (insn, 1) != 0)
     for (i = 0; i < XVECLEN (insn, 1); i++)
       {
@@ -225,12 +222,13 @@  gen_expand (rtx insn)
 /* Similar but scan a define_split.  */
 
 static void
-gen_split (rtx split)
+gen_split (md_rtx_info *info)
 {
   int i;
 
   /* Look through the patterns that are matched
      to compute the maximum operand number.  */
+  rtx split = info->def;
   for (i = 0; i < XVECLEN (split, 0); i++)
     walk_insn_part (XVECEXP (split, 0, i), 1, 0);
   /* Look at the number of insns this insn could split into.  */
@@ -239,23 +237,25 @@  gen_split (rtx split)
 }
 
 static void
-gen_peephole (rtx peep)
+gen_peephole (md_rtx_info *info)
 {
   int i;
 
   /* Look through the patterns that are matched
      to compute the maximum operand number.  */
+  rtx peep = info->def;
   for (i = 0; i < XVECLEN (peep, 0); i++)
     walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
 }
 
 static void
-gen_peephole2 (rtx peep)
+gen_peephole2 (md_rtx_info *info)
 {
   int i, n;
 
   /* Look through the patterns that are matched
      to compute the maximum operand number.  */
+  rtx peep = info->def;
   for (i = XVECLEN (peep, 0) - 1; i >= 0; --i)
     walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
 
@@ -271,8 +271,6 @@  gen_peephole2 (rtx peep)
 int
 main (int argc, char **argv)
 {
-  rtx desc;
-
   progname = "genconfig";
 
   if (!init_rtx_reader_args (argc, argv))
@@ -291,42 +289,35 @@  main (int argc, char **argv)
 
   /* Read the machine description.  */
 
-  while (1)
-    {
-      int line_no, insn_code_number = 0;
+  md_rtx_info info;
+  while (read_md_rtx (&info))
+    switch (GET_CODE (info.def))
+      {
+      case DEFINE_INSN:
+	gen_insn (&info);
+	break;
 
-      desc = read_md_rtx (&line_no, &insn_code_number);
-      if (desc == NULL)
+      case DEFINE_EXPAND:
+	gen_expand (&info);
 	break;
 
-      switch (GET_CODE (desc))
-	{
-  	  case DEFINE_INSN:
-	    gen_insn (desc);
-	    break;
-
-	  case DEFINE_EXPAND:
-	    gen_expand (desc);
-	    break;
-
-	  case DEFINE_SPLIT:
-	    gen_split (desc);
-	    break;
-
-	  case DEFINE_PEEPHOLE2:
-	    have_peephole2_flag = 1;
-	    gen_peephole2 (desc);
-	    break;
-
-	  case DEFINE_PEEPHOLE:
-	    have_peephole_flag = 1;
-	    gen_peephole (desc);
-	    break;
-
-	  default:
-	    break;
-	}
-    }
+      case DEFINE_SPLIT:
+	gen_split (&info);
+	break;
+
+      case DEFINE_PEEPHOLE2:
+	have_peephole2_flag = 1;
+	gen_peephole2 (&info);
+	break;
+
+      case DEFINE_PEEPHOLE:
+	have_peephole_flag = 1;
+	gen_peephole (&info);
+	break;
+
+      default:
+	break;
+      }
 
   printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
   printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
Index: gcc/genemit.c
===================================================================
--- gcc/genemit.c	2015-07-12 14:18:21.158356783 +0100
+++ gcc/genemit.c	2015-07-12 14:18:26.679112278 +0100
@@ -28,9 +28,6 @@  Software Foundation; either version 3, o
 #include "gensupport.h"
 
 
-static int insn_code_number;
-static int insn_index_number;
-
 /* Data structure for recording the patterns of insns that have CLOBBERs.
    We use this to output a function that adds these CLOBBERs to a
    previously-allocated PARALLEL expression.  */
@@ -299,7 +296,7 @@  gen_emit_seq (rtvec vec, char *used)
 /* Generate the `gen_...' function for a DEFINE_INSN.  */
 
 static void
-gen_insn (rtx insn, int lineno)
+gen_insn (md_rtx_info *info)
 {
   struct pattern_stats stats;
   int i;
@@ -308,6 +305,7 @@  gen_insn (rtx insn, int lineno)
      registers or MATCH_SCRATCHes.  If so, store away the information for
      later.  */
 
+  rtx insn = info->def;
   if (XVEC (insn, 1))
     {
       int has_hard_reg = 0;
@@ -329,7 +327,7 @@  gen_insn (rtx insn, int lineno)
 	  struct clobber_ent *link = XNEW (struct clobber_ent);
 	  int j;
 
-	  link->code_number = insn_code_number;
+	  link->code_number = info->index;
 
 	  /* See if any previous CLOBBER_LIST entry is the same as this
 	     one.  */
@@ -383,12 +381,12 @@  gen_insn (rtx insn, int lineno)
   if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*')
     return;
 
-  printf ("/* %s:%d */\n", read_md_filename, lineno);
+  printf ("/* %s:%d */\n", info->loc.filename, info->loc.lineno);
 
   /* Find out how many operands this function has.  */
   get_pattern_stats (&stats, XVEC (insn, 1));
   if (stats.max_dup_opno > stats.max_opno)
-    fatal ("match_dup operand number has no match_operand");
+    fatal_at (info->loc, "match_dup operand number has no match_operand");
 
   /* Output the function name and argument declarations.  */
   printf ("rtx\ngen_%s (", XSTR (insn, 0));
@@ -419,16 +417,18 @@  gen_insn (rtx insn, int lineno)
 /* Generate the `gen_...' function for a DEFINE_EXPAND.  */
 
 static void
-gen_expand (rtx expand)
+gen_expand (md_rtx_info *info)
 {
   struct pattern_stats stats;
   int i;
   char *used;
 
+  rtx expand = info->def;
   if (strlen (XSTR (expand, 0)) == 0)
-    fatal ("define_expand lacks a name");
+    fatal_at (info->loc, "define_expand lacks a name");
   if (XVEC (expand, 1) == 0)
-    fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));
+    fatal_at (info->loc, "define_expand for %s lacks a pattern",
+	      XSTR (expand, 0));
 
   /* Find out how many operands this function has.  */
   get_pattern_stats (&stats, XVEC (expand, 1));
@@ -517,21 +517,22 @@  gen_expand (rtx expand)
 /* Like gen_expand, but generates insns resulting from splitting SPLIT.  */
 
 static void
-gen_split (rtx split)
+gen_split (md_rtx_info *info)
 {
   struct pattern_stats stats;
   int i;
+  rtx split = info->def;
   const char *const name =
     ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split");
   const char *unused;
   char *used;
 
   if (XVEC (split, 0) == 0)
-    fatal ("define_%s (definition %d) lacks a pattern", name,
-	   insn_index_number);
+    fatal_at (info->loc, "%s lacks a pattern",
+	      GET_RTX_NAME (GET_CODE (split)));
   else if (XVEC (split, 2) == 0)
-    fatal ("define_%s (definition %d) lacks a replacement pattern", name,
-	   insn_index_number);
+    fatal_at (info->loc, "%s lacks a replacement pattern",
+	      GET_RTX_NAME (GET_CODE (split)));
 
   /* Find out how many operands this function has.  */
 
@@ -543,17 +544,18 @@  gen_split (rtx split)
   if (GET_CODE (split) == DEFINE_PEEPHOLE2)
     {
       printf ("extern rtx_insn *gen_%s_%d (rtx_insn *, rtx *);\n",
-	      name, insn_code_number);
-      printf ("rtx_insn *\ngen_%s_%d (rtx_insn *curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
-	      name, insn_code_number, unused);
+	      name, info->index);
+      printf ("rtx_insn *\ngen_%s_%d (rtx_insn *curr_insn ATTRIBUTE_UNUSED,"
+	      " rtx *operands%s)\n",
+	      name, info->index, unused);
     }
   else
     {
       printf ("extern rtx_insn *gen_split_%d (rtx_insn *, rtx *);\n",
-	      insn_code_number);
+	      info->index);
       printf ("rtx_insn *\ngen_split_%d "
 	      "(rtx_insn *curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
-	      insn_code_number, unused);
+	      info->index, unused);
     }
   printf ("{\n");
 
@@ -567,7 +569,7 @@  gen_split (rtx split)
 
   printf ("  if (dump_file)\n");
   printf ("    fprintf (dump_file, \"Splitting with gen_%s_%d\\n\");\n",
-	  name, insn_code_number);
+	  name, info->index);
 
   printf ("  start_sequence ();\n");
 
@@ -725,8 +727,6 @@  output_peephole2_scratches (rtx split)
 int
 main (int argc, char **argv)
 {
-  rtx desc;
-
   progname = "genemit";
 
   if (!init_rtx_reader_args (argc, argv))
@@ -735,9 +735,6 @@  main (int argc, char **argv)
   /* Assign sequential codes to all entries in the machine description
      in parallel with the tables in insn-output.c.  */
 
-  insn_code_number = 0;
-  insn_index_number = 0;
-
   printf ("/* Generated automatically by the program `genemit'\n\
 from the machine description file `md'.  */\n\n");
 
@@ -780,40 +777,32 @@  main (int argc, char **argv)
 
   /* Read the machine description.  */
 
-  while (1)
-    {
-      int line_no;
-
-      desc = read_md_rtx (&line_no, &insn_code_number);
-      if (desc == NULL)
+  md_rtx_info info;
+  while (read_md_rtx (&info))
+    switch (GET_CODE (info.def))
+      {
+      case DEFINE_INSN:
+	gen_insn (&info);
 	break;
 
-      switch (GET_CODE (desc))
-	{
-	case DEFINE_INSN:
-	  gen_insn (desc, line_no);
-	  break;
-
-	case DEFINE_EXPAND:
-	  printf ("/* %s:%d */\n", read_md_filename, line_no);
-	  gen_expand (desc);
-	  break;
+      case DEFINE_EXPAND:
+	printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno);
+	gen_expand (&info);
+	break;
 
-	case DEFINE_SPLIT:
-	  printf ("/* %s:%d */\n", read_md_filename, line_no);
-	  gen_split (desc);
-	  break;
+      case DEFINE_SPLIT:
+	printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno);
+	gen_split (&info);
+	break;
 
-	case DEFINE_PEEPHOLE2:
-	  printf ("/* %s:%d */\n", read_md_filename, line_no);
-	  gen_split (desc);
-	  break;
+      case DEFINE_PEEPHOLE2:
+	printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno);
+	gen_split (&info);
+	break;
 
-	default:
-	  break;
-	}
-      ++insn_index_number;
-    }
+      default:
+	break;
+      }
 
   /* Write out the routines to add CLOBBERs to a pattern and say whether they
      clobber a hard reg.  */
Index: gcc/genextract.c
===================================================================
--- gcc/genextract.c	2015-07-12 14:18:07.691911409 +0100
+++ gcc/genextract.c	2015-07-12 14:18:26.679112278 +0100
@@ -75,13 +75,11 @@  struct accum_extract
   vec<char> pathstr;
 };
 
-int line_no;
-
 /* Forward declarations.  */
-static void walk_rtx (rtx, struct accum_extract *);
+static void walk_rtx (md_rtx_info *, rtx, struct accum_extract *);
 
 static void
-gen_insn (rtx insn, int insn_code_number)
+gen_insn (md_rtx_info *info)
 {
   int i;
   unsigned int op_count, dup_count, j;
@@ -97,18 +95,19 @@  gen_insn (rtx insn, int insn_code_number
   /* Walk the insn's pattern, remembering at all times the path
      down to the walking point.  */
 
+  rtx insn = info->def;
   if (XVECLEN (insn, 1) == 1)
-    walk_rtx (XVECEXP (insn, 1, 0), &acc);
+    walk_rtx (info, XVECEXP (insn, 1, 0), &acc);
   else
     for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
       {
 	acc.pathstr.safe_push ('a' + i);
-	walk_rtx (XVECEXP (insn, 1, i), &acc);
+	walk_rtx (info, XVECEXP (insn, 1, i), &acc);
 	acc.pathstr.pop ();
       }
 
   link = XNEW (struct code_ptr);
-  link->insn_code = insn_code_number;
+  link->insn_code = info->index;
 
   /* See if we find something that already had this extraction method.  */
 
@@ -178,15 +177,17 @@  gen_insn (rtx insn, int insn_code_number
 /* Helper subroutine of walk_rtx: given a vec<locstr>, an index, and a
    string, insert the string at the index, which should either already
    exist and be NULL, or not yet exist within the vector.  In the latter
-   case the vector is enlarged as appropriate.  */
+   case the vector is enlarged as appropriate.  INFO describes the
+   containing define_* expression.  */
 static void
-VEC_safe_set_locstr (vec<locstr> *vp, unsigned int ix, char *str)
+VEC_safe_set_locstr (md_rtx_info *info, vec<locstr> *vp,
+		     unsigned int ix, char *str)
 {
   if (ix < (*vp).length ())
     {
       if ((*vp)[ix])
 	{
-	  message_with_line (line_no, "repeated operand number %d", ix);
+	  message_at (info->loc, "repeated operand number %d", ix);
 	  have_error = 1;
 	}
       else
@@ -213,7 +214,7 @@  VEC_char_to_string (vec<char> v)
 }
 
 static void
-walk_rtx (rtx x, struct accum_extract *acc)
+walk_rtx (md_rtx_info *info, rtx x, struct accum_extract *acc)
 {
   RTX_CODE code;
   int i, len, base;
@@ -233,20 +234,20 @@  walk_rtx (rtx x, struct accum_extract *a
 
     case MATCH_OPERAND:
     case MATCH_SCRATCH:
-      VEC_safe_set_locstr (&acc->oplocs, XINT (x, 0),
+      VEC_safe_set_locstr (info, &acc->oplocs, XINT (x, 0),
 			   VEC_char_to_string (acc->pathstr));
       break;
 
     case MATCH_OPERATOR:
     case MATCH_PARALLEL:
-      VEC_safe_set_locstr (&acc->oplocs, XINT (x, 0),
+      VEC_safe_set_locstr (info, &acc->oplocs, XINT (x, 0),
 			   VEC_char_to_string (acc->pathstr));
 
       base = (code == MATCH_OPERATOR ? '0' : 'a');
       for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
 	{
 	  acc->pathstr.safe_push (base + i);
-	  walk_rtx (XVECEXP (x, 2, i), acc);
+	  walk_rtx (info, XVECEXP (x, 2, i), acc);
 	  acc->pathstr.pop ();
         }
       return;
@@ -264,7 +265,7 @@  walk_rtx (rtx x, struct accum_extract *a
       for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
         {
 	  acc->pathstr.safe_push (base + i);
-	  walk_rtx (XVECEXP (x, 1, i), acc);
+	  walk_rtx (info, XVECEXP (x, 1, i), acc);
 	  acc->pathstr.pop ();
         }
       return;
@@ -280,7 +281,7 @@  walk_rtx (rtx x, struct accum_extract *a
       if (fmt[i] == 'e' || fmt[i] == 'u')
 	{
 	  acc->pathstr.safe_push ('0' + i);
-	  walk_rtx (XEXP (x, i), acc);
+	  walk_rtx (info, XEXP (x, i), acc);
 	  acc->pathstr.pop ();
 	}
       else if (fmt[i] == 'E')
@@ -289,7 +290,7 @@  walk_rtx (rtx x, struct accum_extract *a
 	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
 	    {
 	      acc->pathstr.safe_push ('a' + j);
-	      walk_rtx (XVECEXP (x, i, j), acc);
+	      walk_rtx (info, XVECEXP (x, i, j), acc);
 	      acc->pathstr.pop ();
 	    }
 	}
@@ -394,12 +395,10 @@  insn_extract (rtx_insn *insn)\n{\n\
 int
 main (int argc, char **argv)
 {
-  rtx desc;
   unsigned int i;
   struct extraction *p;
   struct code_ptr *link;
   const char *name;
-  int insn_code_number;
 
   progname = "genextract";
 
@@ -408,19 +407,26 @@  main (int argc, char **argv)
 
   /* Read the machine description.  */
 
-  while ((desc = read_md_rtx (&line_no, &insn_code_number)) != NULL)
-    {
-       if (GET_CODE (desc) == DEFINE_INSN)
-	 gen_insn (desc, insn_code_number);
+  md_rtx_info info;
+  while (read_md_rtx (&info))
+    switch (GET_CODE (info.def))
+      {
+      case DEFINE_INSN:
+	gen_insn (&info);
+	break;
 
-      else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
+      case DEFINE_PEEPHOLE:
 	{
 	  struct code_ptr *link = XNEW (struct code_ptr);
 
-	  link->insn_code = insn_code_number;
+	  link->insn_code = info.index;
 	  link->next = peepholes;
 	  peepholes = link;
 	}
+	break;
+
+      default:
+	break;
     }
 
   if (have_error)
Index: gcc/genflags.c
===================================================================
--- gcc/genflags.c	2015-07-12 14:18:07.691911409 +0100
+++ gcc/genflags.c	2015-07-12 14:18:26.679112278 +0100
@@ -43,7 +43,6 @@  static void max_operand_1 (rtx);
 static int num_operands (rtx);
 static void gen_proto (rtx);
 static void gen_macro (const char *, int, int);
-static void gen_insn (int, rtx);
 
 /* Count the number of match_operand's found.  */
 
@@ -187,8 +186,9 @@  gen_proto (rtx insn)
 }
 
 static void
-gen_insn (int line_no, rtx insn)
+gen_insn (md_rtx_info *info)
 {
+  rtx insn = info->def;
   const char *name = XSTR (insn, 0);
   const char *p;
   const char *lt, *gt;
@@ -198,18 +198,15 @@  gen_insn (int line_no, rtx insn)
   lt = strchr (name, '<');
   if (lt && strchr (lt + 1, '>'))
     {
-      message_with_line (line_no, "unresolved iterator");
-      have_error = 1;
+      error_at (info->loc, "unresolved iterator");
       return;
     }
 
   gt = strchr (name, '>');
   if (lt || gt)
     {
-      message_with_line (line_no,
-			 "unmatched angle brackets, likely "
-			 "an error in iterator syntax");
-      have_error = 1;
+      error_at (info->loc, "unmatched angle brackets, likely "
+		"an error in iterator syntax");
       return;
     }
 
@@ -249,7 +246,6 @@  gen_insn (int line_no, rtx insn)
 int
 main (int argc, char **argv)
 {
-  rtx desc;
   rtx dummy;
   rtx *insns;
   rtx *insn_ptr;
@@ -271,16 +267,18 @@  main (int argc, char **argv)
 
   /* Read the machine description.  */
 
-  while (1)
-    {
-      int line_no, insn_code_number = 0;
+  md_rtx_info info;
+  while (read_md_rtx (&info))
+    switch (GET_CODE (info.def))
+      {
+      case DEFINE_INSN:
+      case DEFINE_EXPAND:
+	gen_insn (&info);
+	break;
 
-      desc = read_md_rtx (&line_no, &insn_code_number);
-      if (desc == NULL)
+      default:
 	break;
-      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
-	gen_insn (line_no, desc);
-    }
+      }
 
   /* Print out the prototypes now.  */
   dummy = (rtx) 0;
Index: gcc/genmddump.c
===================================================================
--- gcc/genmddump.c	2015-07-12 14:18:07.691911409 +0100
+++ gcc/genmddump.c	2015-07-12 14:18:26.679112278 +0100
@@ -40,22 +40,17 @@  extern int main (int, char **);
 int
 main (int argc, char **argv)
 {
-  rtx desc;
-  int pattern_lineno;
-  int code; /* not used */
   progname = "genmddump";
 
   if (!init_rtx_reader_args (argc, argv))
     return (FATAL_EXIT_CODE);
 
   /* Read the machine description.  */
-  while (1)
+  md_rtx_info info;
+  while (read_md_rtx (&info))
     {
-      desc = read_md_rtx (&pattern_lineno, &code);
-      if (desc == NULL)
-	break;
-      printf (";; %s: %d\n", read_md_filename, pattern_lineno);
-      print_inline_rtx (stdout, desc, 0);
+      printf (";; %s: %d\n", info.loc.filename, info.loc.lineno);
+      print_inline_rtx (stdout, info.def, 0);
       printf ("\n\n");
     }
 
Index: gcc/genopinit.c
===================================================================
--- gcc/genopinit.c	2015-07-12 14:18:20.787373213 +0100
+++ gcc/genopinit.c	2015-07-12 14:18:26.679112278 +0100
@@ -243,8 +243,9 @@  match_pattern (pattern *p, const char *n
 }
 
 static void
-gen_insn (rtx insn)
+gen_insn (md_rtx_info *info)
 {
+  rtx insn = info->def;
   const char *name = XSTR (insn, 0);
   pattern p;
   unsigned pindex;
@@ -346,15 +347,18 @@  main (int argc, char **argv)
   s_file = open_outfile (source_file_name);
 
   /* Read the machine description.  */
-  while (1)
-    {
-      int line_no, insn_code_number = 0;
-      rtx desc = read_md_rtx (&line_no, &insn_code_number);
-      if (desc == NULL)
+  md_rtx_info info;
+  while (read_md_rtx (&info))
+    switch (GET_CODE (info.def))
+      {
+      case DEFINE_INSN:
+      case DEFINE_EXPAND:
+	gen_insn (&info);
 	break;
-      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
-	gen_insn (desc);
-    }
+
+      default:
+	break;
+      }
 
   /* Sort the collected patterns.  */
   patterns.qsort (pattern_cmp);
Index: gcc/genoutput.c
===================================================================
--- gcc/genoutput.c	2015-07-12 14:18:26.659113164 +0100
+++ gcc/genoutput.c	2015-07-12 14:18:26.680112234 +0100
@@ -103,12 +103,6 @@  static char general_mem[] = { TARGET_MEM
 static int n_occurrences		(int, const char *);
 static const char *strip_whitespace	(const char *);
 
-/* insns in the machine description are assigned sequential code numbers
-   that are used by insn-recog.c (produced by genrecog) to communicate
-   to insn-output.c (produced by this program).  */
-
-static int next_code_number;
-
 /* This counts all operands used in the md file.  The first is null.  */
 
 static int next_operand_number = 1;
@@ -184,10 +178,6 @@  static void place_operands (struct data
 static void process_template (struct data *, const char *);
 static void validate_insn_alternatives (struct data *);
 static void validate_insn_operands (struct data *);
-static void gen_insn (rtx, int);
-static void gen_peephole (rtx, int);
-static void gen_expand (rtx, int);
-static void gen_split (rtx, int);
 
 struct constraint_data
 {
@@ -205,7 +195,7 @@  static const char indep_constraints[] =
 constraints_by_letter_table[1 << CHAR_BIT];
 
 static int mdep_constraint_len (const char *, file_location, int);
-static void note_constraint (rtx, int);
+static void note_constraint (md_rtx_info *);
 
 static void
 output_prologue (void)
@@ -861,14 +851,15 @@  validate_optab_operands (struct data *d)
    a hairy output action, output a function for now.  */
 
 static void
-gen_insn (rtx insn, int lineno)
+gen_insn (md_rtx_info *info)
 {
   struct pattern_stats stats;
+  rtx insn = info->def;
   data *d = new data;
   int i;
 
-  d->code_number = next_code_number;
-  d->loc = file_location (read_md_filename, lineno);
+  d->code_number = info->index;
+  d->loc = info->loc;
   if (XSTR (insn, 0)[0])
     d->name = XSTR (insn, 0);
   else
@@ -902,14 +893,14 @@  gen_insn (rtx insn, int lineno)
    If the insn has a hairy output action, output it now.  */
 
 static void
-gen_peephole (rtx peep, int lineno)
+gen_peephole (md_rtx_info *info)
 {
   struct pattern_stats stats;
   data *d = new data;
   int i;
 
-  d->code_number = next_code_number;
-  d->loc = file_location (read_md_filename, lineno);
+  d->code_number = info->index;
+  d->loc = info->loc;
   d->name = 0;
 
   /* Build up the list in the same order as the insns are seen
@@ -923,6 +914,7 @@  gen_peephole (rtx peep, int lineno)
   /* Get the number of operands by scanning all the patterns of the
      peephole optimizer.  But ignore all the rest of the information
      thus obtained.  */
+  rtx peep = info->def;
   for (i = 0; i < XVECLEN (peep, 0); i++)
     scan_operands (d, XVECEXP (peep, 0, i), 0, 0);
 
@@ -940,14 +932,15 @@  gen_peephole (rtx peep, int lineno)
    only for the purposes of `insn_gen_function'.  */
 
 static void
-gen_expand (rtx insn, int lineno)
+gen_expand (md_rtx_info *info)
 {
   struct pattern_stats stats;
+  rtx insn = info->def;
   data *d = new data;
   int i;
 
-  d->code_number = next_code_number;
-  d->loc = file_location (read_md_filename, lineno);
+  d->code_number = info->index;
+  d->loc = info->loc;
   if (XSTR (insn, 0)[0])
     d->name = XSTR (insn, 0);
   else
@@ -984,14 +977,14 @@  gen_expand (rtx insn, int lineno)
    only for reasons of consistency and to simplify genrecog.  */
 
 static void
-gen_split (rtx split, int lineno)
+gen_split (md_rtx_info *info)
 {
   struct pattern_stats stats;
   data *d = new data;
   int i;
 
-  d->code_number = next_code_number;
-  d->loc = file_location (read_md_filename, lineno);
+  d->code_number = info->index;
+  d->loc = info->loc;
   d->name = 0;
 
   /* Build up the list in the same order as the insns are seen
@@ -1005,6 +998,7 @@  gen_split (rtx split, int lineno)
   /* Get the number of operands by scanning all the patterns of the
      split patterns.  But ignore all the rest of the information thus
      obtained.  */
+  rtx split = info->def;
   for (i = 0; i < XVECLEN (split, 0); i++)
     scan_operands (d, XVECEXP (split, 0, i), 0, 0);
 
@@ -1034,8 +1028,6 @@  extern int main (int, char **);
 int
 main (int argc, char **argv)
 {
-  rtx desc;
-
   progname = "genoutput";
 
   init_insn_for_nothing ();
@@ -1047,44 +1039,37 @@  main (int argc, char **argv)
 
   /* Read the machine description.  */
 
-  while (1)
-    {
-      int line_no;
-
-      desc = read_md_rtx (&line_no, &next_code_number);
-      if (desc == NULL)
+  md_rtx_info info;
+  while (read_md_rtx (&info))
+    switch (GET_CODE (info.def))
+      {
+      case DEFINE_INSN:
+	gen_insn (&info);
 	break;
 
-      switch (GET_CODE (desc))
-	{
-	case DEFINE_INSN:
-	  gen_insn (desc, line_no);
-	  break;
-
-	case DEFINE_PEEPHOLE:
-	  gen_peephole (desc, line_no);
-	  break;
+      case DEFINE_PEEPHOLE:
+	gen_peephole (&info);
+	break;
 
-	case DEFINE_EXPAND:
-	  gen_expand (desc, line_no);
-	  break;
+      case DEFINE_EXPAND:
+	gen_expand (&info);
+	break;
 
-	case DEFINE_SPLIT:
-	case DEFINE_PEEPHOLE2:
-	  gen_split (desc, line_no);
-	  break;
+      case DEFINE_SPLIT:
+      case DEFINE_PEEPHOLE2:
+	gen_split (&info);
+	break;
 
-	case DEFINE_CONSTRAINT:
-	case DEFINE_REGISTER_CONSTRAINT:
-	case DEFINE_ADDRESS_CONSTRAINT:
-	case DEFINE_MEMORY_CONSTRAINT:
-	  note_constraint (desc, line_no);
-	  break;
+      case DEFINE_CONSTRAINT:
+      case DEFINE_REGISTER_CONSTRAINT:
+      case DEFINE_ADDRESS_CONSTRAINT:
+      case DEFINE_MEMORY_CONSTRAINT:
+	note_constraint (&info);
+	break;
 
-	default:
-	  break;
-	}
-    }
+      default:
+	break;
+      }
 
   printf ("\n\n");
   output_operand_data ();
@@ -1134,15 +1119,14 @@  strip_whitespace (const char *s)
   return q;
 }
 
-/* Record just enough information about a constraint to allow checking
-   of operand constraint strings above, in validate_insn_alternatives.
-   Does not validate most properties of the constraint itself; does
-   enforce no duplicate names, no overlap with MI constraints, and no
-   prefixes.  EXP is the define_*constraint form, LINENO the line number
-   reported by the reader.  */
+/* Record just enough information about the constraint in *INFO to allow
+   checking of operand constraint strings above, in validate_insn_alternatives.
+   Does not validate most properties of the constraint itself; does enforce
+   no duplicate names, no overlap with MI constraints, and no prefixes.  */
 static void
-note_constraint (rtx exp, int lineno)
+note_constraint (md_rtx_info *info)
 {
+  rtx exp = info->def;
   const char *name = XSTR (exp, 0);
   struct constraint_data **iter, **slot, *new_cdata;
 
@@ -1153,12 +1137,12 @@  note_constraint (rtx exp, int lineno)
   if (strchr (indep_constraints, name[0]))
     {
       if (name[1] == '\0')
-	error_with_line (lineno, "constraint letter '%s' cannot be "
-			 "redefined by the machine description", name);
+	error_at (info->loc, "constraint letter '%s' cannot be "
+		  "redefined by the machine description", name);
       else
-	error_with_line (lineno, "constraint name '%s' cannot be defined by "
-			 "the machine description, as it begins with '%c'",
-			 name, name[0]);
+	error_at (info->loc, "constraint name '%s' cannot be defined by "
+		  "the machine description, as it begins with '%c'",
+		  name, name[0]);
       return;
     }
 
@@ -1175,20 +1159,20 @@  note_constraint (rtx exp, int lineno)
 
       if (!strcmp ((*iter)->name, name))
 	{
-	  error_with_line (lineno, "redefinition of constraint '%s'", name);
+	  error_at (info->loc, "redefinition of constraint '%s'", name);
 	  message_at ((*iter)->loc, "previous definition is here");
 	  return;
 	}
       else if (!strncmp ((*iter)->name, name, (*iter)->namelen))
 	{
-	  error_with_line (lineno, "defining constraint '%s' here", name);
+	  error_at (info->loc, "defining constraint '%s' here", name);
 	  message_at ((*iter)->loc, "renders constraint '%s' "
 		      "(defined here) a prefix", (*iter)->name);
 	  return;
 	}
       else if (!strncmp ((*iter)->name, name, namelen))
 	{
-	  error_with_line (lineno, "constraint '%s' is a prefix", name);
+	  error_at (info->loc, "constraint '%s' is a prefix", name);
 	  message_at ((*iter)->loc, "of constraint '%s' "
 		      "(defined here)", (*iter)->name);
 	  return;
@@ -1199,7 +1183,7 @@  note_constraint (rtx exp, int lineno)
   new (new_cdata) constraint_data ();
   strcpy (CONST_CAST (char *, new_cdata->name), name);
   new_cdata->namelen = namelen;
-  new_cdata->loc = file_location (read_md_filename, lineno);
+  new_cdata->loc = info->loc;
   new_cdata->next_this_letter = *slot;
   *slot = new_cdata;
 }
Index: gcc/genpeep.c
===================================================================
--- gcc/genpeep.c	2015-07-12 14:18:22.088315597 +0100
+++ gcc/genpeep.c	2015-07-12 14:18:26.680112234 +0100
@@ -46,14 +46,14 @@  struct link
 
 static int n_operands;
 
-static void gen_peephole (rtx, int);
 static void match_rtx (rtx, struct link *, int);
 static void print_path (struct link *);
 static void print_code (RTX_CODE);
 
 static void
-gen_peephole (rtx peep, int insn_code_number)
+gen_peephole (md_rtx_info *info)
 {
+  rtx peep = info->def;
   int ninsns = XVECLEN (peep, 0);
   int i;
 
@@ -66,16 +66,14 @@  gen_peephole (rtx peep, int insn_code_nu
       if (i > 0)
 	{
 	  printf ("  do { insn = NEXT_INSN (insn);\n");
-	  printf ("       if (insn == 0) goto L%d; }\n",
-		  insn_code_number);
+	  printf ("       if (insn == 0) goto L%d; }\n", info->index);
 	  printf ("  while (NOTE_P (insn)\n");
 	  printf ("\t || (NONJUMP_INSN_P (insn)\n");
 	  printf ("\t     && (GET_CODE (PATTERN (insn)) == USE\n");
 	  printf ("\t\t || GET_CODE (PATTERN (insn)) == CLOBBER)));\n");
 
 	  printf ("  if (LABEL_P (insn)\n\
-      || BARRIER_P (insn))\n    goto L%d;\n",
-		  insn_code_number);
+      || BARRIER_P (insn))\n    goto L%d;\n", info->index);
 	}
 
       printf ("  pat = PATTERN (insn);\n");
@@ -83,7 +81,7 @@  gen_peephole (rtx peep, int insn_code_nu
       /* Walk the insn's pattern, remembering at all times the path
 	 down to the walking point.  */
 
-      match_rtx (XVECEXP (peep, 0, i), NULL, insn_code_number);
+      match_rtx (XVECEXP (peep, 0, i), NULL, info->index);
     }
 
   /* We get this far if the pattern matches.
@@ -91,7 +89,7 @@  gen_peephole (rtx peep, int insn_code_nu
 
   if (XSTR (peep, 1) && XSTR (peep, 1)[0])
     printf ("  if (! (%s)) goto L%d;\n",
-	    XSTR (peep, 1), insn_code_number);
+	    XSTR (peep, 1), info->index);
 
   /* If that matches, construct new pattern and put it in the first insn.
      This new pattern will never be matched.
@@ -103,8 +101,7 @@  gen_peephole (rtx peep, int insn_code_nu
 
   /* Record this define_peephole's insn code in the insn,
      as if it had been recognized to match this.  */
-  printf ("  INSN_CODE (ins1) = %d;\n",
-	  insn_code_number);
+  printf ("  INSN_CODE (ins1) = %d;\n", info->index);
 
   /* Delete the remaining insns.  */
   if (ninsns > 1)
@@ -114,7 +111,7 @@  gen_peephole (rtx peep, int insn_code_nu
      cannot be zero.  */
   printf ("  return NEXT_INSN (insn);\n");
 
-  printf (" L%d:\n\n", insn_code_number);
+  printf (" L%d:\n\n", info->index);
 }
 
 static void
@@ -348,8 +345,6 @@  extern int main (int, char **);
 int
 main (int argc, char **argv)
 {
-  rtx desc;
-
   max_opno = -1;
 
   progname = "genpeep";
@@ -394,18 +389,17 @@  main (int argc, char **argv)
 
   /* Read the machine description.  */
 
-  while (1)
-    {
-      int line_no;
-      int insn_code_number;
-
-      desc = read_md_rtx (&line_no, &insn_code_number);
-      if (desc == NULL)
+  md_rtx_info info;
+  while (read_md_rtx (&info))
+    switch (GET_CODE (info.def))
+      {
+      case DEFINE_PEEPHOLE:
+	gen_peephole (&info);
 	break;
 
-      if (GET_CODE (desc) == DEFINE_PEEPHOLE)
-	gen_peephole (desc, insn_code_number);
-    }
+      default:
+	break;
+      }
 
   printf ("  return 0;\n}\n\n");
 
Index: gcc/genpreds.c
===================================================================
--- gcc/genpreds.c	2015-07-12 14:18:26.667112809 +0100
+++ gcc/genpreds.c	2015-07-12 14:18:26.680112234 +0100
@@ -91,10 +91,9 @@  validate_exp (rtx exp, const char *name,
 /* Predicates are defined with (define_predicate) or
    (define_special_predicate) expressions in the machine description.  */
 static void
-process_define_predicate (rtx defn, int lineno)
+process_define_predicate (md_rtx_info *info)
 {
-  validate_exp (XEXP (defn, 1), XSTR (defn, 0),
-		file_location (read_md_filename, lineno));
+  validate_exp (XEXP (info->def, 1), XSTR (info->def, 0), info->loc);
 }
 
 /* Given a predicate, if it has an embedded C block, write the block
@@ -936,20 +935,20 @@  add_constraint (const char *name, const
 /* Process a DEFINE_CONSTRAINT, DEFINE_MEMORY_CONSTRAINT, or
    DEFINE_ADDRESS_CONSTRAINT expression, C.  */
 static void
-process_define_constraint (rtx c, int lineno)
+process_define_constraint (md_rtx_info *info)
 {
-  add_constraint (XSTR (c, 0), 0, XEXP (c, 2),
-		  GET_CODE (c) == DEFINE_MEMORY_CONSTRAINT,
-		  GET_CODE (c) == DEFINE_ADDRESS_CONSTRAINT,
-		  file_location (read_md_filename, lineno));
+  add_constraint (XSTR (info->def, 0), 0, XEXP (info->def, 2),
+		  GET_CODE (info->def) == DEFINE_MEMORY_CONSTRAINT,
+		  GET_CODE (info->def) == DEFINE_ADDRESS_CONSTRAINT,
+		  info->loc);
 }
 
 /* Process a DEFINE_REGISTER_CONSTRAINT expression, C.  */
 static void
-process_define_register_constraint (rtx c, int lineno)
+process_define_register_constraint (md_rtx_info *info)
 {
-  add_constraint (XSTR (c, 0), XSTR (c, 1), 0, false, false,
-		  file_location (read_md_filename, lineno));
+  add_constraint (XSTR (info->def, 0), XSTR (info->def, 1),
+		  0, false, false, info->loc);
 }
 
 /* Put the constraints into enum order.  We want to keep constraints
@@ -1584,31 +1583,29 @@  parse_option (const char *opt)
 int
 main (int argc, char **argv)
 {
-  rtx defn;
-  int pattern_lineno, next_insn_code = 0;
-
   progname = argv[0];
   if (argc <= 1)
     fatal ("no input file name");
   if (!init_rtx_reader_args_cb (argc, argv, parse_option))
     return FATAL_EXIT_CODE;
 
-  while ((defn = read_md_rtx (&pattern_lineno, &next_insn_code)) != 0)
-    switch (GET_CODE (defn))
+  md_rtx_info info;
+  while (read_md_rtx (&info))
+    switch (GET_CODE (info.def))
       {
       case DEFINE_PREDICATE:
       case DEFINE_SPECIAL_PREDICATE:
-	process_define_predicate (defn, pattern_lineno);
+	process_define_predicate (&info);
 	break;
 
       case DEFINE_CONSTRAINT:
       case DEFINE_MEMORY_CONSTRAINT:
       case DEFINE_ADDRESS_CONSTRAINT:
-	process_define_constraint (defn, pattern_lineno);
+	process_define_constraint (&info);
 	break;
 
       case DEFINE_REGISTER_CONSTRAINT:
-	process_define_register_constraint (defn, pattern_lineno);
+	process_define_register_constraint (&info);
 	break;
 
       default:
Index: gcc/genrecog.c
===================================================================
--- gcc/genrecog.c	2015-07-12 14:18:20.370391681 +0100
+++ gcc/genrecog.c	2015-07-12 20:52:12.069368786 +0100
@@ -250,12 +250,6 @@  enum routine_type {
   SUBPATTERN, RECOG, SPLIT, PEEPHOLE2
 };
 
-/* Next number to use as an insn_code.  */
-static int next_insn_code;
-
-/* The line number of the start of the pattern currently being processed.  */
-static int pattern_lineno;
-
 /* The root position (x0).  */
 static struct position root_pos;
 
@@ -469,12 +463,13 @@  constraints_supported_in_insn_p (rtx ins
 	   || GET_CODE (insn) == DEFINE_PEEPHOLE2);
 }
 
-/* Check for various errors in patterns.  SET is nonnull for a destination,
-   and is the complete set pattern.  SET_CODE is '=' for normal sets, and
-   '+' within a context that requires in-out constraints.  */
+/* Check for various errors in PATTERN, which is part of INFO.
+   SET is nonnull for a destination, and is the complete set pattern.
+   SET_CODE is '=' for normal sets, and '+' within a context that
+   requires in-out constraints.  */
 
 static void
-validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
+validate_pattern (rtx pattern, md_rtx_info *info, rtx set, int set_code)
 {
   const char *fmt;
   RTX_CODE code;
@@ -488,13 +483,12 @@  validate_pattern (rtx pattern, rtx insn,
       {
 	const char constraints0 = XSTR (pattern, 1)[0];
 
-	if (!constraints_supported_in_insn_p (insn))
+	if (!constraints_supported_in_insn_p (info->def))
 	  {
 	    if (constraints0)
 	      {
-		error_with_line (pattern_lineno,
-				 "constraints not supported in %s",
-				 rtx_name[GET_CODE (insn)]);
+		error_at (info->loc, "constraints not supported in %s",
+			  GET_RTX_NAME (GET_CODE (info->def)));
 	      }
 	    return;
 	  }
@@ -506,19 +500,17 @@  validate_pattern (rtx pattern, rtx insn,
 	    && constraints0 != '='
 	    && constraints0 != '+')
 	  {
-	    error_with_line (pattern_lineno,
-			     "operand %d missing output reload",
-			     XINT (pattern, 0));
+	    error_at (info->loc, "operand %d missing output reload",
+		      XINT (pattern, 0));
 	  }
 	return;
       }
     case MATCH_DUP:
     case MATCH_OP_DUP:
     case MATCH_PAR_DUP:
-      if (find_operand (insn, XINT (pattern, 0), pattern) == pattern)
-	error_with_line (pattern_lineno,
-			 "operand %i duplicated before defined",
-			 XINT (pattern, 0));
+      if (find_operand (info->def, XINT (pattern, 0), pattern) == pattern)
+	error_at (info->loc, "operand %i duplicated before defined",
+		  XINT (pattern, 0));
       break;
     case MATCH_OPERAND:
     case MATCH_OPERATOR:
@@ -527,17 +519,16 @@  validate_pattern (rtx pattern, rtx insn,
 	const struct pred_data *pred;
 	const char *c_test;
 
-	if (GET_CODE (insn) == DEFINE_INSN)
-	  c_test = XSTR (insn, 2);
+	if (GET_CODE (info->def) == DEFINE_INSN)
+	  c_test = XSTR (info->def, 2);
 	else
-	  c_test = XSTR (insn, 1);
+	  c_test = XSTR (info->def, 1);
 
 	if (pred_name[0] != 0)
 	  {
 	    pred = lookup_predicate (pred_name);
 	    if (!pred)
-	      error_with_line (pattern_lineno, "unknown predicate '%s'",
-			       pred_name);
+	      error_at (info->loc, "unknown predicate '%s'", pred_name);
 	  }
 	else
 	  pred = 0;
@@ -547,13 +538,12 @@  validate_pattern (rtx pattern, rtx insn,
 	    const char *constraints = XSTR (pattern, 2);
 	    const char constraints0 = constraints[0];
 
-	    if (!constraints_supported_in_insn_p (insn))
+	    if (!constraints_supported_in_insn_p (info->def))
 	      {
 		if (constraints0)
 		  {
-		    error_with_line (pattern_lineno,
-				     "constraints not supported in %s",
-				     rtx_name[GET_CODE (insn)]);
+		    error_at (info->loc, "constraints not supported in %s",
+			      GET_RTX_NAME (GET_CODE (info->def)));
 		  }
 	      }
 
@@ -567,17 +557,16 @@  validate_pattern (rtx pattern, rtx insn,
 		    /* If we've only got an output reload for this operand,
 		       we'd better have a matching input operand.  */
 		    else if (constraints0 == '='
-			     && find_matching_operand (insn, XINT (pattern, 0)))
+			     && find_matching_operand (info->def,
+						       XINT (pattern, 0)))
 		      ;
 		    else
-		      error_with_line (pattern_lineno,
-				       "operand %d missing in-out reload",
-				       XINT (pattern, 0));
+		      error_at (info->loc, "operand %d missing in-out reload",
+				XINT (pattern, 0));
 		  }
 		else if (constraints0 != '=' && constraints0 != '+')
-		  error_with_line (pattern_lineno,
-				   "operand %d missing output reload",
-				   XINT (pattern, 0));
+		  error_at (info->loc, "operand %d missing output reload",
+			    XINT (pattern, 0));
 	      }
 
 	    /* For matching constraint in MATCH_OPERAND, the digit must be a
@@ -597,10 +586,9 @@  validate_pattern (rtx pattern, rtx insn,
 
 		    sscanf (constraints, "%d", &val);
 		    if (val >= XINT (pattern, 0))
-		      error_with_line (pattern_lineno,
-				       "constraint digit %d is not smaller than"
-				       " operand %d",
-				       val, XINT (pattern, 0));
+		      error_at (info->loc, "constraint digit %d is not"
+				" smaller than operand %d",
+				val, XINT (pattern, 0));
 		  }
 
 		while (constraints[0] && constraints[0] != ',')
@@ -612,9 +600,8 @@  validate_pattern (rtx pattern, rtx insn,
 	   while not likely to occur at runtime, results in less efficient
 	   code from insn-recog.c.  */
 	if (set && pred && pred->allows_non_lvalue)
-	  error_with_line (pattern_lineno,
-			   "destination operand %d allows non-lvalue",
-			   XINT (pattern, 0));
+	  error_at (info->loc, "destination operand %d allows non-lvalue",
+		    XINT (pattern, 0));
 
 	/* A modeless MATCH_OPERAND can be handy when we can check for
 	   multiple modes in the c_test.  In most other cases, it is a
@@ -626,7 +613,7 @@  validate_pattern (rtx pattern, rtx insn,
 
 	if (GET_MODE (pattern) == VOIDmode
 	    && code == MATCH_OPERAND
-	    && GET_CODE (insn) == DEFINE_INSN
+	    && GET_CODE (info->def) == DEFINE_INSN
 	    && pred
 	    && !pred->special
 	    && pred->allows_non_const
@@ -634,9 +621,8 @@  validate_pattern (rtx pattern, rtx insn,
 	    && ! (set
 		  && GET_CODE (set) == SET
 		  && GET_CODE (SET_SRC (set)) == CALL))
-	  message_with_line (pattern_lineno,
-			     "warning: operand %d missing mode?",
-			     XINT (pattern, 0));
+	  message_at (info->loc, "warning: operand %d missing mode?",
+		      XINT (pattern, 0));
 	return;
       }
 
@@ -658,12 +644,12 @@  validate_pattern (rtx pattern, rtx insn,
 	if (GET_CODE (dest) == MATCH_DUP
 	    || GET_CODE (dest) == MATCH_OP_DUP
 	    || GET_CODE (dest) == MATCH_PAR_DUP)
-	  dest = find_operand (insn, XINT (dest, 0), NULL);
+	  dest = find_operand (info->def, XINT (dest, 0), NULL);
 
 	if (GET_CODE (src) == MATCH_DUP
 	    || GET_CODE (src) == MATCH_OP_DUP
 	    || GET_CODE (src) == MATCH_PAR_DUP)
-	  src = find_operand (insn, XINT (src, 0), NULL);
+	  src = find_operand (info->def, XINT (src, 0), NULL);
 
 	dmode = GET_MODE (dest);
 	smode = GET_MODE (src);
@@ -677,9 +663,8 @@  validate_pattern (rtx pattern, rtx insn,
         /* The operands of a SET must have the same mode unless one
 	   is VOIDmode.  */
         else if (dmode != VOIDmode && smode != VOIDmode && dmode != smode)
-	  error_with_line (pattern_lineno,
-			   "mode mismatch in set: %smode vs %smode",
-			   GET_MODE_NAME (dmode), GET_MODE_NAME (smode));
+	  error_at (info->loc, "mode mismatch in set: %smode vs %smode",
+		    GET_MODE_NAME (dmode), GET_MODE_NAME (smode));
 
 	/* If only one of the operands is VOIDmode, and PC or CC0 is
 	   not involved, it's probably a mistake.  */
@@ -694,36 +679,34 @@  validate_pattern (rtx pattern, rtx insn,
 	  {
 	    const char *which;
 	    which = (dmode == VOIDmode ? "destination" : "source");
-	    message_with_line (pattern_lineno,
-			       "warning: %s missing a mode?", which);
+	    message_at (info->loc, "warning: %s missing a mode?", which);
 	  }
 
 	if (dest != SET_DEST (pattern))
-	  validate_pattern (dest, insn, pattern, '=');
-	validate_pattern (SET_DEST (pattern), insn, pattern, '=');
-        validate_pattern (SET_SRC (pattern), insn, NULL_RTX, 0);
+	  validate_pattern (dest, info, pattern, '=');
+	validate_pattern (SET_DEST (pattern), info, pattern, '=');
+        validate_pattern (SET_SRC (pattern), info, NULL_RTX, 0);
         return;
       }
 
     case CLOBBER:
-      validate_pattern (SET_DEST (pattern), insn, pattern, '=');
+      validate_pattern (SET_DEST (pattern), info, pattern, '=');
       return;
 
     case ZERO_EXTRACT:
-      validate_pattern (XEXP (pattern, 0), insn, set, set ? '+' : 0);
-      validate_pattern (XEXP (pattern, 1), insn, NULL_RTX, 0);
-      validate_pattern (XEXP (pattern, 2), insn, NULL_RTX, 0);
+      validate_pattern (XEXP (pattern, 0), info, set, set ? '+' : 0);
+      validate_pattern (XEXP (pattern, 1), info, NULL_RTX, 0);
+      validate_pattern (XEXP (pattern, 2), info, NULL_RTX, 0);
       return;
 
     case STRICT_LOW_PART:
-      validate_pattern (XEXP (pattern, 0), insn, set, set ? '+' : 0);
+      validate_pattern (XEXP (pattern, 0), info, set, set ? '+' : 0);
       return;
 
     case LABEL_REF:
       if (GET_MODE (LABEL_REF_LABEL (pattern)) != VOIDmode)
-	error_with_line (pattern_lineno,
-			 "operand to label_ref %smode not VOIDmode",
-			 GET_MODE_NAME (GET_MODE (LABEL_REF_LABEL (pattern))));
+	error_at (info->loc, "operand to label_ref %smode not VOIDmode",
+		  GET_MODE_NAME (GET_MODE (LABEL_REF_LABEL (pattern))));
       break;
 
     default:
@@ -737,12 +720,12 @@  validate_pattern (rtx pattern, rtx insn,
       switch (fmt[i])
 	{
 	case 'e': case 'u':
-	  validate_pattern (XEXP (pattern, i), insn, NULL_RTX, 0);
+	  validate_pattern (XEXP (pattern, i), info, NULL_RTX, 0);
 	  break;
 
 	case 'E':
 	  for (j = 0; j < XVECLEN (pattern, i); j++)
-	    validate_pattern (XVECEXP (pattern, i, j), insn, NULL_RTX, 0);
+	    validate_pattern (XVECEXP (pattern, i, j), info, NULL_RTX, 0);
 	  break;
 
 	case 'i': case 'r': case 'w': case '0': case 's':
@@ -3823,7 +3806,7 @@  predicate_name (rtx match_rtx)
    TOP_PATTERN is the overall pattern, as passed to match_pattern_1.  */
 
 static state *
-match_pattern_2 (state *s, rtx top_pattern, position *pos, rtx pattern)
+match_pattern_2 (state *s, md_rtx_info *info, position *pos, rtx pattern)
 {
   auto_vec <pattern_pos, 32> worklist;
   auto_vec <pattern_pos, 32> pred_and_mode_tests;
@@ -3848,7 +3831,7 @@  match_pattern_2 (state *s, rtx top_patte
 	  dup_tests.safe_push (pattern_pos (pattern, pos));
 
 	  /* Use the same code check as the original operand.  */
-	  pattern = find_operand (top_pattern, XINT (pattern, 0), NULL_RTX);
+	  pattern = find_operand (info->def, XINT (pattern, 0), NULL_RTX);
 	  /* Fall through.  */
 
 	case MATCH_PARALLEL:
@@ -3865,16 +3848,13 @@  match_pattern_2 (state *s, rtx top_patte
 		if (code == GET_CODE (pattern))
 		  {
 		    if (!pred)
-		      error_with_line (pattern_lineno,
-				       "unknown predicate '%s'"
-				       " in '%s' expression",
-				       pred_name, GET_RTX_NAME (code));
+		      error_at (info->loc, "unknown predicate '%s' used in %s",
+				pred_name, GET_RTX_NAME (code));
 		    else if (code == MATCH_PARALLEL
 			     && pred->singleton != PARALLEL)
-		      error_with_line (pattern_lineno,
-				       "predicate '%s' used in match_parallel"
-				       " does not allow only PARALLEL",
-				       pred->name);
+		      error_at (info->loc, "predicate '%s' used in"
+				" match_parallel does not allow only PARALLEL",
+				pred->name);
 		  }
 	      }
 
@@ -4106,7 +4086,7 @@  match_pattern_2 (state *s, rtx top_patte
    to match, otherwise it is a single instruction pattern.  */
 
 static void
-match_pattern_1 (state *s, rtx top_pattern, const char *c_test,
+match_pattern_1 (state *s, md_rtx_info *info, rtx pattern, const char *c_test,
 		 acceptance_type acceptance)
 {
   if (acceptance.type == PEEPHOLE2)
@@ -4114,15 +4094,15 @@  match_pattern_1 (state *s, rtx top_patte
       /* Match each individual instruction.  */
       position **subpos_ptr = &peep2_insn_pos_list;
       int count = 0;
-      for (int i = 0; i < XVECLEN (top_pattern, 0); ++i)
+      for (int i = 0; i < XVECLEN (pattern, 0); ++i)
 	{
-	  rtx x = XVECEXP (top_pattern, 0, i);
+	  rtx x = XVECEXP (pattern, 0, i);
 	  position *subpos = next_position (subpos_ptr, &root_pos,
 					    POS_PEEP2_INSN, count);
 	  if (count > 0)
 	    s = add_decision (s, rtx_test::peep2_count (count + 1),
 			      true, false);
-	  s = match_pattern_2 (s, top_pattern, subpos, x);
+	  s = match_pattern_2 (s, info, subpos, x);
 	  subpos_ptr = &subpos->next;
 	  count += 1;
 	}
@@ -4131,7 +4111,7 @@  match_pattern_1 (state *s, rtx top_patte
   else
     {
       /* Make the rtx itself.  */
-      s = match_pattern_2 (s, top_pattern, &root_pos, top_pattern);
+      s = match_pattern_2 (s, info, &root_pos, pattern);
 
       /* If the match is only valid when extra clobbers are added,
 	 make sure we're able to pass that information to the caller.  */
@@ -4152,7 +4132,7 @@  match_pattern_1 (state *s, rtx top_patte
    backtracking.  */
 
 static void
-match_pattern (state *s, rtx top_pattern, const char *c_test,
+match_pattern (state *s, md_rtx_info *info, rtx pattern, const char *c_test,
 	       acceptance_type acceptance)
 {
   if (merge_states_p)
@@ -4160,11 +4140,11 @@  match_pattern (state *s, rtx top_pattern
       state root;
       /* Add the decisions to a fresh state and then merge the full tree
 	 into the existing one.  */
-      match_pattern_1 (&root, top_pattern, c_test, acceptance);
+      match_pattern_1 (&root, info, pattern, c_test, acceptance);
       merge_into_state (s, &root);
     }
   else
-    match_pattern_1 (s, top_pattern, c_test, acceptance);
+    match_pattern_1 (s, info, pattern, c_test, acceptance);
 }
 
 /* Begin the output file.  */
@@ -5178,9 +5158,10 @@  print_subroutine_group (output_state *os
 /* Return the rtx pattern for the list of rtxes in a define_peephole2.  */
 
 static rtx
-get_peephole2_pattern (rtvec vec)
+get_peephole2_pattern (md_rtx_info *info)
 {
   int i, j;
+  rtvec vec = XVEC (info->def, 0);
   rtx pattern = rtx_alloc (SEQUENCE);
   XVEC (pattern, 0) = rtvec_alloc (GET_NUM_ELEM (vec));
   for (i = j = 0; i < GET_NUM_ELEM (vec); i++)
@@ -5195,7 +5176,7 @@  get_peephole2_pattern (rtvec vec)
     }
   XVECLEN (pattern, 0) = j;
   if (j == 0)
-    error_with_line (pattern_lineno, "empty define_peephole2");
+    error_at (info->loc, "empty define_peephole2");
   return pattern;
 }
 
@@ -5245,7 +5226,6 @@  remove_clobbers (acceptance_type *accept
 int
 main (int argc, char **argv)
 {
-  rtx desc;
   state insn_root, split_root, peephole2_root;
 
   progname = "genrecog";
@@ -5253,64 +5233,65 @@  main (int argc, char **argv)
   if (!init_rtx_reader_args (argc, argv))
     return (FATAL_EXIT_CODE);
 
-  next_insn_code = 0;
-
   write_header ();
 
   /* Read the machine description.  */
 
-  while (1)
+  md_rtx_info info;
+  while (read_md_rtx (&info))
     {
-      desc = read_md_rtx (&pattern_lineno, &next_insn_code);
-      if (desc == NULL)
-	break;
+      rtx def = info.def;
 
       acceptance_type acceptance;
       acceptance.partial_p = false;
-      acceptance.u.full.code = next_insn_code;
+      acceptance.u.full.code = info.index;
 
       rtx pattern;
-      switch (GET_CODE (desc))
+      switch (GET_CODE (def))
 	{
 	case DEFINE_INSN:
 	  {
 	    /* Match the instruction in the original .md form.  */
 	    acceptance.type = RECOG;
 	    acceptance.u.full.u.num_clobbers = 0;
-	    pattern = add_implicit_parallel (XVEC (desc, 1));
-	    validate_pattern (pattern, desc, NULL_RTX, 0);
-	    match_pattern (&insn_root, pattern, XSTR (desc, 2), acceptance);
+	    pattern = add_implicit_parallel (XVEC (def, 1));
+	    validate_pattern (pattern, &info, NULL_RTX, 0);
+	    match_pattern (&insn_root, &info, pattern,
+			   XSTR (def, 2), acceptance);
 
 	    /* If the pattern is a PARALLEL with trailing CLOBBERs,
 	       allow recog_for_combine to match without the clobbers.  */
 	    if (GET_CODE (pattern) == PARALLEL
 		&& remove_clobbers (&acceptance, &pattern))
-	      match_pattern (&insn_root, pattern, XSTR (desc, 2), acceptance);
+	      match_pattern (&insn_root, &info, pattern,
+			     XSTR (def, 2), acceptance);
 	    break;
 	  }
 
 	case DEFINE_SPLIT:
 	  acceptance.type = SPLIT;
-	  pattern = add_implicit_parallel (XVEC (desc, 0));
-	  validate_pattern (pattern, desc, NULL_RTX, 0);
-	  match_pattern (&split_root, pattern, XSTR (desc, 1), acceptance);
+	  pattern = add_implicit_parallel (XVEC (def, 0));
+	  validate_pattern (pattern, &info, NULL_RTX, 0);
+	  match_pattern (&split_root, &info, pattern,
+			 XSTR (def, 1), acceptance);
 
 	  /* Declare the gen_split routine that we'll call if the
 	     pattern matches.  The definition comes from insn-emit.c.  */
 	  printf ("extern rtx_insn *gen_split_%d (rtx_insn *, rtx *);\n",
-		  next_insn_code);
+		  info.index);
 	  break;
 
 	case DEFINE_PEEPHOLE2:
 	  acceptance.type = PEEPHOLE2;
-	  pattern = get_peephole2_pattern (XVEC (desc, 0));
-	  validate_pattern (pattern, desc, NULL_RTX, 0);
-	  match_pattern (&peephole2_root, pattern, XSTR (desc, 1), acceptance);
+	  pattern = get_peephole2_pattern (&info);
+	  validate_pattern (pattern, &info, NULL_RTX, 0);
+	  match_pattern (&peephole2_root, &info, pattern,
+			 XSTR (def, 1), acceptance);
 
 	  /* Declare the gen_peephole2 routine that we'll call if the
 	     pattern matches.  The definition comes from insn-emit.c.  */
 	  printf ("extern rtx_insn *gen_peephole2_%d (rtx_insn *, rtx *);\n",
-		  next_insn_code);
+		  info.index);
 	  break;
 
 	default:
Index: gcc/gentarget-def.c
===================================================================
--- gcc/gentarget-def.c	2015-07-12 14:18:07.691911409 +0100
+++ gcc/gentarget-def.c	2015-07-12 14:18:26.682112145 +0100
@@ -198,11 +198,27 @@  def_target_insn (const char *name, const
     printf ("CODE_FOR_%s\n", name);
 }
 
+/* Record the DEFINE_INSN or DEFINE_EXPAND described by INFO.  */
+
+static void
+add_insn (md_rtx_info *info)
+{
+  rtx def = info->def;
+  const char *name = XSTR (def, 0);
+  if (name[0] == 0 || name[0] == '*')
+    return;
+
+  hashval_t hash = htab_hash_string (name);
+  rtx *slot = insns->find_slot_with_hash (name, hash, INSERT);
+  if (*slot)
+    error_at (info->loc, "duplicate definition of '%s'", name);
+  else
+    *slot = def;
+}
+
 int
 main (int argc, char **argv)
 {
-  int insn_code_number = 0;
-
   progname = "gentarget-def";
 
   if (!init_rtx_reader_args (argc, argv))
@@ -212,30 +228,18 @@  main (int argc, char **argv)
   stubs = new hash_table <nofree_string_hash> (31);
   have_funcs = new hash_map <nofree_string_hash, const char *>;
 
-  while (1)
-    {
-      int line_no;
-      rtx desc = read_md_rtx (&line_no, &insn_code_number);
-      if (desc == NULL)
+  md_rtx_info info;
+  while (read_md_rtx (&info))
+    switch (GET_CODE (info.def))
+      {
+      case DEFINE_INSN:
+      case DEFINE_EXPAND:
+	add_insn (&info);
+	break;
+
+      default:
 	break;
-      if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
-	{
-	  const char *name = XSTR (desc, 0);
-	  if (name[0] != 0 && name[0] != '*')
-	    {
-	      hashval_t hash = htab_hash_string (name);
-	      rtx *slot = insns->find_slot_with_hash (name, hash, INSERT);
-	      if (*slot)
-		{
-		  message_with_line (line_no, "duplicate definition of '%s'",
-				     name);
-		  have_error = 1;
-		}
-	      else
-		*slot = desc;
-	    }
-	}
-    }
+      }
 
   printf ("/* Generated automatically by the program `gentarget-def'.  */\n");
   printf ("#ifndef GCC_INSN_TARGET_DEF_H\n");