LCOV - code coverage report
Current view: top level - gcc - read-rtl.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 309 529 58.4 %
Date: 2020-04-04 11:58:09 Functions: 19 34 55.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

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

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.