diff gcc/read-rtl.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
line wrap: on
line diff
--- a/gcc/read-rtl.c	Fri Oct 27 22:46:09 2017 +0900
+++ b/gcc/read-rtl.c	Thu Oct 25 07:37:49 2018 +0900
@@ -1,5 +1,5 @@
 /* RTL reader for GCC.
-   Copyright (C) 1987-2017 Free Software Foundation, Inc.
+   Copyright (C) 1987-2018 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -72,6 +72,9 @@
      iterators.  */
   htab_t attrs, iterators;
 
+  /* The C++ type of the iterator, such as "machine_mode" for modes.  */
+  const char *type;
+
   /* Treat the given string as the name of a standard mode, etc., and
      return its integer value.  */
   int (*find_builtin) (const char *);
@@ -80,6 +83,9 @@
      If the iterator applies to operands, the second argument gives the
      operand index, otherwise it is ignored.  */
   void (*apply_iterator) (rtx, unsigned int, int);
+
+  /* Return the C token for the given standard mode, code, etc.  */
+  const char *(*get_c_token) (int);
 };
 
 /* Records one use of an iterator.  */
@@ -163,6 +169,12 @@
   PUT_MODE (x, (machine_mode) mode);
 }
 
+static const char *
+get_mode_token (int mode)
+{
+  return concat ("E_", GET_MODE_NAME (mode), "mode", NULL);
+}
+
 /* In compact dumps, the code of insns is prefixed with "c", giving "cinsn",
    "cnote" etc, and CODE_LABEL is special-cased as "clabel".  */
 
@@ -206,6 +218,15 @@
   PUT_CODE (x, (enum rtx_code) code);
 }
 
+static const char *
+get_code_token (int code)
+{
+  char *name = xstrdup (GET_RTX_NAME (code));
+  for (int i = 0; name[i]; ++i)
+    name[i] = TOUPPER (name[i]);
+  return name;
+}
+
 /* Implementations of the iterator_group callbacks for ints.  */
 
 /* Since GCC does not construct a table of valid constants,
@@ -222,7 +243,18 @@
 static void
 apply_int_iterator (rtx x, unsigned int index, int value)
 {
-  XINT (x, index) = value;
+  if (GET_CODE (x) == SUBREG)
+    SUBREG_BYTE (x) = value;
+  else
+    XINT (x, index) = value;
+}
+
+static const char *
+get_int_token (int value)
+{
+  char buffer[HOST_BITS_PER_INT + 1];
+  sprintf (buffer, "%d", value);
+  return xstrdup (buffer);
 }
 
 #ifdef GENERATOR_FILE
@@ -314,10 +346,11 @@
 }
 
 /* Map attribute string P to its current value.  Return null if the attribute
-   isn't known.  */
+   isn't known.  If ITERATOR_OUT is nonnull, store the associated iterator
+   there.  */
 
 static struct map_value *
-map_attr_string (const char *p)
+map_attr_string (const char *p, mapping **iterator_out = 0)
 {
   const char *attr;
   struct mapping *iterator;
@@ -366,7 +399,11 @@
 	     iterator value.  */
 	  for (v = m->values; v; v = v->next)
 	    if (v->number == iterator->current_value->number)
-	      return v;
+	      {
+		if (iterator_out)
+		  *iterator_out = iterator;
+		return v;
+	      }
 	}
     }
   return NULL;
@@ -542,6 +579,178 @@
   return 1;
 }
 
