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

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.