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

Generated by: LCOV version 2.0-1

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