+/* Return a hash value for overloaded_name UNCAST_ONAME.  There shouldn't
+   be many instances of two overloaded_names having the same name but
+   different arguments, so hashing on the name should be good enough in
+   practice.  */
+
+static hashval_t
+overloaded_name_hash (const void *uncast_oname)
+{
+  const overloaded_name *oname = (const overloaded_name *) uncast_oname;
+  return htab_hash_string (oname->name);
+}
+
+/* Return true if two overloaded_names are similar enough to share
+   the same generated functions.  */
+
+static int
+overloaded_name_eq_p (const void *uncast_oname1, const void *uncast_oname2)
+{
+  const overloaded_name *oname1 = (const overloaded_name *) uncast_oname1;
+  const overloaded_name *oname2 = (const overloaded_name *) uncast_oname2;
+  if (strcmp (oname1->name, oname2->name) != 0
+      || oname1->arg_types.length () != oname2->arg_types.length ())
+    return 0;
+
+  for (unsigned int i = 0; i < oname1->arg_types.length (); ++i)
+    if (strcmp (oname1->arg_types[i], oname2->arg_types[i]) != 0)
+      return 0;
+
+  return 1;
+}
+
+/* Return true if X has an instruction name in XSTR (X, 0).  */
+
+static bool
+named_rtx_p (rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case DEFINE_EXPAND:
+    case DEFINE_INSN:
+    case DEFINE_INSN_AND_SPLIT:
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+/* Check whether ORIGINAL is a named pattern whose name starts with '@'.
+   If so, return the associated overloaded_name and add the iterator for
+   each argument to ITERATORS.  Return null otherwise.  */
+
+overloaded_name *
+md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators)
+{
+  /* Check for the leading '@'.  */
+  if (!named_rtx_p (original) || XSTR (original, 0)[0] != '@')
+    return NULL;
+
+  /* Remove the '@', so that no other code needs to worry about it.  */
+  const char *name = XSTR (original, 0);
+  copy_md_ptr_loc (name + 1, name);
+  name += 1;
+  XSTR (original, 0) = name;
+
+  /* Build a copy of the name without the '<...>' attribute strings.
+     Add the iterator associated with each such attribute string to ITERATORS
+     and add an associated argument to TMP_ONAME.  */
+  char *copy = ASTRDUP (name);
+  char *base = copy, *start, *end;
+  overloaded_name tmp_oname;
+  tmp_oname.arg_types.create (current_iterators.length ());
+  bool pending_underscore_p = false;
+  while ((start = strchr (base, '<')) && (end = strchr (start, '>')))
+    {
+      *end = 0;
+      mapping *iterator;
+      if (!map_attr_string (start + 1, &iterator))
+	fatal_with_file_and_line ("unknown iterator `%s'", start + 1);
+      *end = '>';
+
+      /* Remove a trailing underscore, so that we don't end a name
+	 with "_" or turn "_<...>_" into "__".  */
+      if (start != base && start[-1] == '_')
+	{
+	  start -= 1;
+	  pending_underscore_p = true;
+	}
+
+      /* Add the text between either the last '>' or the start of
+	 the string and this '<'.  */
+      obstack_grow (&m_string_obstack, base, start - base);
+      base = end + 1;
+
+      /* If there's a character we need to keep after the '>', check
+	 whether we should prefix it with a previously-dropped '_'.  */
+      if (base[0] != 0 && base[0] != '<')
+	{
+	  if (pending_underscore_p && base[0] != '_')
+	    obstack_1grow (&m_string_obstack, '_');
+	  pending_underscore_p = false;
+	}
+
+      /* Record an argument for ITERATOR.  */
+      iterators->safe_push (iterator);
+      tmp_oname.arg_types.safe_push (iterator->group->type);
+    }
+  if (base == copy)
+    fatal_with_file_and_line ("no iterator attributes in name `%s'", name);
+
+  size_t length = obstack_object_size (&m_string_obstack);
+  if (length == 0)
+    fatal_with_file_and_line ("`%s' only contains iterator attributes", name);
+
+  /* Get the completed name.  */
+  obstack_grow (&m_string_obstack, base, strlen (base) + 1);
+  char *new_name = XOBFINISH (&m_string_obstack, char *);
+  tmp_oname.name = new_name;
+
+  if (!m_overloads_htab)
+    m_overloads_htab = htab_create (31, overloaded_name_hash,
+				    overloaded_name_eq_p, NULL);
+
+  /* See whether another pattern had the same overload name and list
+     of argument types.  Create a new permanent one if not.  */
+  void **slot = htab_find_slot (m_overloads_htab, &tmp_oname, INSERT);
+  overloaded_name *oname = (overloaded_name *) *slot;
+  if (!oname)
+    {
+      *slot = oname = new overloaded_name;
+      oname->name = tmp_oname.name;
+      oname->arg_types = tmp_oname.arg_types;
+      oname->next = NULL;
+      oname->first_instance = NULL;
+      oname->next_instance_ptr = &oname->first_instance;
+
+      *m_next_overload_ptr = oname;
+      m_next_overload_ptr = &oname->next;
+    }
+  else
+    {
+      obstack_free (&m_string_obstack, new_name);
+      tmp_oname.arg_types.release ();
+    }
+
+  return oname;
+}
+
+/* Add an instance of ONAME for instruction pattern X.  ITERATORS[I]
+   gives the iterator associated with argument I of ONAME.  */
+
+static void
+add_overload_instance (overloaded_name *oname, vec<mapping *> iterators, rtx x)
+{
+  /* Create the instance.  */
+  overloaded_instance *instance = new overloaded_instance;
+  instance->next = NULL;
+  instance->arg_values.create (oname->arg_types.length ());
+  for (unsigned int i = 0; i < iterators.length (); ++i)
+    {
+      int value = iterators[i]->current_value->number;
+      const char *name = iterators[i]->group->get_c_token (value);
+      instance->arg_values.quick_push (name);
+    }
+  instance->name = XSTR (x, 0);
+  instance->insn = x;
+
+  /* Chain it onto the end of ONAME's list.  */
+  *oname->next_instance_ptr = instance;
+  oname->next_instance_ptr = &instance->next;
+}
+
 /* Expand all iterators in the current rtx, which is given as ORIGINAL.
    Build a list of expanded rtxes in the EXPR_LIST pointed to by QUEUE.  */
 
