LCOV - code coverage report
Current view: top level - gcc - read-rtl.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 56.4 % 571 322
Test Date: 2026-02-28 14:20:25 Functions: 61.8 % 34 21
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* RTL reader for GCC.
       2              :    Copyright (C) 1987-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : /* This file is compiled twice: once for the generator programs
      21              :    once for the compiler.  */
      22              : #ifdef GENERATOR_FILE
      23              : #include "bconfig.h"
      24              : #else
      25              : #include "config.h"
      26              : #endif
      27              : 
      28              : /* Disable rtl checking; it conflicts with the iterator handling.  */
      29              : #undef ENABLE_RTL_CHECKING
      30              : 
      31              : #include "system.h"
      32              : #include "coretypes.h"
      33              : #include "tm.h"
      34              : #include "rtl.h"
      35              : #include "obstack.h"
      36              : #include "read-md.h"
      37              : #include "gensupport.h"
      38              : 
      39              : /* One element in a singly-linked list of (integer, string) pairs.  */
      40              : struct map_value {
      41              :   struct map_value *next;
      42              :   int number;
      43              :   const char *string;
      44              : };
      45              : 
      46              : /* Maps an iterator or attribute name to a list of (integer, string) pairs.
      47              :    The integers are iterator values; the strings are either C conditions
      48              :    or attribute values.  */
      49              : struct mapping {
      50              :   /* The name of the iterator or attribute.  */
      51              :   const char *name;
      52              : 
      53              :   /* The group (modes or codes) to which the iterator or attribute belongs.  */
      54              :   struct iterator_group *group;
      55              : 
      56              :   /* The list of (integer, string) pairs.  */
      57              :   struct map_value *values;
      58              : 
      59              :   /* For iterators, records the current value of the iterator.  */
      60              :   struct map_value *current_value;
      61              : };
      62              : 
      63              : /* A structure for abstracting the common parts of iterators.  */
      64              : struct iterator_group {
      65              :   /* Tables of "mapping" structures, one for attributes and one for
      66              :      iterators.  */
      67              :   htab_t attrs, iterators;
      68              : 
      69              :   /* The C++ type of the iterator, such as "machine_mode" for modes.  */
      70              :   const char *type;
      71              : 
      72              :   /* Treat the given string as the name of a standard mode, etc., and
      73              :      return its integer value.  */
      74              :   HOST_WIDE_INT (*find_builtin) (const char *);
      75              : 
      76              :   /* Make the given rtx use the iterator value given by the third argument.
      77              :      If the iterator applies to operands, the second argument gives the
      78              :      operand index, otherwise it is ignored.  */
      79              :   void (*apply_iterator) (rtx, unsigned int, HOST_WIDE_INT);
      80              : 
      81              :   /* Return the C token for the given standard mode, code, etc.  */
      82              :   const char *(*get_c_token) (int);
      83              : 
      84              :   /* True if each iterator name should be treated as an attribute that
      85              :      maps to the C token produced by get_c_token.  This means that for
      86              :      an iterator ITER, <ITER> can be used in strings to refer to the
      87              :      current value of ITER, as a C token.  */
      88              :   bool has_self_attr;
      89              : };
      90              : 
      91              : /* Records one use of an iterator.  */
      92              : struct iterator_use {
      93              :   /* The iterator itself.  */
      94              :   struct mapping *iterator;
      95              : 
      96              :   /* The location of the use, as passed to the apply_iterator callback.
      97              :      The index is the number of the operand that used the iterator
      98              :      if applicable, otherwise it is ignored.  */
      99              :   rtx x;
     100              :   unsigned int index;
     101              : };
     102              : 
     103              : /* Records one use of an attribute (the "<[iterator:]attribute>" syntax)
     104              :    in a non-string rtx field.  */
     105              : struct attribute_use {
     106              :   /* The group that describes the use site.  */
     107              :   struct iterator_group *group;
     108              : 
     109              :   /* The location at which the use occurs.  */
     110              :   file_location loc;
     111              : 
     112              :   /* The name of the attribute, possibly with an "iterator:" prefix.  */
     113              :   const char *value;
     114              : 
     115              :   /* The location of the use, as passed to GROUP's apply_iterator callback.
     116              :      The index is the number of the operand that used the iterator
     117              :      if applicable, otherwise it is ignored.  */
     118              :   rtx x;
     119              :   unsigned int index;
     120              : };
     121              : 
     122              : /* This struct is used to link subst_attr named ATTR_NAME with
     123              :    corresponding define_subst named ITER_NAME.  */
     124              : struct subst_attr_to_iter_mapping
     125              : {
     126              :     char *attr_name;
     127              :     char *iter_name;
     128              : };
     129              : 
     130              : /* Hash-table to store links between subst-attributes and
     131              :    define_substs.  */
     132              : htab_t subst_attr_to_iter_map = NULL;
     133              : /* This global stores name of subst-iterator which is currently being
     134              :    processed.  */
     135              : const char *current_iterator_name;
     136              : 
     137              : static void validate_const_int (const char *);
     138              : static void one_time_initialization (void);
     139              : 
     140              : /* Global singleton.  */
     141              : rtx_reader *rtx_reader_ptr = NULL;
     142              : 
     143              : /* The mode and code iterator structures.  */
     144              : static struct iterator_group modes, codes, ints, substs;
     145              : 
     146              : /* All iterators used in the current rtx.  */
     147              : static vec<mapping *> current_iterators;
     148              : 
     149              : /* The list of all iterator uses in the current rtx.  */
     150              : static vec<iterator_use> iterator_uses;
     151              : 
     152              : /* The list of all attribute uses in the current rtx.  */
     153              : static vec<attribute_use> attribute_uses;
     154              : 
     155              : /* Provide a version of a function to read a long long if the system does
     156              :    not provide one.  */
     157              : #if (HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG                     \
     158              :      && !HAVE_DECL_ATOLL                                                \
     159              :      && !defined (HAVE_ATOQ))
     160              : HOST_WIDE_INT atoll (const char *);
     161              : 
     162              : HOST_WIDE_INT
     163              : atoll (const char *p)
     164              : {
     165              :   int neg = 0;
     166              :   HOST_WIDE_INT tmp_wide;
     167              : 
     168              :   while (ISSPACE (*p))
     169              :     p++;
     170              :   if (*p == '-')
     171              :     neg = 1, p++;
     172              :   else if (*p == '+')
     173              :     p++;
     174              : 
     175              :   tmp_wide = 0;
     176              :   while (ISDIGIT (*p))
     177              :     {
     178              :       HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0');
     179              :       if (new_wide < tmp_wide)
     180              :         {
     181              :           /* Return INT_MAX equiv on overflow.  */
     182              :           tmp_wide = HOST_WIDE_INT_M1U >> 1;
     183              :           break;
     184              :         }
     185              :       tmp_wide = new_wide;
     186              :       p++;
     187              :     }
     188              : 
     189              :   if (neg)
     190              :     tmp_wide = -tmp_wide;
     191              :   return tmp_wide;
     192              : }
     193              : #endif
     194              : 
     195              : /* Implementations of the iterator_group callbacks for modes.  */
     196              : 
     197              : static HOST_WIDE_INT
     198         1044 : find_mode (const char *name)
     199              : {
     200         1044 :   int i;
     201              : 
     202        24735 :   for (i = 0; i < NUM_MACHINE_MODES; i++)
     203        24735 :     if (strcmp (GET_MODE_NAME (i), name) == 0)
     204         1044 :       return i;
     205              : 
     206            0 :   fatal_with_file_and_line ("unknown mode `%s'", name);
     207              : }
     208              : 
     209              : static void
     210         1044 : apply_mode_iterator (rtx x, unsigned int, HOST_WIDE_INT mode)
     211              : {
     212         1044 :   PUT_MODE (x, (machine_mode) mode);
     213         1044 : }
     214              : 
     215              : static const char *
     216            0 : get_mode_token (int mode)
     217              : {
     218            0 :   return concat ("E_", GET_MODE_NAME (mode), "mode", NULL);
     219              : }
     220              : 
     221              : /* In compact dumps, the code of insns is prefixed with "c", giving "cinsn",
     222              :    "cnote" etc, and CODE_LABEL is special-cased as "clabel".  */
     223              : 
     224              : struct compact_insn_name {
     225              :   RTX_CODE code;
     226              :   const char *name;
     227              : };
     228              : 
     229              : static const compact_insn_name compact_insn_names[] = {
     230              :   { DEBUG_INSN, "cdebug_insn" },
     231              :   { INSN, "cinsn" },
     232              :   { JUMP_INSN, "cjump_insn" },
     233              :   { CALL_INSN, "ccall_insn" },
     234              :   { JUMP_TABLE_DATA, "cjump_table_data" },
     235              :   { BARRIER, "cbarrier" },
     236              :   { CODE_LABEL, "clabel" },
     237              :   { NOTE, "cnote" }
     238              : };
     239              : 
     240              : /* Return the rtx code for NAME, or UNKNOWN if NAME isn't a valid rtx code.  */
     241              : 
     242              : static rtx_code
     243         2202 : maybe_find_code (const char *name)
     244              : {
     245       140913 :   for (int i = 0; i < NUM_RTX_CODE; i++)
     246       140452 :     if (strcmp (GET_RTX_NAME (i), name) == 0)
     247         1741 :       return (rtx_code) i;
     248              : 
     249         1914 :   for (int i = 0; i < (signed)ARRAY_SIZE (compact_insn_names); i++)
     250         1913 :     if (strcmp (compact_insn_names[i].name, name) == 0)
     251          460 :       return compact_insn_names[i].code;
     252              : 
     253              :   return UNKNOWN;
     254              : }
     255              : 
     256              : /* Implementations of the iterator_group callbacks for codes.  */
     257              : 
     258              : static HOST_WIDE_INT
     259         2202 : find_code (const char *name)
     260              : {
     261         2202 :   rtx_code code = maybe_find_code (name);
     262         2202 :   if (code == UNKNOWN)
     263            1 :     fatal_with_file_and_line ("unknown rtx code `%s'", name);
     264         2201 :   return code;
     265              : }
     266              : 
     267              : static void
     268            0 : apply_code_iterator (rtx x, unsigned int, HOST_WIDE_INT code)
     269              : {
     270            0 :   PUT_CODE (x, (enum rtx_code) code);
     271            0 : }
     272              : 
     273              : static const char *
     274            0 : get_code_token (int code)
     275              : {
     276            0 :   char *name = xstrdup (GET_RTX_NAME (code));
     277            0 :   for (int i = 0; name[i]; ++i)
     278            0 :     name[i] = TOUPPER (name[i]);
     279            0 :   return name;
     280              : }
     281              : 
     282              : /* Implementations of the iterator_group callbacks for ints.  */
     283              : 
     284              : /* Since GCC does not construct a table of valid constants,
     285              :    we have to accept any int as valid.  No cross-checking can
     286              :    be done.  */
     287              : 
     288              : static HOST_WIDE_INT
     289          244 : find_int (const char *name)
     290              : {
     291          244 :   HOST_WIDE_INT tmp;
     292              : 
     293          244 :   struct md_constant tmp_def;
     294          244 :   tmp_def.name = const_cast<char *> (name);
     295          244 :   auto htab = rtx_reader_ptr->get_md_constants ();
     296          244 :   if (auto def = (struct md_constant *) htab_find (htab, &tmp_def))
     297            0 :     name = def->value;
     298              : 
     299          244 :   validate_const_int (name);
     300              : #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
     301              :   tmp = atoi (name);
     302              : #else
     303              : #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
     304          244 :   tmp = atol (name);
     305              : #else
     306              :   /* Prefer atoll over atoq, since the former is in the ISO C99 standard.
     307              :      But prefer not to use our hand-rolled function above either.  */
     308              : #if HAVE_DECL_ATOLL || !defined(HAVE_ATOQ)
     309              :   tmp = atoll (name);
     310              : #else
     311              :   tmp = atoq (name);
     312              : #endif
     313              : #endif
     314              : #endif
     315          244 :   return tmp;
     316              : }
     317              : 
     318              : static void
     319          244 : apply_int_iterator (rtx x, unsigned int index, HOST_WIDE_INT value)
     320              : {
     321          244 :   RTX_CODE code = GET_CODE (x);
     322          244 :   const char *format_ptr = GET_RTX_FORMAT (code);
     323              : 
     324          244 :   switch (format_ptr[index])
     325              :     {
     326            0 :     case 'i':
     327            0 :     case 'n':
     328            0 :       XINT (x, index) = value;
     329            0 :       break;
     330            0 :     case 'L':
     331            0 :       XLOC (x, index) = value;
     332            0 :       break;
     333          240 :     case 'w':
     334          240 :       XWINT (x, index) = value;
     335          240 :       break;
     336            4 :     case 'p':
     337            4 :       gcc_assert (code == SUBREG);
     338            4 :       SUBREG_BYTE (x) = value;
     339            4 :       break;
     340            0 :     default:
     341            0 :       gcc_unreachable ();
     342              :     }
     343          244 : }
     344              : 
     345              : static const char *
     346            0 : get_int_token (int value)
     347              : {
     348            0 :   char buffer[HOST_BITS_PER_INT + 1];
     349            0 :   sprintf (buffer, "%d", value);
     350            0 :   return xstrdup (buffer);
     351              : }
     352              : 
     353              : #ifdef GENERATOR_FILE
     354              : 
     355              : /* This routine adds attribute or does nothing depending on VALUE.  When
     356              :    VALUE is 1, it does nothing - the first duplicate of original
     357              :    template is kept untouched when it's subjected to a define_subst.
     358              :    When VALUE isn't 1, the routine modifies RTL-template RT, adding
     359              :    attribute, named exactly as define_subst, which later will be
     360              :    applied.  If such attribute has already been added, then no the
     361              :    routine has no effect.  */
     362              : static void
     363              : apply_subst_iterator (rtx rt, unsigned int, HOST_WIDE_INT value)
     364              : {
     365              :   rtx new_attr;
     366              :   rtvec attrs_vec, new_attrs_vec;
     367              :   int i;
     368              :   /* define_split has no attributes.  */
     369              :   if (value == 1 || GET_CODE (rt) == DEFINE_SPLIT)
     370              :     return;
     371              :   gcc_assert (GET_CODE (rt) == DEFINE_INSN
     372              :               || GET_CODE (rt) == DEFINE_INSN_AND_SPLIT
     373              :               || GET_CODE (rt) == DEFINE_INSN_AND_REWRITE
     374              :               || GET_CODE (rt) == DEFINE_EXPAND);
     375              : 
     376              :   int attrs = (GET_CODE (rt) == DEFINE_INSN_AND_SPLIT ? 7
     377              :                : GET_CODE (rt) == DEFINE_INSN_AND_REWRITE ? 6 : 4);
     378              :   attrs_vec = XVEC (rt, attrs);
     379              : 
     380              :   /* If we've already added attribute 'current_iterator_name', then we
     381              :      have nothing to do now.  */
     382              :   if (attrs_vec)
     383              :     {
     384              :       for (i = 0; i < GET_NUM_ELEM (attrs_vec); i++)
     385              :         {
     386              :           if (strcmp (XSTR (attrs_vec->elem[i], 0), current_iterator_name) == 0)
     387              :             return;
     388              :         }
     389              :     }
     390              : 
     391              :   /* Add attribute with subst name - it serves as a mark for
     392              :      define_subst which later would be applied to this pattern.  */
     393              :   new_attr = rtx_alloc (SET_ATTR);
     394              :   PUT_CODE (new_attr, SET_ATTR);
     395              :   XSTR (new_attr, 0) = xstrdup (current_iterator_name);
     396              :   XSTR (new_attr, 1) = xstrdup ("yes");
     397              : 
     398              :   if (!attrs_vec)
     399              :     {
     400              :       new_attrs_vec = rtvec_alloc (1);
     401              :       new_attrs_vec->elem[0] = new_attr;
     402              :     }
     403              :   else
     404              :     {
     405              :       new_attrs_vec = rtvec_alloc (GET_NUM_ELEM (attrs_vec) + 1);
     406              :       memcpy (&new_attrs_vec->elem[0], &attrs_vec->elem[0],
     407              :               GET_NUM_ELEM (attrs_vec) * sizeof (rtx));
     408              :       new_attrs_vec->elem[GET_NUM_ELEM (attrs_vec)] = new_attr;
     409              :     }
     410              :   XVEC (rt, attrs) = new_attrs_vec;
     411              : }
     412              : 
     413              : /* Map subst-attribute ATTR to subst iterator ITER.  */
     414              : 
     415              : static void
     416              : bind_subst_iter_and_attr (const char *iter, const char *attr)
     417              : {
     418              :   struct subst_attr_to_iter_mapping *value;
     419              :   void **slot;
     420              :   if (!subst_attr_to_iter_map)
     421              :     subst_attr_to_iter_map =
     422              :       htab_create (1, leading_string_hash, leading_string_eq_p, 0);
     423              :   value = XNEW (struct subst_attr_to_iter_mapping);
     424              :   value->attr_name = xstrdup (attr);
     425              :   value->iter_name = xstrdup (iter);
     426              :   slot = htab_find_slot (subst_attr_to_iter_map, value, INSERT);
     427              :   *slot = value;
     428              : }
     429              : 
     430              : #endif /* #ifdef GENERATOR_FILE */
     431              : 
     432              : /* Return name of a subst-iterator, corresponding to subst-attribute ATTR.  */
     433              : 
     434              : static char*
     435            0 : find_subst_iter_by_attr (const char *attr)
     436              : {
     437            0 :   char *iter_name = NULL;
     438            0 :   struct subst_attr_to_iter_mapping *value;
     439            0 :   value = (struct subst_attr_to_iter_mapping*)
     440            0 :     htab_find (subst_attr_to_iter_map, &attr);
     441            0 :   if (value)
     442            0 :     iter_name = value->iter_name;
     443            0 :   return iter_name;
     444              : }
     445              : 
     446              : /* Map attribute string P to its current value.  Return null if the attribute
     447              :    isn't known.  If ITERATOR_OUT is nonnull, store the associated iterator
     448              :    there.  Report any errors against location LOC.  */
     449              : 
     450              : static struct map_value *
     451            0 : map_attr_string (file_location loc, const char *p, mapping **iterator_out = 0)
     452              : {
     453            0 :   const char *attr;
     454            0 :   struct mapping *iterator;
     455            0 :   unsigned int i;
     456            0 :   struct mapping *m;
     457            0 :   struct map_value *v;
     458            0 :   int iterator_name_len;
     459            0 :   struct map_value *res = NULL;
     460            0 :   struct mapping *prev = NULL;
     461              : 
     462              :   /* Peel off any "iterator:" prefix.  Set ATTR to the start of the
     463              :      attribute name.  */
     464            0 :   attr = strchr (p, ':');
     465            0 :   if (attr == 0)
     466              :     {
     467            0 :       iterator_name_len = -1;
     468            0 :       attr = p;
     469              :     }
     470              :   else
     471              :     {
     472            0 :       iterator_name_len = attr - p;
     473            0 :       attr++;
     474              :     }
     475              : 
     476            0 :   FOR_EACH_VEC_ELT (current_iterators, i, iterator)
     477              :     {
     478              :       /* If an iterator name was specified, check that it matches.  */
     479            0 :       if (iterator_name_len >= 0
     480            0 :           && (strncmp (p, iterator->name, iterator_name_len) != 0
     481            0 :               || iterator->name[iterator_name_len] != 0))
     482            0 :         continue;
     483              : 
     484            0 :       if (iterator->group->has_self_attr
     485            0 :           && strcmp (attr, iterator->name) == 0)
     486              :         {
     487            0 :           if (iterator_out)
     488            0 :             *iterator_out = iterator;
     489            0 :           int number = iterator->current_value->number;
     490            0 :           const char *string = iterator->group->get_c_token (number);
     491            0 :           if (res && strcmp (string, res->string) != 0)
     492              :             {
     493            0 :               error_at (loc, "ambiguous attribute '%s'; could be"
     494              :                         " '%s' (via '%s:%s') or '%s' (via '%s:%s')",
     495              :                         attr, res->string, prev->name, attr,
     496              :                         string, iterator->name, attr);
     497            0 :               return res;
     498              :             }
     499            0 :           prev = iterator;
     500            0 :           res = new map_value { nullptr, number, string };
     501              :         }
     502              : 
     503              :       /* Find the attribute specification.  */
     504            0 :       m = (struct mapping *) htab_find (iterator->group->attrs, &attr);
     505            0 :       if (m)
     506              :         {
     507              :           /* In contrast to code/mode/int iterators, attributes of subst
     508              :              iterators are linked to one specific subst-iterator.  So, if
     509              :              we are dealing with subst-iterator, we should check if it's
     510              :              the one which linked with the given attribute.  */
     511            0 :           if (iterator->group == &substs)
     512              :             {
     513            0 :               char *iter_name = find_subst_iter_by_attr (attr);
     514            0 :               if (strcmp (iter_name, iterator->name) != 0)
     515            0 :                 continue;
     516              :             }
     517              :           /* Find the attribute value associated with the current
     518              :              iterator value.  */
     519            0 :           for (v = m->values; v; v = v->next)
     520            0 :             if (v->number == iterator->current_value->number)
     521              :               {
     522            0 :                 if (res && strcmp (v->string, res->string) != 0)
     523              :                   {
     524            0 :                     error_at (loc, "ambiguous attribute '%s'; could be"
     525              :                               " '%s' (via '%s:%s') or '%s' (via '%s:%s')",
     526              :                               attr, res->string, prev->name, attr,
     527              :                               v->string, iterator->name, attr);
     528            0 :                     return v;
     529              :                   }
     530            0 :                 if (iterator_out)
     531            0 :                   *iterator_out = iterator;
     532              :                 prev = iterator;
     533              :                 res = v;
     534              :               }
     535              :         }
     536              :     }
     537              :   return res;
     538              : }
     539              : 
     540              : /* Apply the current iterator values to STRING.  Return the new string
     541              :    if any changes were needed, otherwise return STRING itself.  */
     542              : 
     543              : const char *
     544            0 : md_reader::apply_iterator_to_string (const char *string)
     545              : {
     546            0 :   char *base, *copy, *p, *start, *end;
     547            0 :   struct map_value *v;
     548              : 
     549            0 :   if (string == 0 || string[0] == 0)
     550              :     return string;
     551              : 
     552            0 :   file_location loc = get_md_ptr_loc (string)->loc;
     553            0 :   base = p = copy = ASTRDUP (string);
     554            0 :   while ((start = strchr (p, '<')) && (end = strchr (start, '>')))
     555              :     {
     556            0 :       p = start + 1;
     557              : 
     558            0 :       *end = 0;
     559            0 :       v = map_attr_string (loc, p);
     560            0 :       *end = '>';
     561            0 :       if (v == 0)
     562            0 :         continue;
     563              : 
     564              :       /* Add everything between the last copied byte and the '<',
     565              :          then add in the attribute value.  */
     566            0 :       obstack_grow (&m_string_obstack, base, start - base);
     567            0 :       obstack_grow (&m_string_obstack, v->string, strlen (v->string));
     568            0 :       base = end + 1;
     569              :     }
     570            0 :   if (base != copy)
     571              :     {
     572            0 :       obstack_grow (&m_string_obstack, base, strlen (base) + 1);
     573            0 :       copy = XOBFINISH (&m_string_obstack, char *);
     574            0 :       copy_md_ptr_loc (copy, string);
     575            0 :       return copy;
     576              :     }
     577              :   return string;
     578              : }
     579              : 
     580              : /* Return a deep copy of X, substituting the current iterator
     581              :    values into any strings.  */
     582              : 
     583              : rtx
     584            0 : md_reader::copy_rtx_for_iterators (rtx original)
     585              : {
     586            0 :   const char *format_ptr, *p;
     587            0 :   int i, j;
     588            0 :   rtx x;
     589              : 
     590            0 :   if (original == 0)
     591              :     return original;
     592              : 
     593              :   /* Create a shallow copy of ORIGINAL.  */
     594            0 :   x = rtx_alloc (GET_CODE (original));
     595            0 :   memcpy (x, original, RTX_CODE_SIZE (GET_CODE (original)));
     596              : 
     597              :   /* Change each string and recursively change each rtx.  */
     598            0 :   format_ptr = GET_RTX_FORMAT (GET_CODE (original));
     599            0 :   for (i = 0; format_ptr[i] != 0; i++)
     600            0 :     switch (format_ptr[i])
     601              :       {
     602              :       case 'T':
     603            0 :         while (XTMPL (x, i) != (p = apply_iterator_to_string (XTMPL (x, i))))
     604            0 :           XTMPL (x, i) = p;
     605              :         break;
     606              : 
     607              :       case 'S':
     608              :       case 's':
     609            0 :         while (XSTR (x, i) != (p = apply_iterator_to_string (XSTR (x, i))))
     610            0 :           XSTR (x, i) = p;
     611              :         break;
     612              : 
     613            0 :       case 'e':
     614            0 :         XEXP (x, i) = copy_rtx_for_iterators (XEXP (x, i));
     615            0 :         break;
     616              : 
     617            0 :       case 'V':
     618            0 :       case 'E':
     619            0 :         if (XVEC (original, i))
     620              :           {
     621            0 :             XVEC (x, i) = rtvec_alloc (XVECLEN (original, i));
     622            0 :             for (j = 0; j < XVECLEN (x, i); j++)
     623            0 :               XVECEXP (x, i, j)
     624            0 :                 = copy_rtx_for_iterators (XVECEXP (original, i, j));
     625              :           }
     626              :         break;
     627              : 
     628              :       default:
     629              :         break;
     630              :       }
     631              :   return x;
     632              : }
     633              : 
     634              : #ifdef GENERATOR_FILE
     635              : 
     636              : /* Return a condition that must satisfy both ORIGINAL and EXTRA.  If ORIGINAL
     637              :    has the form "&& ..." (as used in define_insn_and_splits), assume that
     638              :    EXTRA is already satisfied.  Empty strings are treated like "true".  */
     639              : 
     640              : static const char *
     641              : add_condition_to_string (const char *original, const char *extra)
     642              : {
     643              :   if (original != 0 && original[0] == '&' && original[1] == '&')
     644              :     return original;
     645              :   return rtx_reader_ptr->join_c_conditions (original, extra);
     646              : }
     647              : 
     648              : /* Like add_condition, but applied to all conditions in rtx X.  */
     649              : 
     650              : static void
     651              : add_condition_to_rtx (rtx x, const char *extra)
     652              : {
     653              :   switch (GET_CODE (x))
     654              :     {
     655              :     case DEFINE_INSN:
     656              :     case DEFINE_EXPAND:
     657              :     case DEFINE_SUBST:
     658              :       XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra);
     659              :       break;
     660              : 
     661              :     case DEFINE_SPLIT:
     662              :     case DEFINE_PEEPHOLE:
     663              :     case DEFINE_PEEPHOLE2:
     664              :     case DEFINE_COND_EXEC:
     665              :       XSTR (x, 1) = add_condition_to_string (XSTR (x, 1), extra);
     666              :       break;
     667              : 
     668              :     case DEFINE_INSN_AND_SPLIT:
     669              :     case DEFINE_INSN_AND_REWRITE:
     670              :       XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra);
     671              :       XSTR (x, 4) = add_condition_to_string (XSTR (x, 4), extra);
     672              :       break;
     673              : 
     674              :     default:
     675              :       break;
     676              :     }
     677              : }
     678              : 
     679              : /* Apply the current iterator values to all attribute_uses.  */
     680              : 
     681              : static void
     682              : apply_attribute_uses (void)
     683              : {
     684              :   struct map_value *v;
     685              :   attribute_use *ause;
     686              :   unsigned int i;
     687              : 
     688              :   FOR_EACH_VEC_ELT (attribute_uses, i, ause)
     689              :     {
     690              :       v = map_attr_string (ause->loc, ause->value);
     691              :       if (!v)
     692              :         fatal_with_file_and_line ("unknown iterator value `%s'", ause->value);
     693              :       ause->group->apply_iterator (ause->x, ause->index,
     694              :                                    ause->group->find_builtin (v->string));
     695              :     }
     696              : }
     697              : 
     698              : /* A htab_traverse callback for iterators.  Add all used iterators
     699              :    to current_iterators.  */
     700              : 
     701              : static int
     702              : add_current_iterators (void **slot, void *data ATTRIBUTE_UNUSED)
     703              : {
     704              :   struct mapping *iterator;
     705              : 
     706              :   iterator = (struct mapping *) *slot;
     707              :   if (iterator->current_value)
     708              :     current_iterators.safe_push (iterator);
     709              :   return 1;
     710              : }
     711              : 
     712              : /* Return a hash value for overloaded_name UNCAST_ONAME.  There shouldn't
     713              :    be many instances of two overloaded_names having the same name but
     714              :    different arguments, so hashing on the name should be good enough in
     715              :    practice.  */
     716              : 
     717              : static hashval_t
     718              : overloaded_name_hash (const void *uncast_oname)
     719              : {
     720              :   const overloaded_name *oname = (const overloaded_name *) uncast_oname;
     721              :   return htab_hash_string (oname->name);
     722              : }
     723              : 
     724              : /* Return true if two overloaded_names are similar enough to share
     725              :    the same generated functions.  */
     726              : 
     727              : static int
     728              : overloaded_name_eq_p (const void *uncast_oname1, const void *uncast_oname2)
     729              : {
     730              :   const overloaded_name *oname1 = (const overloaded_name *) uncast_oname1;
     731              :   const overloaded_name *oname2 = (const overloaded_name *) uncast_oname2;
     732              :   if (strcmp (oname1->name, oname2->name) != 0
     733              :       || oname1->arg_types.length () != oname2->arg_types.length ())
     734              :     return 0;
     735              : 
     736              :   for (unsigned int i = 0; i < oname1->arg_types.length (); ++i)
     737              :     if (strcmp (oname1->arg_types[i], oname2->arg_types[i]) != 0)
     738              :       return 0;
     739              : 
     740              :   return 1;
     741              : }
     742              : 
     743              : /* Return true if X has an instruction name in XSTR (X, 0).  */
     744              : 
     745              : static bool
     746              : named_rtx_p (rtx x)
     747              : {
     748              :   switch (GET_CODE (x))
     749              :     {
     750              :     case DEFINE_EXPAND:
     751              :     case DEFINE_INSN:
     752              :     case DEFINE_INSN_AND_SPLIT:
     753              :     case DEFINE_INSN_AND_REWRITE:
     754              :       return true;
     755              : 
     756              :     default:
     757              :       return false;
     758              :     }
     759              : }
     760              : 
     761              : /* Check whether ORIGINAL is a named pattern whose name starts with '@'.
     762              :    If so, return the associated overloaded_name and add the iterator for
     763              :    each argument to ITERATORS.  Return null otherwise.  */
     764              : 
     765              : overloaded_name *
     766              : md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators)
     767              : {
     768              :   /* Check for the leading '@'.  */
     769              :   if (!named_rtx_p (original) || XSTR (original, 0)[0] != '@')
     770              :     return NULL;
     771              : 
     772              :   /* Remove the '@', so that no other code needs to worry about it.  */
     773              :   const char *name = XSTR (original, 0);
     774              :   file_location loc = get_md_ptr_loc (name)->loc;
     775              :   copy_md_ptr_loc (name + 1, name);
     776              :   name += 1;
     777              :   XSTR (original, 0) = name;
     778              : 
     779              :   /* Build a copy of the name without the '<...>' attribute strings.
     780              :      Add the iterator associated with each such attribute string to ITERATORS
     781              :      and add an associated argument to TMP_ONAME.  */
     782              :   char *copy = ASTRDUP (name);
     783              :   char *base = copy, *start, *end;
     784              :   overloaded_name tmp_oname;
     785              :   tmp_oname.arg_types.create (current_iterators.length ());
     786              :   bool pending_underscore_p = false;
     787              :   while ((start = strchr (base, '<')) && (end = strchr (start, '>')))
     788              :     {
     789              :       *end = 0;
     790              :       mapping *iterator;
     791              :       if (!map_attr_string (loc, start + 1, &iterator))
     792              :         fatal_with_file_and_line ("unknown iterator `%s'", start + 1);
     793              :       *end = '>';
     794              : 
     795              :       /* Remove a trailing underscore, so that we don't end a name
     796              :          with "_" or turn "_<...>_" into "__".  */
     797              :       if (start != base && start[-1] == '_')
     798              :         {
     799              :           start -= 1;
     800              :           pending_underscore_p = true;
     801              :         }
     802              : 
     803              :       /* Add the text between either the last '>' or the start of
     804              :          the string and this '<'.  */
     805              :       obstack_grow (&m_string_obstack, base, start - base);
     806              :       base = end + 1;
     807              : 
     808              :       /* If there's a character we need to keep after the '>', check
     809              :          whether we should prefix it with a previously-dropped '_'.  */
     810              :       if (base[0] != 0 && base[0] != '<')
     811              :         {
     812              :           if (pending_underscore_p && base[0] != '_')
     813              :             obstack_1grow (&m_string_obstack, '_');
     814              :           pending_underscore_p = false;
     815              :         }
     816              : 
     817              :       /* Skip define_subst iterators, since define_substs are allowed to
     818              :          add new match_operands in their output templates.  */
     819              :       if (iterator->group != &substs)
     820              :         {
     821              :           /* Record an argument for ITERATOR.  */
     822              :           iterators->safe_push (iterator);
     823              :           tmp_oname.arg_types.safe_push (iterator->group->type);
     824              :         }
     825              :     }
     826              :   if (base == copy)
     827              :     fatal_with_file_and_line ("no iterator attributes in name `%s'", name);
     828              : 
     829              :   size_t length = obstack_object_size (&m_string_obstack);
     830              :   if (length == 0)
     831              :     fatal_with_file_and_line ("`%s' only contains iterator attributes", name);
     832              : 
     833              :   /* Get the completed name.  */
     834              :   obstack_grow (&m_string_obstack, base, strlen (base) + 1);
     835              :   char *new_name = XOBFINISH (&m_string_obstack, char *);
     836              :   tmp_oname.name = new_name;
     837              : 
     838              :   if (!m_overloads_htab)
     839              :     m_overloads_htab = htab_create (31, overloaded_name_hash,
     840              :                                     overloaded_name_eq_p, NULL);
     841              : 
     842              :   /* See whether another pattern had the same overload name and list
     843              :      of argument types.  Create a new permanent one if not.  */
     844              :   void **slot = htab_find_slot (m_overloads_htab, &tmp_oname, INSERT);
     845              :   overloaded_name *oname = (overloaded_name *) *slot;
     846              :   if (!oname)
     847              :     {
     848              :       *slot = oname = new overloaded_name;
     849              :       oname->name = tmp_oname.name;
     850              :       oname->arg_types = tmp_oname.arg_types;
     851              :       oname->next = NULL;
     852              :       oname->first_instance = NULL;
     853              :       oname->next_instance_ptr = &oname->first_instance;
     854              : 
     855              :       *m_next_overload_ptr = oname;
     856              :       m_next_overload_ptr = &oname->next;
     857              :     }
     858              :   else
     859              :     {
     860              :       obstack_free (&m_string_obstack, new_name);
     861              :       tmp_oname.arg_types.release ();
     862              :     }
     863              : 
     864              :   return oname;
     865              : }
     866              : 
     867              : /* Add an instance of ONAME for instruction pattern X.  ITERATORS[I]
     868              :    gives the iterator associated with argument I of ONAME.  */
     869              : 
     870              : static void
     871              : add_overload_instance (overloaded_name *oname, const vec<mapping *> &iterators, rtx x)
     872              : {
     873              :   /* Create the instance.  */
     874              :   overloaded_instance *instance = new overloaded_instance;
     875              :   instance->next = NULL;
     876              :   instance->arg_values.create (oname->arg_types.length ());
     877              :   for (unsigned int i = 0; i < iterators.length (); ++i)
     878              :     {
     879              :       int value = iterators[i]->current_value->number;
     880              :       const char *name = iterators[i]->group->get_c_token (value);
     881              :       instance->arg_values.quick_push (name);
     882              :     }
     883              :   instance->name = XSTR (x, 0);
     884              :   instance->insn = x;
     885              : 
     886              :   /* Chain it onto the end of ONAME's list.  */
     887              :   *oname->next_instance_ptr = instance;
     888              :   oname->next_instance_ptr = &instance->next;
     889              : }
     890              : 
     891              : /* Expand all iterators in the current rtx, which is given as ORIGINAL.
     892              :    Build a list of expanded rtxes in the EXPR_LIST pointed to by QUEUE.  */
     893              : 
     894              : static void
     895              : apply_iterators (rtx original, vec<rtx> *queue)
     896              : {
     897              :   unsigned int i;
     898              :   const char *condition;
     899              :   iterator_use *iuse;
     900              :   struct mapping *iterator;
     901              :   struct map_value *v;
     902              :   rtx x;
     903              : 
     904              :   if (iterator_uses.is_empty ())
     905              :     {
     906              :       /* Raise an error if any attributes were used.  */
     907              :       apply_attribute_uses ();
     908              : 
     909              :       if (named_rtx_p (original) && XSTR (original, 0)[0] == '@')
     910              :         fatal_with_file_and_line ("'@' used without iterators");
     911              : 
     912              :       queue->safe_push (original);
     913              :       return;
     914              :     }
     915              : 
     916              :   /* Clear out the iterators from the previous run.  */
     917              :   FOR_EACH_VEC_ELT (current_iterators, i, iterator)
     918              :     iterator->current_value = NULL;
     919              :   current_iterators.truncate (0);
     920              : 
     921              :   /* Mark the iterators that we need this time.  */
     922              :   FOR_EACH_VEC_ELT (iterator_uses, i, iuse)
     923              :     iuse->iterator->current_value = iuse->iterator->values;
     924              : 
     925              :   /* Get the list of iterators that are in use, preserving the
     926              :      definition order within each group.  */
     927              :   htab_traverse (modes.iterators, add_current_iterators, NULL);
     928              :   htab_traverse (codes.iterators, add_current_iterators, NULL);
     929              :   htab_traverse (ints.iterators, add_current_iterators, NULL);
     930              :   htab_traverse (substs.iterators, add_current_iterators, NULL);
     931              :   gcc_assert (!current_iterators.is_empty ());
     932              : 
     933              :   /* Check whether this is a '@' overloaded pattern.  */
     934              :   auto_vec<mapping *, 16> iterators;
     935              :   overloaded_name *oname
     936              :     = rtx_reader_ptr->handle_overloaded_name (original, &iterators);
     937              : 
     938              :   for (;;)
     939              :     {
     940              :       /* Apply the current iterator values.  Accumulate a condition to
     941              :          say when the resulting rtx can be used.  */
     942              :       condition = "";
     943              :       FOR_EACH_VEC_ELT (iterator_uses, i, iuse)
     944              :         {
     945              :           if (iuse->iterator->group == &substs)
     946              :             continue;
     947              :           v = iuse->iterator->current_value;
     948              :           iuse->iterator->group->apply_iterator (iuse->x, iuse->index,
     949              :                                                  v->number);
     950              :           condition = rtx_reader_ptr->join_c_conditions (condition, v->string);
     951              :         }
     952              :       apply_attribute_uses ();
     953              :       x = rtx_reader_ptr->copy_rtx_for_iterators (original);
     954              :       add_condition_to_rtx (x, condition);
     955              : 
     956              :       /* We apply subst iterator after RTL-template is copied, as during
     957              :          subst-iterator processing, we could add an attribute to the
     958              :          RTL-template, and we don't want to do it in the original one.  */
     959              :       bool add_oname = true;
     960              :       FOR_EACH_VEC_ELT (iterator_uses, i, iuse)
     961              :         {
     962              :           v = iuse->iterator->current_value;
     963              :           if (iuse->iterator->group == &substs)
     964              :             {
     965              :               iuse->x = x;
     966              :               iuse->index = 0;
     967              :               current_iterator_name = iuse->iterator->name;
     968              :               iuse->iterator->group->apply_iterator (iuse->x, iuse->index,
     969              :                                                      v->number);
     970              :               /* Only handle '@' overloading for the default value.
     971              :                  See handle_overloaded_name for details.  */
     972              :               if (v != iuse->iterator->values)
     973              :                 add_oname = false;
     974              :             }
     975              :         }
     976              : 
     977              :       if (oname && add_oname)
     978              :         add_overload_instance (oname, iterators, x);
     979              : 
     980              :       /* Add the new rtx to the end of the queue.  */
     981              :       queue->safe_push (x);
     982              : 
     983              :       /* Lexicographically increment the iterator value sequence.
     984              :          That is, cycle through iterator values, starting from the right,
     985              :          and stopping when one of them doesn't wrap around.  */
     986              :       i = current_iterators.length ();
     987              :       for (;;)
     988              :         {
     989              :           if (i == 0)
     990              :             return;
     991              :           i--;
     992              :           iterator = current_iterators[i];
     993              :           iterator->current_value = iterator->current_value->next;
     994              :           if (iterator->current_value)
     995              :             break;
     996              :           iterator->current_value = iterator->values;
     997              :         }
     998              :     }
     999              : }
    1000              : #endif /* #ifdef GENERATOR_FILE */
    1001              : 
    1002              : /* Add a new "mapping" structure to hashtable TABLE.  NAME is the name
    1003              :    of the mapping and GROUP is the group to which it belongs.  */
    1004              : 
    1005              : static struct mapping *
    1006           88 : add_mapping (struct iterator_group *group, htab_t table, const char *name)
    1007              : {
    1008           88 :   struct mapping *m;
    1009           88 :   void **slot;
    1010              : 
    1011           88 :   m = XNEW (struct mapping);
    1012           88 :   m->name = xstrdup (name);
    1013           88 :   m->group = group;
    1014           88 :   m->values = 0;
    1015           88 :   m->current_value = NULL;
    1016              : 
    1017           88 :   slot = htab_find_slot (table, m, INSERT);
    1018           88 :   if (*slot != 0)
    1019            0 :     fatal_with_file_and_line ("`%s' already defined", name);
    1020              : 
    1021           88 :   *slot = m;
    1022           88 :   return m;
    1023              : }
    1024              : 
    1025              : /* Add the pair (NUMBER, STRING) to a list of map_value structures.
    1026              :    END_PTR points to the current null terminator for the list; return
    1027              :    a pointer the new null terminator.  */
    1028              : 
    1029              : static struct map_value **
    1030        12232 : add_map_value (struct map_value **end_ptr, int number, const char *string)
    1031              : {
    1032        12232 :   struct map_value *value;
    1033              : 
    1034            0 :   value = XNEW (struct map_value);
    1035        12232 :   value->next = 0;
    1036        12232 :   value->number = number;
    1037        12232 :   value->string = string;
    1038              : 
    1039        12232 :   *end_ptr = value;
    1040        12232 :   return &value->next;
    1041              : }
    1042              : 
    1043              : /* Do one-time initialization of the mode and code attributes.  */
    1044              : 
    1045              : static void
    1046           22 : initialize_iterators (void)
    1047              : {
    1048           22 :   struct mapping *lower, *upper;
    1049           22 :   struct map_value **lower_ptr, **upper_ptr;
    1050           22 :   char *copy, *p;
    1051           22 :   int i;
    1052              : 
    1053           22 :   modes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
    1054           22 :   modes.iterators = htab_create (13, leading_string_hash,
    1055              :                                  leading_string_eq_p, 0);
    1056           22 :   modes.type = "machine_mode";
    1057           22 :   modes.find_builtin = find_mode;
    1058           22 :   modes.apply_iterator = apply_mode_iterator;
    1059           22 :   modes.get_c_token = get_mode_token;
    1060              : 
    1061           22 :   codes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
    1062           22 :   codes.iterators = htab_create (13, leading_string_hash,
    1063              :                                  leading_string_eq_p, 0);
    1064           22 :   codes.type = "rtx_code";
    1065           22 :   codes.find_builtin = find_code;
    1066           22 :   codes.apply_iterator = apply_code_iterator;
    1067           22 :   codes.get_c_token = get_code_token;
    1068              : 
    1069           22 :   ints.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
    1070           22 :   ints.iterators = htab_create (13, leading_string_hash,
    1071              :                                  leading_string_eq_p, 0);
    1072           22 :   ints.type = "int";
    1073           22 :   ints.find_builtin = find_int;
    1074           22 :   ints.apply_iterator = apply_int_iterator;
    1075           22 :   ints.get_c_token = get_int_token;
    1076           22 :   ints.has_self_attr = true;
    1077              : 
    1078           22 :   substs.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
    1079           22 :   substs.iterators = htab_create (13, leading_string_hash,
    1080              :                                  leading_string_eq_p, 0);
    1081           22 :   substs.type = "int";
    1082           22 :   substs.find_builtin = find_int; /* We don't use it, anyway.  */
    1083              : #ifdef GENERATOR_FILE
    1084              :   substs.apply_iterator = apply_subst_iterator;
    1085              : #endif
    1086           22 :   substs.get_c_token = get_int_token;
    1087              : 
    1088           22 :   lower = add_mapping (&modes, modes.attrs, "mode");
    1089           22 :   upper = add_mapping (&modes, modes.attrs, "MODE");
    1090           22 :   lower_ptr = &lower->values;
    1091           22 :   upper_ptr = &upper->values;
    1092         2750 :   for (i = 0; i < MAX_MACHINE_MODE; i++)
    1093              :     {
    1094         2728 :       copy = xstrdup (GET_MODE_NAME (i));
    1095        14938 :       for (p = copy; *p != 0; p++)
    1096         9482 :         *p = TOLOWER (*p);
    1097              : 
    1098         2728 :       upper_ptr = add_map_value (upper_ptr, i, GET_MODE_NAME (i));
    1099         2728 :       lower_ptr = add_map_value (lower_ptr, i, copy);
    1100              :     }
    1101              : 
    1102           22 :   lower = add_mapping (&codes, codes.attrs, "code");
    1103           22 :   upper = add_mapping (&codes, codes.attrs, "CODE");
    1104           22 :   lower_ptr = &lower->values;
    1105           22 :   upper_ptr = &upper->values;
    1106         3410 :   for (i = 0; i < NUM_RTX_CODE; i++)
    1107              :     {
    1108         3388 :       copy = xstrdup (GET_RTX_NAME (i));
    1109        32450 :       for (p = copy; *p != 0; p++)
    1110        25674 :         *p = TOUPPER (*p);
    1111              : 
    1112         3388 :       lower_ptr = add_map_value (lower_ptr, i, GET_RTX_NAME (i));
    1113         3388 :       upper_ptr = add_map_value (upper_ptr, i, copy);
    1114              :     }
    1115           22 : }
    1116              : 
    1117              : 
    1118              : #ifdef GENERATOR_FILE
    1119              : /* Process a define_conditions directive, starting with the optional
    1120              :    space after the "define_conditions".  The directive looks like this:
    1121              : 
    1122              :      (define_conditions [
    1123              :         (number "string")
    1124              :         (number "string")
    1125              :         ...
    1126              :      ])
    1127              : 
    1128              :    It's not intended to appear in machine descriptions.  It is
    1129              :    generated by (the program generated by) genconditions.cc, and
    1130              :    slipped in at the beginning of the sequence of MD files read by
    1131              :    most of the other generators.  */
    1132              : void
    1133              : md_reader::read_conditions ()
    1134              : {
    1135              :   int c;
    1136              : 
    1137              :   require_char_ws ('[');
    1138              : 
    1139              :   while ( (c = read_skip_spaces ()) != ']')
    1140              :     {
    1141              :       struct md_name name;
    1142              :       char *expr;
    1143              :       int value;
    1144              : 
    1145              :       if (c != '(')
    1146              :         fatal_expected_char ('(', c);
    1147              : 
    1148              :       read_name (&name);
    1149              :       validate_const_int (name.string);
    1150              :       value = atoi (name.string);
    1151              : 
    1152              :       require_char_ws ('"');
    1153              :       expr = read_quoted_string ();
    1154              : 
    1155              :       require_char_ws (')');
    1156              : 
    1157              :       add_c_test (expr, value);
    1158              :     }
    1159              : }
    1160              : #endif /* #ifdef GENERATOR_FILE */
    1161              : 
    1162              : static void
    1163          244 : validate_const_int (const char *string)
    1164              : {
    1165          244 :   const char *cp;
    1166          244 :   int valid = 1;
    1167              : 
    1168          244 :   cp = string;
    1169          244 :   while (*cp && ISSPACE (*cp))
    1170            0 :     cp++;
    1171          244 :   if (*cp == '-' || *cp == '+')
    1172          148 :     cp++;
    1173          244 :   if (*cp == 0)
    1174            0 :     valid = 0;
    1175          553 :   for (; *cp; cp++)
    1176          309 :     if (! ISDIGIT (*cp))
    1177              :       {
    1178              :         valid = 0;
    1179              :         break;
    1180              :       }
    1181          244 :   if (!valid)
    1182            0 :     fatal_with_file_and_line ("invalid decimal constant \"%s\"\n", string);
    1183          244 : }
    1184              : 
    1185              : static void
    1186            0 : validate_const_wide_int (const char *string)
    1187              : {
    1188            0 :   const char *cp;
    1189            0 :   int valid = 1;
    1190              : 
    1191            0 :   cp = string;
    1192            0 :   while (*cp && ISSPACE (*cp))
    1193            0 :     cp++;
    1194              :   /* Skip the leading 0x.  */
    1195            0 :   if (cp[0] == '0' || cp[1] == 'x')
    1196            0 :     cp += 2;
    1197              :   else
    1198              :     valid = 0;
    1199            0 :   if (*cp == 0)
    1200            0 :     valid = 0;
    1201            0 :   for (; *cp; cp++)
    1202            0 :     if (! ISXDIGIT (*cp))
    1203            0 :       valid = 0;
    1204            0 :   if (!valid)
    1205            0 :     fatal_with_file_and_line ("invalid hex constant \"%s\"\n", string);
    1206            0 : }
    1207              : 
    1208              : /* Record that X uses iterator ITERATOR.  If the use is in an operand
    1209              :    of X, INDEX is the index of that operand, otherwise it is ignored.  */
    1210              : 
    1211              : static void
    1212            0 : record_iterator_use (struct mapping *iterator, rtx x, unsigned int index)
    1213              : {
    1214            0 :   struct iterator_use iuse = {iterator, x, index};
    1215            0 :   iterator_uses.safe_push (iuse);
    1216            0 : }
    1217              : 
    1218              : /* Record that X uses attribute VALUE at location LOC, where VALUE must
    1219              :    match a built-in value from group GROUP.  If the use is in an operand
    1220              :    of X, INDEX is the index of that operand, otherwise it is ignored.  */
    1221              : 
    1222              : static void
    1223            0 : record_attribute_use (struct iterator_group *group, file_location loc, rtx x,
    1224              :                       unsigned int index, const char *value)
    1225              : {
    1226            0 :   struct attribute_use ause = {group, loc, value, x, index};
    1227            0 :   attribute_uses.safe_push (ause);
    1228            0 : }
    1229              : 
    1230              : /* Interpret NAME as either a built-in value, iterator or attribute
    1231              :    for group GROUP.  X and INDEX are the values to pass to GROUP's
    1232              :    apply_iterator callback.  LOC is the location of the use.  */
    1233              : 
    1234              : void
    1235         1288 : md_reader::record_potential_iterator_use (struct iterator_group *group,
    1236              :                                           file_location loc,
    1237              :                                           rtx x, unsigned int index,
    1238              :                                           const char *name)
    1239              : {
    1240         1288 :   struct mapping *m;
    1241         1288 :   size_t len;
    1242              : 
    1243         1288 :   len = strlen (name);
    1244         1288 :   if (name[0] == '<' && name[len - 1] == '>')
    1245              :     {
    1246              :       /* Copy the attribute string into permanent storage, without the
    1247              :          angle brackets around it.  */
    1248            0 :       obstack_grow0 (&m_string_obstack, name + 1, len - 2);
    1249            0 :       record_attribute_use (group, loc, x, index,
    1250            0 :                             XOBFINISH (&m_string_obstack, char *));
    1251            0 :     }
    1252              :   else
    1253              :     {
    1254         1288 :       m = (struct mapping *) htab_find (group->iterators, &name);
    1255         1288 :       if (m != 0)
    1256            0 :         record_iterator_use (m, x, index);
    1257              :       else
    1258         1288 :         group->apply_iterator (x, index, group->find_builtin (name));
    1259              :     }
    1260         1288 : }
    1261              : 
    1262              : #ifdef GENERATOR_FILE
    1263              : 
    1264              : /* Finish reading a declaration of the form:
    1265              : 
    1266              :        (define... <name> [<value1> ... <valuen>])
    1267              : 
    1268              :    from the MD file, where each <valuei> is either a bare symbol name or a
    1269              :    "(<name> <string>)" pair.  The "(define..." part has already been read.
    1270              : 
    1271              :    Represent the declaration as a "mapping" structure; add it to TABLE
    1272              :    (which belongs to GROUP) and return it.  */
    1273              : 
    1274              : struct mapping *
    1275              : md_reader::read_mapping (struct iterator_group *group, htab_t table)
    1276              : {
    1277              :   struct md_name name;
    1278              :   struct mapping *m;
    1279              :   struct map_value **end_ptr;
    1280              :   const char *string;
    1281              :   int number, c;
    1282              : 
    1283              :   /* Read the mapping name and create a structure for it.  */
    1284              :   read_name (&name);
    1285              :   m = add_mapping (group, table, name.string);
    1286              : 
    1287              :   require_char_ws ('[');
    1288              : 
    1289              :   /* Read each value.  */
    1290              :   end_ptr = &m->values;
    1291              :   c = read_skip_spaces ();
    1292              :   do
    1293              :     {
    1294              :       if (c != '(')
    1295              :         {
    1296              :           /* A bare symbol name that is implicitly paired to an
    1297              :              empty string.  */
    1298              :           unread_char (c);
    1299              :           read_name (&name);
    1300              :           string = "";
    1301              :         }
    1302              :       else
    1303              :         {
    1304              :           /* A "(name string)" pair.  */
    1305              :           read_name (&name);
    1306              :           string = read_string (false);
    1307              :           require_char_ws (')');
    1308              :         }
    1309              :       auto *subm = (struct mapping *) htab_find (group->iterators,
    1310              :                                                  &name.string);
    1311              :       if (subm)
    1312              :         {
    1313              :           if (m == subm)
    1314              :             fatal_with_file_and_line ("recursive definition of `%s'",
    1315              :                                       name.string);
    1316              :           for (map_value *v = subm->values; v; v = v->next)
    1317              :             {
    1318              :               auto *joined = rtx_reader_ptr->join_c_conditions (v->string,
    1319              :                                                                 string);
    1320              :               end_ptr = add_map_value (end_ptr, v->number, joined);
    1321              :             }
    1322              :         }
    1323              :       else
    1324              :         {
    1325              :           number = group->find_builtin (name.string);
    1326              :           end_ptr = add_map_value (end_ptr, number, string);
    1327              :         }
    1328              :       c = read_skip_spaces ();
    1329              :     }
    1330              :   while (c != ']');
    1331              : 
    1332              :   return m;
    1333              : }
    1334              : 
    1335              : /* For iterator with name ATTR_NAME generate define_attr with values
    1336              :    'yes' and 'no'.  This attribute is used to mark templates to which
    1337              :    define_subst ATTR_NAME should be applied.  This attribute is set and
    1338              :    defined implicitly and automatically.  */
    1339              : static void
    1340              : add_define_attr_for_define_subst (const char *attr_name, vec<rtx> *queue)
    1341              : {
    1342              :   rtx const_str, return_rtx;
    1343              : 
    1344              :   return_rtx = rtx_alloc (DEFINE_ATTR);
    1345              :   PUT_CODE (return_rtx, DEFINE_ATTR);
    1346              : 
    1347              :   const_str = rtx_alloc (CONST_STRING);
    1348              :   PUT_CODE (const_str, CONST_STRING);
    1349              :   XSTR (const_str, 0) = xstrdup ("no");
    1350              : 
    1351              :   XSTR (return_rtx, 0) = xstrdup (attr_name);
    1352              :   XSTR (return_rtx, 1) = xstrdup ("no,yes");
    1353              :   XEXP (return_rtx, 2) = const_str;
    1354              : 
    1355              :   queue->safe_push (return_rtx);
    1356              : }
    1357              : 
    1358              : /* This routine generates DEFINE_SUBST_ATTR expression with operands
    1359              :    ATTR_OPERANDS and places it to QUEUE.  */
    1360              : static void
    1361              : add_define_subst_attr (const char **attr_operands, vec<rtx> *queue)
    1362              : {
    1363              :   rtx return_rtx;
    1364              :   int i;
    1365              : 
    1366              :   return_rtx = rtx_alloc (DEFINE_SUBST_ATTR);
    1367              :   PUT_CODE (return_rtx, DEFINE_SUBST_ATTR);
    1368              : 
    1369              :   for (i = 0; i < 4; i++)
    1370              :     XSTR (return_rtx, i) = xstrdup (attr_operands[i]);
    1371              : 
    1372              :   queue->safe_push (return_rtx);
    1373              : }
    1374              : 
    1375              : /* Read define_subst_attribute construction.  It has next form:
    1376              :         (define_subst_attribute <attribute_name> <iterator_name> <value1> <value2>)
    1377              :    Attribute is substituted with value1 when no subst is applied and with
    1378              :    value2 in the opposite case.
    1379              :    Attributes are added to SUBST_ATTRS_TABLE.
    1380              :    In case the iterator is encountered for the first time, it's added to
    1381              :    SUBST_ITERS_TABLE.  Also, implicit define_attr is generated.  */
    1382              : 
    1383              : static void
    1384              : read_subst_mapping (htab_t subst_iters_table, htab_t subst_attrs_table,
    1385              :                     vec<rtx> *queue)
    1386              : {
    1387              :   struct mapping *m;
    1388              :   struct map_value **end_ptr;
    1389              :   const char *attr_operands[4];
    1390              :   int i;
    1391              : 
    1392              :   for (i = 0; i < 4; i++)
    1393              :     attr_operands[i] = rtx_reader_ptr->read_string (false);
    1394              : 
    1395              :   add_define_subst_attr (attr_operands, queue);
    1396              : 
    1397              :   bind_subst_iter_and_attr (attr_operands[1], attr_operands[0]);
    1398              : 
    1399              :   m = (struct mapping *) htab_find (substs.iterators, &attr_operands[1]);
    1400              :   if (!m)
    1401              :     {
    1402              :       m = add_mapping (&substs, subst_iters_table, attr_operands[1]);
    1403              :       end_ptr = &m->values;
    1404              :       end_ptr = add_map_value (end_ptr, 1, "");
    1405              :       add_map_value (end_ptr, 2, "");
    1406              : 
    1407              :       add_define_attr_for_define_subst (attr_operands[1], queue);
    1408              :     }
    1409              : 
    1410              :   m = add_mapping (&substs, subst_attrs_table, attr_operands[0]);
    1411              :   end_ptr = &m->values;
    1412              :   end_ptr = add_map_value (end_ptr, 1, attr_operands[2]);
    1413              :   add_map_value (end_ptr, 2, attr_operands[3]);
    1414              : }
    1415              : 
    1416              : /* Check newly-created code iterator ITERATOR to see whether every code has the
    1417              :    same format.  */
    1418              : 
    1419              : static void
    1420              : check_code_iterator (struct mapping *iterator)
    1421              : {
    1422              :   struct map_value *v;
    1423              :   enum rtx_code bellwether;
    1424              : 
    1425              :   bellwether = (enum rtx_code) iterator->values->number;
    1426              :   for (v = iterator->values->next; v != 0; v = v->next)
    1427              :     if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0)
    1428              :       fatal_with_file_and_line ("code iterator `%s' combines "
    1429              :                                 "`%s' and `%s', which have different "
    1430              :                                 "rtx formats", iterator->name,
    1431              :                                 GET_RTX_NAME (bellwether),
    1432              :                                 GET_RTX_NAME (v->number));
    1433              : }
    1434              : 
    1435              : /* Check that all values of attribute ATTR are rtx codes that have a
    1436              :    consistent format.  Return a representative code.  */
    1437              : 
    1438              : static rtx_code
    1439              : check_attribute_codes (mapping *attr)
    1440              : {
    1441              :   rtx_code bellwether = UNKNOWN;
    1442              :   for (map_value *v = attr->values; v != 0; v = v->next)
    1443              :     {
    1444              :       rtx_code code = maybe_find_code (v->string);
    1445              :       if (code == UNKNOWN)
    1446              :         fatal_with_file_and_line ("attribute `%s' contains "
    1447              :                                   "unrecognized rtx code `%s'",
    1448              :                                   attr->name, v->string);
    1449              :       if (bellwether == UNKNOWN)
    1450              :         bellwether = code;
    1451              :       else if (strcmp (GET_RTX_FORMAT (bellwether),
    1452              :                        GET_RTX_FORMAT (code)) != 0)
    1453              :         fatal_with_file_and_line ("attribute `%s' combines "
    1454              :                                   "`%s' and `%s', which have different "
    1455              :                                   "rtx formats", attr->name,
    1456              :                                   GET_RTX_NAME (bellwether),
    1457              :                                   GET_RTX_NAME (code));
    1458              :     }
    1459              :   return bellwether;
    1460              : }
    1461              : 
    1462              : /* Read an rtx-related declaration from the MD file, given that it
    1463              :    starts with directive name RTX_NAME.  Return true if it expands to
    1464              :    one or more rtxes (as defined by rtx.def).  When returning true,
    1465              :    store the list of rtxes as an EXPR_LIST in *X.  */
    1466              : 
    1467              : bool
    1468              : rtx_reader::read_rtx (const char *rtx_name, vec<rtx> *rtxen)
    1469              : {
    1470              :   /* Handle various rtx-related declarations that aren't themselves
    1471              :      encoded as rtxes.  */
    1472              :   if (strcmp (rtx_name, "define_conditions") == 0)
    1473              :     {
    1474              :       read_conditions ();
    1475              :       return false;
    1476              :     }
    1477              :   if (strcmp (rtx_name, "define_mode_attr") == 0)
    1478              :     {
    1479              :       read_mapping (&modes, modes.attrs);
    1480              :       return false;
    1481              :     }
    1482              :   if (strcmp (rtx_name, "define_mode_iterator") == 0)
    1483              :     {
    1484              :       read_mapping (&modes, modes.iterators);
    1485              :       return false;
    1486              :     }
    1487              :   if (strcmp (rtx_name, "define_code_attr") == 0)
    1488              :     {
    1489              :       read_mapping (&codes, codes.attrs);
    1490              :       return false;
    1491              :     }
    1492              :   if (strcmp (rtx_name, "define_code_iterator") == 0)
    1493              :     {
    1494              :       check_code_iterator (read_mapping (&codes, codes.iterators));
    1495              :       return false;
    1496              :     }
    1497              :   if (strcmp (rtx_name, "define_int_attr") == 0)
    1498              :     {
    1499              :       read_mapping (&ints, ints.attrs);
    1500              :       return false;
    1501              :     }
    1502              :   if (strcmp (rtx_name, "define_int_iterator") == 0)
    1503              :     {
    1504              :       read_mapping (&ints, ints.iterators);
    1505              :       return false;
    1506              :     }
    1507              :   if (strcmp (rtx_name, "define_subst_attr") == 0)
    1508              :     {
    1509              :       read_subst_mapping (substs.iterators, substs.attrs, rtxen);
    1510              : 
    1511              :       /* READ_SUBST_MAPPING could generate a new DEFINE_ATTR.  Return
    1512              :          TRUE to process it.  */
    1513              :       return true;
    1514              :     }
    1515              : 
    1516              :   apply_iterators (rtx_reader_ptr->read_rtx_code (rtx_name), rtxen);
    1517              :   iterator_uses.truncate (0);
    1518              :   attribute_uses.truncate (0);
    1519              : 
    1520              :   return true;
    1521              : }
    1522              : 
    1523              : #endif /* #ifdef GENERATOR_FILE */
    1524              : 
    1525              : /* Do one-time initialization.  */
    1526              : 
    1527              : static void
    1528          100 : one_time_initialization (void)
    1529              : {
    1530          100 :   static bool initialized = false;
    1531              : 
    1532          100 :   if (!initialized)
    1533              :     {
    1534           22 :       initialize_iterators ();
    1535           22 :       initialized = true;
    1536              :     }
    1537          100 : }
    1538              : 
    1539              : /* Consume characters until encountering a character in TERMINATOR_CHARS,
    1540              :    consuming the terminator character if CONSUME_TERMINATOR is true.
    1541              :    Return all characters before the terminator as an allocated buffer.  */
    1542              : 
    1543              : char *
    1544          311 : rtx_reader::read_until (const char *terminator_chars, bool consume_terminator)
    1545              : {
    1546          311 :   int ch = read_skip_spaces ();
    1547          311 :   unread_char (ch);
    1548          311 :   auto_vec<char> buf;
    1549         2167 :   while (1)
    1550              :     {
    1551         1239 :       ch = read_char ();
    1552         1239 :       if (strchr (terminator_chars, ch))
    1553              :         {
    1554          311 :           if (!consume_terminator)
    1555          145 :             unread_char (ch);
    1556          311 :           break;
    1557              :         }
    1558          928 :       buf.safe_push (ch);
    1559              :     }
    1560          311 :   buf.safe_push ('\0');
    1561          622 :   return xstrdup (buf.address ());
    1562          311 : }
    1563              : 
    1564              : /* Subroutine of read_rtx_code, for parsing zero or more flags.  */
    1565              : 
    1566              : static void
    1567         2201 : read_flags (rtx return_rtx)
    1568              : {
    1569         2547 :   while (1)
    1570              :     {
    1571         2547 :       int ch = read_char ();
    1572         2547 :       if (ch != '/')
    1573              :         {
    1574         2201 :           unread_char (ch);
    1575         2201 :           break;
    1576              :         }
    1577              : 
    1578          346 :       int flag_char = read_char ();
    1579          346 :       switch (flag_char)
    1580              :         {
    1581            0 :           case 's':
    1582            0 :             RTX_FLAG (return_rtx, in_struct) = 1;
    1583            0 :             break;
    1584           28 :           case 'v':
    1585           28 :             RTX_FLAG (return_rtx, volatil) = 1;
    1586           28 :             break;
    1587            0 :           case 'u':
    1588            0 :             RTX_FLAG (return_rtx, unchanging) = 1;
    1589            0 :             break;
    1590          134 :           case 'f':
    1591          134 :             RTX_FLAG (return_rtx, frame_related) = 1;
    1592          134 :             break;
    1593            5 :           case 'j':
    1594            5 :             RTX_FLAG (return_rtx, jump) = 1;
    1595            5 :             break;
    1596          116 :           case 'c':
    1597          116 :             RTX_FLAG (return_rtx, call) = 1;
    1598          116 :             break;
    1599           63 :           case 'i':
    1600           63 :             RTX_FLAG (return_rtx, return_val) = 1;
    1601           63 :             break;
    1602            0 :           default:
    1603            0 :             fatal_with_file_and_line ("unrecognized flag: `%c'", flag_char);
    1604              :         }
    1605              :     }
    1606         2201 : }
    1607              : 
    1608              : /* Return the numeric value n for GET_REG_NOTE_NAME (n) for STRING,
    1609              :    or fail if STRING isn't recognized.  */
    1610              : 
    1611              : static int
    1612           42 : parse_reg_note_name (const char *string)
    1613              : {
    1614          480 :   for (int i = 0; i < REG_NOTE_MAX; i++)
    1615          480 :     if (strcmp (string, GET_REG_NOTE_NAME (i)) == 0)
    1616           42 :       return i;
    1617            0 :   fatal_with_file_and_line ("unrecognized REG_NOTE name: `%s'", string);
    1618              : }
    1619              : 
    1620              : /* Allocate an rtx for code NAME.  If NAME is a code iterator or an
    1621              :    attribute, record its use for later and use one of its possible
    1622              :    values as an interim rtx code.  */
    1623              : 
    1624              : rtx
    1625         2202 : rtx_reader::rtx_alloc_for_name (const char *name)
    1626              : {
    1627              : #ifdef GENERATOR_FILE
    1628              :   size_t len = strlen (name);
    1629              :   if (name[0] == '<' && name[len - 1] == '>')
    1630              :     {
    1631              :       /* Copy the attribute string into permanent storage, without the
    1632              :          angle brackets around it.  */
    1633              :       obstack *strings = get_string_obstack ();
    1634              :       obstack_grow0 (strings, name + 1, len - 2);
    1635              :       char *deferred_name = XOBFINISH (strings, char *);
    1636              : 
    1637              :       /* Find the name of the attribute.  */
    1638              :       const char *attr = strchr (deferred_name, ':');
    1639              :       if (!attr)
    1640              :         attr = deferred_name;
    1641              : 
    1642              :       /* Find the attribute itself.  */
    1643              :       mapping *m = nullptr;
    1644              :       for (auto attrs : { codes.attrs, ints.attrs, modes.attrs })
    1645              :        if (auto *newm = (mapping *) htab_find (attrs, &attr))
    1646              :          {
    1647              :            if (m)
    1648              :              fatal_with_file_and_line ("ambiguous attribute `%s`", attr);
    1649              :            m = newm;
    1650              :          }
    1651              :       if (!m)
    1652              :         fatal_with_file_and_line ("unknown attribute `%s'", attr);
    1653              : 
    1654              :       /* Pick the first possible code for now, and record the attribute
    1655              :          use for later.  */
    1656              :       rtx x = rtx_alloc (check_attribute_codes (m));
    1657              :       record_attribute_use (&codes, get_current_location (),
    1658              :                             x, 0, deferred_name);
    1659              :       return x;
    1660              :     }
    1661              : 
    1662              :   mapping *iterator = (mapping *) htab_find (codes.iterators, &name);
    1663              :   if (iterator != 0)
    1664              :     {
    1665              :       /* Pick the first possible code for now, and record the iterator
    1666              :          use for later.  */
    1667              :       rtx x = rtx_alloc (rtx_code (iterator->values->number));
    1668              :       record_iterator_use (iterator, x, 0);
    1669              :       return x;
    1670              :     }
    1671              : #endif
    1672              : 
    1673         2202 :   return rtx_alloc (rtx_code (codes.find_builtin (name)));
    1674              : }
    1675              : 
    1676              : /* Subroutine of read_rtx and read_nested_rtx.  CODE_NAME is the name of
    1677              :    either an rtx code or a code iterator.  Parse the rest of the rtx and
    1678              :    return it.  */
    1679              : 
    1680              : rtx
    1681         2212 : rtx_reader::read_rtx_code (const char *code_name)
    1682              : {
    1683         2212 :   RTX_CODE code;
    1684         2212 :   const char *format_ptr;
    1685         2212 :   struct md_name name;
    1686         2212 :   rtx return_rtx;
    1687         2212 :   int c;
    1688              : 
    1689              :   /* Linked list structure for making RTXs: */
    1690         2212 :   struct rtx_list
    1691              :     {
    1692              :       struct rtx_list *next;
    1693              :       rtx value;                /* Value of this node.  */
    1694              :     };
    1695              : 
    1696              : #ifndef GENERATOR_FILE
    1697         2212 :   long reuse_id = -1;
    1698              :   /* Handle reuse_rtx ids e.g. "(0|scratch:DI)".  */
    1699         2212 :   if (ISDIGIT (code_name[0]))
    1700              :     {
    1701           10 :       reuse_id = atoi (code_name);
    1702           20 :       while (char ch = *code_name++)
    1703           20 :         if (ch == '|')
    1704              :           break;
    1705              :     }
    1706              : 
    1707              :   /* Handle "reuse_rtx".  */
    1708         2212 :   if (strcmp (code_name, "reuse_rtx") == 0)
    1709              :     {
    1710           10 :       read_name (&name);
    1711           10 :       unsigned idx = atoi (name.string);
    1712              :       /* Look it up by ID.  */
    1713           10 :       if (idx >= m_reuse_rtx_by_id.length ())
    1714            0 :         fatal_with_file_and_line ("invalid reuse index %u", idx);
    1715           10 :       return_rtx = m_reuse_rtx_by_id[idx];
    1716           10 :       return return_rtx;
    1717              :     }
    1718              : #endif
    1719              : 
    1720              :   /* Handle "const_double_zero".  */
    1721         2202 :   if (strcmp (code_name, "const_double_zero") == 0)
    1722              :     {
    1723            0 :       code = CONST_DOUBLE;
    1724            0 :       return_rtx = rtx_alloc (code);
    1725            0 :       memset (return_rtx, 0, RTX_CODE_SIZE (code));
    1726            0 :       PUT_CODE (return_rtx, code);
    1727            0 :       c = read_skip_spaces ();
    1728            0 :       if (c == ':')
    1729              :         {
    1730            0 :           file_location loc = read_name (&name);
    1731            0 :           record_potential_iterator_use (&modes, loc, return_rtx, 0,
    1732            0 :                                          name.string);
    1733              :         }
    1734              :       else
    1735            0 :         unread_char (c);
    1736            0 :       return return_rtx;
    1737              :     }
    1738              : 
    1739              :   /* If we end up with an insn expression then we free this space below.  */
    1740         2202 :   return_rtx = rtx_alloc_for_name (code_name);
    1741         2201 :   code = GET_CODE (return_rtx);
    1742         2201 :   format_ptr = GET_RTX_FORMAT (code);
    1743         2201 :   memset (return_rtx, 0, RTX_CODE_SIZE (code));
    1744         2201 :   PUT_CODE (return_rtx, code);
    1745              : 
    1746              : #ifndef GENERATOR_FILE
    1747         2201 :   if (reuse_id != -1)
    1748              :     {
    1749              :       /* Store away for later reuse.  */
    1750           10 :       m_reuse_rtx_by_id.safe_grow_cleared (reuse_id + 1, true);
    1751           10 :       m_reuse_rtx_by_id[reuse_id] = return_rtx;
    1752              :     }
    1753              : #endif
    1754              : 
    1755              :   /* Check for flags. */
    1756         2201 :   read_flags (return_rtx);
    1757              : 
    1758              :   /* Read REG_NOTE names for EXPR_LIST and INSN_LIST.  */
    1759         2201 :   if ((GET_CODE (return_rtx) == EXPR_LIST
    1760              :        || GET_CODE (return_rtx) == INSN_LIST
    1761         2201 :        || GET_CODE (return_rtx) == INT_LIST)
    1762           47 :       && !m_in_call_function_usage)
    1763              :     {
    1764           42 :       char ch = read_char ();
    1765           42 :       if (ch == ':')
    1766              :         {
    1767           42 :           read_name (&name);
    1768           42 :           PUT_MODE_RAW (return_rtx,
    1769              :                         (machine_mode)parse_reg_note_name (name.string));
    1770              :         }
    1771              :       else
    1772            0 :         unread_char (ch);
    1773              :     }
    1774              : 
    1775              :   /* If what follows is `: mode ', read it and
    1776              :      store the mode in the rtx.  */
    1777              : 
    1778         2201 :   c = read_skip_spaces ();
    1779         2201 :   if (c == ':')
    1780              :     {
    1781         1044 :       file_location loc = read_name (&name);
    1782         1044 :       record_potential_iterator_use (&modes, loc, return_rtx, 0, name.string);
    1783              :     }
    1784              :   else
    1785         1157 :     unread_char (c);
    1786              : 
    1787         2201 :   if (INSN_CHAIN_CODE_P (code))
    1788              :     {
    1789          464 :       read_name (&name);
    1790          464 :       INSN_UID (return_rtx) = atoi (name.string);
    1791              :     }
    1792              : 
    1793              :   /* Use the format_ptr to parse the various operands of this rtx.  */
    1794         7772 :   for (int idx = 0; format_ptr[idx] != 0; idx++)
    1795         5571 :     return_rtx = read_rtx_operand (return_rtx, idx);
    1796              : 
    1797              :   /* Handle any additional information that after the regular fields
    1798              :      (e.g. when parsing function dumps).  */
    1799         2201 :   handle_any_trailing_information (return_rtx);
    1800              : 
    1801         2201 :   if (CONST_WIDE_INT_P (return_rtx))
    1802              :     {
    1803            0 :       read_name (&name);
    1804            0 :       validate_const_wide_int (name.string);
    1805            0 :       {
    1806            0 :         const char *s = name.string;
    1807            0 :         int len;
    1808            0 :         int index = 0;
    1809            0 :         int gs = HOST_BITS_PER_WIDE_INT/4;
    1810            0 :         int pos;
    1811            0 :         char * buf = XALLOCAVEC (char, gs + 1);
    1812            0 :         unsigned HOST_WIDE_INT wi;
    1813            0 :         int wlen;
    1814              : 
    1815              :         /* Skip the leading spaces.  */
    1816            0 :         while (*s && ISSPACE (*s))
    1817            0 :           s++;
    1818              : 
    1819              :         /* Skip the leading 0x.  */
    1820            0 :         gcc_assert (s[0] == '0');
    1821            0 :         gcc_assert (s[1] == 'x');
    1822            0 :         s += 2;
    1823              : 
    1824            0 :         len = strlen (s);
    1825            0 :         pos = len - gs;
    1826            0 :         wlen = (len + gs - 1) / gs;     /* Number of words needed */
    1827              : 
    1828            0 :         return_rtx = const_wide_int_alloc (wlen);
    1829              : 
    1830            0 :         while (pos > 0)
    1831              :           {
    1832              : #if HOST_BITS_PER_WIDE_INT == 64
    1833            0 :             sscanf (s + pos, "%16" HOST_WIDE_INT_PRINT "x", &wi);
    1834              : #else
    1835              :             sscanf (s + pos, "%8" HOST_WIDE_INT_PRINT "x", &wi);
    1836              : #endif
    1837            0 :             CWI_ELT (return_rtx, index++) = wi;
    1838            0 :             pos -= gs;
    1839              :           }
    1840            0 :         strncpy (buf, s, gs - pos);
    1841            0 :         buf [gs - pos] = 0;
    1842            0 :         sscanf (buf, "%" HOST_WIDE_INT_PRINT "x", &wi);
    1843            0 :         CWI_ELT (return_rtx, index++) = wi;
    1844              :         /* TODO: After reading, do we want to canonicalize with:
    1845              :            value = lookup_const_wide_int (value); ? */
    1846              :       }
    1847              :     }
    1848              : 
    1849         2201 :   c = read_skip_spaces ();
    1850              :   /* Syntactic sugar for AND and IOR, allowing Lisp-like
    1851              :      arbitrary number of arguments for them.  */
    1852         2201 :   if (c == '('
    1853            0 :       && (GET_CODE (return_rtx) == AND
    1854            0 :           || GET_CODE (return_rtx) == IOR))
    1855            0 :     return read_rtx_variadic (return_rtx);
    1856              : 
    1857         2201 :   unread_char (c);
    1858         2201 :   return return_rtx;
    1859              : }
    1860              : 
    1861              : /* Subroutine of read_rtx_code.  Parse operand IDX within RETURN_RTX,
    1862              :    based on the corresponding format character within GET_RTX_FORMAT
    1863              :    for the GET_CODE (RETURN_RTX), and return RETURN_RTX.
    1864              :    This is a virtual function, so that function_reader can override
    1865              :    some parsing, and potentially return a different rtx.  */
    1866              : 
    1867              : rtx
    1868         2678 : rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
    1869              : {
    1870         2678 :   RTX_CODE code = GET_CODE (return_rtx);
    1871         2678 :   const char *format_ptr = GET_RTX_FORMAT (code);
    1872         2678 :   int c;
    1873         2678 :   struct md_name name;
    1874              : 
    1875         2678 :   switch (format_ptr[idx])
    1876              :     {
    1877              :       /* 0 means a field for internal use only.
    1878              :          Don't expect it to be present in the input.  */
    1879          461 :     case '0':
    1880          461 :       if (code == REG)
    1881            0 :         ORIGINAL_REGNO (return_rtx) = REGNO (return_rtx);
    1882              :       break;
    1883              : 
    1884         1888 :     case 'e':
    1885         1888 :       XEXP (return_rtx, idx) = read_nested_rtx ();
    1886         1888 :       break;
    1887              : 
    1888            0 :     case 'u':
    1889            0 :       XEXP (return_rtx, idx) = read_nested_rtx ();
    1890            0 :       break;
    1891              : 
    1892            0 :     case 'V':
    1893              :       /* 'V' is an optional vector: if a closeparen follows,
    1894              :          just store NULL for this element.  */
    1895            0 :       c = read_skip_spaces ();
    1896            0 :       unread_char (c);
    1897            0 :       if (c == ')')
    1898              :         {
    1899            0 :           XVEC (return_rtx, idx) = 0;
    1900            0 :           break;
    1901              :         }
    1902              :       /* Now process the vector.  */
    1903              :       /* FALLTHRU */
    1904              : 
    1905           43 :     case 'E':
    1906           43 :       {
    1907              :         /* Obstack to store scratch vector in.  */
    1908           43 :         struct obstack vector_stack;
    1909           43 :         int list_counter = 0;
    1910           43 :         rtvec return_vec = NULL_RTVEC;
    1911           43 :         rtx saved_rtx = NULL_RTX;
    1912              : 
    1913           43 :         require_char_ws ('[');
    1914              : 
    1915              :         /* Add expressions to a list, while keeping a count.  */
    1916           43 :         obstack_init (&vector_stack);
    1917          180 :         while ((c = read_skip_spaces ()) && c != ']')
    1918              :           {
    1919           94 :             if (c == EOF)
    1920            0 :               fatal_expected_char (']', c);
    1921           94 :             unread_char (c);
    1922              : 
    1923           94 :             rtx value;
    1924           94 :             int repeat_count = 1;
    1925           94 :             if (c == 'r')
    1926              :               {
    1927              :                 /* Process "repeated xN" directive.  */
    1928            4 :                 read_name (&name);
    1929            4 :                 if (strcmp (name.string, "repeated"))
    1930            0 :                   fatal_with_file_and_line ("invalid directive \"%s\"\n",
    1931              :                                             name.string);
    1932            4 :                 read_name (&name);
    1933            4 :                 if (!sscanf (name.string, "x%d", &repeat_count))
    1934            0 :                   fatal_with_file_and_line ("invalid repeat count \"%s\"\n",
    1935              :                                             name.string);
    1936              : 
    1937              :                 /* We already saw one of the instances.  */
    1938            4 :                 repeat_count--;
    1939            4 :                 value = saved_rtx;
    1940              :               }
    1941           90 :             else if (c == '(')
    1942           90 :               value = read_nested_rtx ();
    1943              :             else
    1944            0 :               fatal_with_file_and_line ("unexpected character in vector");
    1945              : 
    1946          436 :             for (; repeat_count > 0; repeat_count--)
    1947              :               {
    1948          342 :                 list_counter++;
    1949          342 :                 obstack_ptr_grow (&vector_stack, value);
    1950              :               }
    1951           94 :             saved_rtx = value;
    1952              :           }
    1953           43 :         if (list_counter > 0)
    1954              :           {
    1955           43 :             return_vec = rtvec_alloc (list_counter);
    1956           43 :             memcpy (&return_vec->elem[0], obstack_finish (&vector_stack),
    1957              :                     list_counter * sizeof (rtx));
    1958              :           }
    1959            0 :         else if (format_ptr[idx] == 'E')
    1960            0 :           fatal_with_file_and_line ("vector must have at least one element");
    1961           43 :         XVEC (return_rtx, idx) = return_vec;
    1962           43 :         obstack_free (&vector_stack, NULL);
    1963              :         /* close bracket gotten */
    1964              :       }
    1965           43 :       break;
    1966              : 
    1967           42 :     case 'S':
    1968           42 :     case 'T':
    1969           42 :     case 's':
    1970           42 :       {
    1971           42 :         char *stringbuf;
    1972           42 :         int star_if_braced;
    1973              : 
    1974           42 :         c = read_skip_spaces ();
    1975           42 :         unread_char (c);
    1976           42 :         if (c == ')')
    1977              :           {
    1978              :             /* 'S' fields are optional and should be NULL if no string
    1979              :                was given.  Also allow normal 's' and 'T' strings to be
    1980              :                omitted, treating them in the same way as empty strings.  */
    1981           16 :             XSTR (return_rtx, idx) = (format_ptr[idx] == 'S' ? NULL : "");
    1982           16 :             break;
    1983              :           }
    1984              : 
    1985              :         /* The output template slot of a DEFINE_INSN, DEFINE_INSN_AND_SPLIT,
    1986              :            DEFINE_INSN_AND_REWRITE or DEFINE_PEEPHOLE automatically
    1987              :            gets a star inserted as its first character, if it is
    1988              :            written with a brace block instead of a string constant.  */
    1989           26 :         star_if_braced = (format_ptr[idx] == 'T');
    1990              : 
    1991           26 :         stringbuf = read_string (star_if_braced);
    1992           26 :         if (!stringbuf)
    1993              :           break;
    1994              : 
    1995              : #ifdef GENERATOR_FILE
    1996              :         /* For insn patterns, we want to provide a default name
    1997              :            based on the file and line, like "*foo.md:12", if the
    1998              :            given name is blank.  These are only for define_insn and
    1999              :            define_insn_and_split, to aid debugging.  */
    2000              :         if (*stringbuf == '\0'
    2001              :             && idx == 0
    2002              :             && (GET_CODE (return_rtx) == DEFINE_INSN
    2003              :                 || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT
    2004              :                 || GET_CODE (return_rtx) == DEFINE_INSN_AND_REWRITE))
    2005              :           {
    2006              :             const char *old_stringbuf = stringbuf;
    2007              :             struct obstack *string_obstack = get_string_obstack ();
    2008              :             char line_name[20];
    2009              :             const char *read_md_filename = get_filename ();
    2010              :             const char *fn = (read_md_filename ? read_md_filename : "rtx");
    2011              :             const char *slash;
    2012              :             for (slash = fn; *slash; slash ++)
    2013              :               if (*slash == '/' || *slash == '\\' || *slash == ':')
    2014              :                 fn = slash + 1;
    2015              :             obstack_1grow (string_obstack, '*');
    2016              :             obstack_grow (string_obstack, fn, strlen (fn));
    2017              :             sprintf (line_name, ":%d", get_lineno ());
    2018              :             obstack_grow (string_obstack, line_name, strlen (line_name)+1);
    2019              :             stringbuf = XOBFINISH (string_obstack, char *);
    2020              :             copy_md_ptr_loc (stringbuf, old_stringbuf);
    2021              :           }
    2022              : 
    2023              :         /* Find attr-names in the string.  */
    2024              :         char *str;
    2025              :         char *start, *end, *ptr;
    2026              :         char tmpstr[256];
    2027              :         ptr = &tmpstr[0];
    2028              :         end = stringbuf;
    2029              :         while ((start = strchr (end, '<')) && (end  = strchr (start, '>')))
    2030              :           {
    2031              :             if ((end - start - 1 > 0)
    2032              :                 && (end - start - 1 < (int)sizeof (tmpstr)))
    2033              :               {
    2034              :                 strncpy (tmpstr, start+1, end-start-1);
    2035              :                 tmpstr[end-start-1] = 0;
    2036              :                 end++;
    2037              :               }
    2038              :             else
    2039              :               break;
    2040              :             struct mapping *m
    2041              :               = (struct mapping *) htab_find (substs.attrs, &ptr);
    2042              :             if (m != 0)
    2043              :               {
    2044              :                 /* Here we should find linked subst-iter.  */
    2045              :                 str = find_subst_iter_by_attr (ptr);
    2046              :                 if (str)
    2047              :                   m = (struct mapping *) htab_find (substs.iterators, &str);
    2048              :                 else
    2049              :                   m = 0;
    2050              :               }
    2051              :             if (m != 0)
    2052              :               record_iterator_use (m, return_rtx, 0);
    2053              :           }
    2054              : #endif /* #ifdef GENERATOR_FILE */
    2055              : 
    2056           18 :         const char *string_ptr = finalize_string (stringbuf);
    2057              : 
    2058           18 :         if (star_if_braced)
    2059            0 :           XTMPL (return_rtx, idx) = string_ptr;
    2060              :         else
    2061           18 :           XSTR (return_rtx, idx) = string_ptr;
    2062              :       }
    2063              :       break;
    2064              : 
    2065          244 :     case 'i':
    2066          244 :     case 'n':
    2067          244 :     case 'w':
    2068          244 :     case 'p':
    2069          244 :     case 'L':
    2070          244 :       {
    2071              :         /* Can be an iterator or an integer constant.  */
    2072          244 :         file_location loc = read_name (&name);
    2073          244 :         record_potential_iterator_use (&ints, loc, return_rtx, idx,
    2074          244 :                                        name.string);
    2075          244 :         break;
    2076              :       }
    2077              : 
    2078            0 :     case 'r':
    2079            0 :       read_name (&name);
    2080            0 :       validate_const_int (name.string);
    2081            0 :       set_regno_raw (return_rtx, atoi (name.string), 1);
    2082            0 :       REG_ATTRS (return_rtx) = NULL;
    2083            0 :       break;
    2084              : 
    2085            0 :     default:
    2086            0 :       gcc_unreachable ();
    2087              :     }
    2088              : 
    2089         2678 :   return return_rtx;
    2090              : }
    2091              : 
    2092              : /* Read a nested rtx construct from the MD file and return it.  */
    2093              : 
    2094              : rtx
    2095         1978 : rtx_reader::read_nested_rtx ()
    2096              : {
    2097         1978 :   struct md_name name;
    2098         1978 :   rtx return_rtx;
    2099              : 
    2100              :   /* In compact dumps, trailing "(nil)" values can be omitted.
    2101              :      Handle such dumps.  */
    2102         1978 :   if (peek_char () == ')')
    2103              :     return NULL_RTX;
    2104              : 
    2105         1782 :   require_char_ws ('(');
    2106              : 
    2107         1782 :   read_name (&name);
    2108         1782 :   if (strcmp (name.string, "nil") == 0)
    2109              :     return_rtx = NULL;
    2110              :   else
    2111         1676 :     return_rtx = read_rtx_code (name.string);
    2112              : 
    2113         1782 :   require_char_ws (')');
    2114              : 
    2115         1782 :   return_rtx = postprocess (return_rtx);
    2116              : 
    2117         1782 :   return return_rtx;
    2118              : }
    2119              : 
    2120              : /* Mutually recursive subroutine of read_rtx which reads
    2121              :    (thing x1 x2 x3 ...) and produces RTL as if
    2122              :    (thing x1 (thing x2 (thing x3 ...)))  had been written.
    2123              :    When called, FORM is (thing x1 x2), and the file position
    2124              :    is just past the leading parenthesis of x3.  Only works
    2125              :    for THINGs which are dyadic expressions, e.g. AND, IOR.  */
    2126              : rtx
    2127            0 : rtx_reader::read_rtx_variadic (rtx form)
    2128              : {
    2129            0 :   char c = '(';
    2130            0 :   rtx p = form, q;
    2131              : 
    2132            0 :   do
    2133              :     {
    2134            0 :       unread_char (c);
    2135              : 
    2136            0 :       q = rtx_alloc (GET_CODE (p));
    2137            0 :       PUT_MODE (q, GET_MODE (p));
    2138              : 
    2139            0 :       XEXP (q, 0) = XEXP (p, 1);
    2140            0 :       XEXP (q, 1) = read_nested_rtx ();
    2141              : 
    2142            0 :       XEXP (p, 1) = q;
    2143            0 :       p = q;
    2144            0 :       c = read_skip_spaces ();
    2145              :     }
    2146            0 :   while (c == '(');
    2147            0 :   unread_char (c);
    2148            0 :   return form;
    2149              : }
    2150              : 
    2151              : /* Constructor for class rtx_reader.  */
    2152              : 
    2153          100 : rtx_reader::rtx_reader (bool compact)
    2154              : : md_reader (compact),
    2155          100 :   m_in_call_function_usage (false)
    2156              : {
    2157              :   /* Set the global singleton pointer.  */
    2158          100 :   rtx_reader_ptr = this;
    2159              : 
    2160          100 :   one_time_initialization ();
    2161          100 : }
    2162              : 
    2163              : /* Destructor for class rtx_reader.  */
    2164              : 
    2165           99 : rtx_reader::~rtx_reader ()
    2166              : {
    2167              :   /* Clear the global singleton pointer.  */
    2168           99 :   rtx_reader_ptr = NULL;
    2169           99 : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.