@@ -559,6 +768,10 @@
     {
       /* Raise an error if any attributes were used.  */
       apply_attribute_uses ();
+
+      if (named_rtx_p (original) && XSTR (original, 0)[0] == '@')
+	fatal_with_file_and_line ("'@' used without iterators");
+
       queue->safe_push (original);
       return;
     }
@@ -580,6 +793,11 @@
   htab_traverse (substs.iterators, add_current_iterators, NULL);
   gcc_assert (!current_iterators.is_empty ());
 
+  /* Check whether this is a '@' overloaded pattern.  */
+  auto_vec<mapping *, 16> iterators;
+  overloaded_name *oname
+    = rtx_reader_ptr->handle_overloaded_name (original, &iterators);
+
   for (;;)
     {
       /* Apply the current iterator values.  Accumulate a condition to
@@ -613,6 +831,10 @@
 						     v->number);
 	    }
 	}
+
+      if (oname)
+	add_overload_instance (oname, iterators, x);
+
       /* Add the new rtx to the end of the queue.  */
       queue->safe_push (x);
 
@@ -689,28 +911,36 @@
   modes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
   modes.iterators = htab_create (13, leading_string_hash,
 				 leading_string_eq_p, 0);
+  modes.type = "machine_mode";
   modes.find_builtin = find_mode;
   modes.apply_iterator = apply_mode_iterator;
+  modes.get_c_token = get_mode_token;
 
   codes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
   codes.iterators = htab_create (13, leading_string_hash,
 				 leading_string_eq_p, 0);
+  codes.type = "rtx_code";
   codes.find_builtin = find_code;
   codes.apply_iterator = apply_code_iterator;
+  codes.get_c_token = get_code_token;
 
   ints.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
   ints.iterators = htab_create (13, leading_string_hash,
 				 leading_string_eq_p, 0);
+  ints.type = "int";
   ints.find_builtin = find_int;
   ints.apply_iterator = apply_int_iterator;
+  ints.get_c_token = get_int_token;
 
   substs.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
   substs.iterators = htab_create (13, leading_string_hash,
 				 leading_string_eq_p, 0);
+  substs.type = "int";
   substs.find_builtin = find_int; /* We don't use it, anyway.  */
 #ifdef GENERATOR_FILE
   substs.apply_iterator = apply_subst_iterator;
 #endif
+  substs.get_c_token = get_int_token;
 
   lower = add_mapping (&modes, modes.attrs, "mode");
   upper = add_mapping (&modes, modes.attrs, "MODE");
@@ -1229,7 +1459,7 @@
 parse_reg_note_name (const char *string)
 {
   for (int i = 0; i < REG_NOTE_MAX; i++)
-    if (0 == strcmp (string, GET_REG_NOTE_NAME (i)))
+    if (strcmp (string, GET_REG_NOTE_NAME (i)) == 0)
       return i;
   fatal_with_file_and_line ("unrecognized REG_NOTE name: `%s'", string);
 }
@@ -1460,6 +1690,7 @@
 	struct obstack vector_stack;
 	int list_counter = 0;
 	rtvec return_vec = NULL_RTVEC;
+	rtx saved_rtx = NULL_RTX;
 
 	require_char_ws ('[');
 
@@ -1470,8 +1701,34 @@
 	    if (c == EOF)
 	      fatal_expected_char (']', c);
 	    unread_char (c);
-	    list_counter++;
-	    obstack_ptr_grow (&vector_stack, read_nested_rtx ());
+
+	    rtx value;
+	    int repeat_count = 1;
+	    if (c == 'r')
+	      {
+		/* Process "repeated xN" directive.  */
+		read_name (&name);
+		if (strcmp (name.string, "repeated"))
+		  fatal_with_file_and_line ("invalid directive \"%s\"\n",
+					    name.string);
+		read_name (&name);
+		if (!sscanf (name.string, "x%d", &repeat_count))
+		  fatal_with_file_and_line ("invalid repeat count \"%s\"\n",
+					    name.string);
+
+		/* We already saw one of the instances.  */
+		repeat_count--;
+		value = saved_rtx;
+	      }
+	    else
+	      value = read_nested_rtx ();
+
+	    for (; repeat_count > 0; repeat_count--)
+	      {
+		list_counter++;
+		obstack_ptr_grow (&vector_stack, value);
+	      }
+	    saved_rtx = value;
 	  }
 	if (list_counter > 0)
 	  {
@@ -1608,6 +1865,7 @@
 
     case 'i':
     case 'n':
+    case 'p':
       /* Can be an iterator or an integer constant.  */
       read_name (&name);
       record_potential_iterator_use (&ints, return_rtx, idx, name.string);