LCOV - code coverage report
Current view: top level - gcc - read-rtl-function.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.4 % 947 894
Test Date: 2024-12-21 13:15:12 Functions: 95.7 % 70 67
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* read-rtl-function.cc - Reader for RTL function dumps
       2                 :             :    Copyright (C) 2016-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                 :             : #include "config.h"
      21                 :             : #include "system.h"
      22                 :             : #include "coretypes.h"
      23                 :             : #include "target.h"
      24                 :             : #include "tree.h"
      25                 :             : #include "diagnostic.h"
      26                 :             : #include "read-md.h"
      27                 :             : #include "rtl.h"
      28                 :             : #include "cfghooks.h"
      29                 :             : #include "stringpool.h"
      30                 :             : #include "function.h"
      31                 :             : #include "tree-cfg.h"
      32                 :             : #include "cfg.h"
      33                 :             : #include "basic-block.h"
      34                 :             : #include "cfgrtl.h"
      35                 :             : #include "memmodel.h"
      36                 :             : #include "emit-rtl.h"
      37                 :             : #include "cgraph.h"
      38                 :             : #include "tree-pass.h"
      39                 :             : #include "toplev.h"
      40                 :             : #include "varasm.h"
      41                 :             : #include "read-rtl-function.h"
      42                 :             : #include "selftest.h"
      43                 :             : #include "selftest-rtl.h"
      44                 :             : #include "regs.h"
      45                 :             : #include "function-abi.h"
      46                 :             : 
      47                 :             : /* Forward decls.  */
      48                 :             : class function_reader;
      49                 :             : class fixup;
      50                 :             : 
      51                 :             : /* Edges are recorded when parsing the "insn-chain" directive,
      52                 :             :    and created at the end when all the blocks ought to exist.
      53                 :             :    This struct records an "edge-from" or "edge-to" directive seen
      54                 :             :    at LOC, which will be turned into an actual CFG edge once
      55                 :             :    the "insn-chain" is fully parsed.  */
      56                 :             : 
      57                 :             : class deferred_edge
      58                 :             : {
      59                 :             : public:
      60                 :         206 :   deferred_edge (file_location loc, int src_bb_idx, int dest_bb_idx, int flags)
      61                 :         206 :   : m_loc (loc), m_src_bb_idx (src_bb_idx), m_dest_bb_idx (dest_bb_idx),
      62                 :         206 :     m_flags (flags)
      63                 :             :   {}
      64                 :             : 
      65                 :             :   file_location m_loc;
      66                 :             :   int m_src_bb_idx;
      67                 :             :   int m_dest_bb_idx;
      68                 :             :   int m_flags;
      69                 :             : };
      70                 :             : 
      71                 :             : /* Subclass of rtx_reader for reading function dumps.  */
      72                 :             : 
      73                 :             : class function_reader : public rtx_reader
      74                 :             : {
      75                 :             :  public:
      76                 :             :   function_reader ();
      77                 :             :   ~function_reader ();
      78                 :             : 
      79                 :             :   /* Overridden vfuncs of class md_reader.  */
      80                 :             :   void handle_unknown_directive (file_location, const char *) final override;
      81                 :             : 
      82                 :             :   /* Overridden vfuncs of class rtx_reader.  */
      83                 :             :   rtx read_rtx_operand (rtx x, int idx) final override;
      84                 :             :   void handle_any_trailing_information (rtx x) final override;
      85                 :             :   rtx postprocess (rtx) final override;
      86                 :             :   const char *finalize_string (char *stringbuf) final override;
      87                 :             : 
      88                 :             :   rtx_insn **get_insn_by_uid (int uid);
      89                 :             :   tree parse_mem_expr (const char *desc);
      90                 :             : 
      91                 :             :  private:
      92                 :             :   void parse_function ();
      93                 :             :   void create_function ();
      94                 :             :   void parse_param ();
      95                 :             :   void parse_insn_chain ();
      96                 :             :   void parse_block ();
      97                 :             :   int parse_bb_idx ();
      98                 :             :   void parse_edge (basic_block block, bool from);
      99                 :             :   rtx_insn *parse_insn (file_location loc, const char *name);
     100                 :             :   void parse_cfg (file_location loc);
     101                 :             :   void parse_crtl (file_location loc);
     102                 :             :   void create_edges ();
     103                 :             : 
     104                 :             :   int parse_enum_value (int num_values, const char *const *strings);
     105                 :             : 
     106                 :             :   void read_rtx_operand_u (rtx x, int idx);
     107                 :             :   void read_rtx_operand_inL (rtx x, int idx, char format_char);
     108                 :             :   rtx read_rtx_operand_r (rtx x);
     109                 :             :   rtx extra_parsing_for_operand_code_0 (rtx x, int idx);
     110                 :             : 
     111                 :             :   void add_fixup_insn_uid (file_location loc, rtx insn, int operand_idx,
     112                 :             :                            int insn_uid);
     113                 :             : 
     114                 :             :   void add_fixup_note_insn_basic_block (file_location loc, rtx insn,
     115                 :             :                                         int operand_idx, int bb_idx);
     116                 :             : 
     117                 :             :   void add_fixup_source_location (file_location loc, rtx_insn *insn,
     118                 :             :                                   const char *filename, int lineno, int colno);
     119                 :             : 
     120                 :             :   void add_fixup_expr (file_location loc, rtx x,
     121                 :             :                        const char *desc);
     122                 :             : 
     123                 :             :   rtx consolidate_singletons (rtx x);
     124                 :             :   rtx parse_rtx ();
     125                 :             :   void maybe_read_location (rtx_insn *insn);
     126                 :             : 
     127                 :             :   void handle_insn_uids ();
     128                 :             :   void apply_fixups ();
     129                 :             : 
     130                 :             :  private:
     131                 :             :   struct uid_hash : int_hash <int, -1, -2> {};
     132                 :             :   hash_map<uid_hash, rtx_insn *> m_insns_by_uid;
     133                 :             :   auto_vec<fixup *> m_fixups;
     134                 :             :   rtx_insn *m_first_insn;
     135                 :             :   auto_vec<tree> m_fake_scope;
     136                 :             :   char *m_name;
     137                 :             :   bool m_have_crtl_directive;
     138                 :             :   basic_block m_bb_to_insert_after;
     139                 :             :   auto_vec <deferred_edge> m_deferred_edges;
     140                 :             :   int m_highest_bb_idx;
     141                 :             : };
     142                 :             : 
     143                 :             : /* Abstract base class for recording post-processing steps that must be
     144                 :             :    done after reading a .rtl file.  */
     145                 :             : 
     146                 :             : class fixup
     147                 :             : {
     148                 :             :  public:
     149                 :             :   /* Constructor for a fixup at LOC affecting X.  */
     150                 :         374 :   fixup (file_location loc, rtx x)
     151                 :         374 :     : m_loc (loc), m_rtx (x)
     152                 :             :   {}
     153                 :         289 :   virtual ~fixup () {}
     154                 :             : 
     155                 :             :   virtual void apply (function_reader *reader) const = 0;
     156                 :             : 
     157                 :             :  protected:
     158                 :             :   file_location m_loc;
     159                 :             :   rtx m_rtx;
     160                 :             : };
     161                 :             : 
     162                 :             : /* An abstract subclass of fixup for post-processing steps that
     163                 :             :    act on a specific operand of a specific instruction.  */
     164                 :             : 
     165                 :             : class operand_fixup : public fixup
     166                 :             : {
     167                 :             :  public:
     168                 :             :   /* Constructor for a fixup at LOC affecting INSN's operand
     169                 :             :      with index OPERAND_IDX.  */
     170                 :          85 :   operand_fixup (file_location loc, rtx insn, int operand_idx)
     171                 :          85 :     : fixup (loc, insn), m_operand_idx (operand_idx)
     172                 :             :   {}
     173                 :             : 
     174                 :             :  protected:
     175                 :             :   int m_operand_idx;
     176                 :             : };
     177                 :             : 
     178                 :             : /* A concrete subclass of operand_fixup: fixup an rtx_insn *
     179                 :             :    field based on an integer UID.  */
     180                 :             : 
     181                 :             : class fixup_insn_uid : public operand_fixup
     182                 :             : {
     183                 :             :  public:
     184                 :             :   /* Constructor for a fixup at LOC affecting INSN's operand
     185                 :             :      with index OPERAND_IDX.  Record INSN_UID as the uid.  */
     186                 :          20 :   fixup_insn_uid (file_location loc, rtx insn, int operand_idx, int insn_uid)
     187                 :          20 :     : operand_fixup (loc, insn, operand_idx),
     188                 :          20 :       m_insn_uid (insn_uid)
     189                 :             :   {}
     190                 :             : 
     191                 :             :   void apply (function_reader *reader) const final override;
     192                 :             : 
     193                 :             :  private:
     194                 :             :   int m_insn_uid;
     195                 :             : };
     196                 :             : 
     197                 :             : /* A concrete subclass of operand_fixup: fix up a
     198                 :             :    NOTE_INSN_BASIC_BLOCK based on an integer block ID.  */
     199                 :             : 
     200                 :             : class fixup_note_insn_basic_block : public operand_fixup
     201                 :             : {
     202                 :             :  public:
     203                 :          65 :   fixup_note_insn_basic_block (file_location loc, rtx insn, int operand_idx,
     204                 :             :                                int bb_idx)
     205                 :          65 :     : operand_fixup (loc, insn, operand_idx),
     206                 :          65 :       m_bb_idx (bb_idx)
     207                 :             :   {}
     208                 :             : 
     209                 :             :   void apply (function_reader *reader) const final override;
     210                 :             : 
     211                 :             :  private:
     212                 :             :   int m_bb_idx;
     213                 :             : };
     214                 :             : 
     215                 :             : /* A concrete subclass of fixup (not operand_fixup): fix up
     216                 :             :    the expr of an rtx (REG or MEM) based on a textual dump.  */
     217                 :             : 
     218                 :             : class fixup_expr : public fixup
     219                 :             : {
     220                 :             :  public:
     221                 :         289 :   fixup_expr (file_location loc, rtx x, const char *desc)
     222                 :         289 :     : fixup (loc, x),
     223                 :         578 :       m_desc (xstrdup (desc))
     224                 :             :   {}
     225                 :             : 
     226                 :         289 :   ~fixup_expr () { free (m_desc); }
     227                 :             : 
     228                 :             :   void apply (function_reader *reader) const final override;
     229                 :             : 
     230                 :             :  private:
     231                 :             :   char *m_desc;
     232                 :             : };
     233                 :             : 
     234                 :             : /* Return a textual description of the operand of INSN with
     235                 :             :    index OPERAND_IDX.  */
     236                 :             : 
     237                 :             : static const char *
     238                 :           0 : get_operand_name (rtx insn, int operand_idx)
     239                 :             : {
     240                 :           0 :   gcc_assert (is_a <rtx_insn *> (insn));
     241                 :           0 :   switch (operand_idx)
     242                 :             :     {
     243                 :             :     case 0:
     244                 :             :       return "PREV_INSN";
     245                 :           0 :     case 1:
     246                 :           0 :       return "NEXT_INSN";
     247                 :           0 :     default:
     248                 :           0 :       return NULL;
     249                 :             :     }
     250                 :             : }
     251                 :             : 
     252                 :             : /* Fixup an rtx_insn * field based on an integer UID, as read by READER.  */
     253                 :             : 
     254                 :             : void
     255                 :          20 : fixup_insn_uid::apply (function_reader *reader) const
     256                 :             : {
     257                 :          20 :   rtx_insn **insn_from_uid = reader->get_insn_by_uid (m_insn_uid);
     258                 :          20 :   if (insn_from_uid)
     259                 :          20 :     XEXP (m_rtx, m_operand_idx) = *insn_from_uid;
     260                 :             :   else
     261                 :             :     {
     262                 :           0 :       const char *op_name = get_operand_name (m_rtx, m_operand_idx);
     263                 :           0 :       if (op_name)
     264                 :           0 :         error_at (m_loc,
     265                 :             :                   "insn with UID %i not found for operand %i (`%s') of insn %i",
     266                 :           0 :                   m_insn_uid, m_operand_idx, op_name, INSN_UID (m_rtx));
     267                 :             :       else
     268                 :           0 :         error_at (m_loc,
     269                 :             :                   "insn with UID %i not found for operand %i of insn %i",
     270                 :           0 :                   m_insn_uid, m_operand_idx, INSN_UID (m_rtx));
     271                 :             :     }
     272                 :          20 : }
     273                 :             : 
     274                 :             : /* Fix up a NOTE_INSN_BASIC_BLOCK based on an integer block ID.  */
     275                 :             : 
     276                 :             : void
     277                 :          65 : fixup_note_insn_basic_block::apply (function_reader *) const
     278                 :             : {
     279                 :          65 :   basic_block bb = BASIC_BLOCK_FOR_FN (cfun, m_bb_idx);
     280                 :          65 :   gcc_assert (bb);
     281                 :          65 :   NOTE_BASIC_BLOCK (m_rtx) = bb;
     282                 :          65 : }
     283                 :             : 
     284                 :             : /* Fix up the expr of an rtx (REG or MEM) based on a textual dump
     285                 :             :    read by READER.  */
     286                 :             : 
     287                 :             : void
     288                 :         289 : fixup_expr::apply (function_reader *reader) const
     289                 :             : {
     290                 :         289 :   tree expr = reader->parse_mem_expr (m_desc);
     291                 :         289 :   switch (GET_CODE (m_rtx))
     292                 :             :     {
     293                 :         150 :     case REG:
     294                 :         150 :       set_reg_attrs_for_decl_rtl (expr, m_rtx);
     295                 :         150 :       break;
     296                 :         139 :     case MEM:
     297                 :         139 :       set_mem_expr (m_rtx, expr);
     298                 :         139 :       break;
     299                 :           0 :     default:
     300                 :           0 :       gcc_unreachable ();
     301                 :             :     }
     302                 :         289 : }
     303                 :             : 
     304                 :             : /* Strip trailing whitespace from DESC.  */
     305                 :             : 
     306                 :             : static void
     307                 :         162 : strip_trailing_whitespace (char *desc)
     308                 :             : {
     309                 :         162 :   char *terminator = desc + strlen (desc);
     310                 :         312 :   while (desc < terminator)
     311                 :             :     {
     312                 :         312 :       terminator--;
     313                 :         312 :       if (ISSPACE (*terminator))
     314                 :         150 :         *terminator = '\0';
     315                 :             :       else
     316                 :             :         break;
     317                 :             :     }
     318                 :         162 : }
     319                 :             : 
     320                 :             : /* Return the numeric value n for GET_NOTE_INSN_NAME (n) for STRING,
     321                 :             :    or fail if STRING isn't recognized.  */
     322                 :             : 
     323                 :             : static int
     324                 :         113 : parse_note_insn_name (const char *string)
     325                 :             : {
     326                 :        1076 :   for (int i = 0; i < NOTE_INSN_MAX; i++)
     327                 :        1076 :     if (strcmp (string, GET_NOTE_INSN_NAME (i)) == 0)
     328                 :         113 :       return i;
     329                 :           0 :   fatal_with_file_and_line ("unrecognized NOTE_INSN name: `%s'", string);
     330                 :             : }
     331                 :             : 
     332                 :             : /* Return the register number for NAME, or return -1 if it isn't
     333                 :             :    recognized.  */
     334                 :             : 
     335                 :             : static int
     336                 :         589 : lookup_reg_by_dump_name (const char *name)
     337                 :             : {
     338                 :       32499 :   for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     339                 :       32180 :     if (reg_names[i][0]
     340                 :       32180 :         && ! strcmp (name, reg_names[i]))
     341                 :             :       return i;
     342                 :             : 
     343                 :             :   /* Also lookup virtuals.  */
     344                 :         319 :   if (!strcmp (name, "virtual-incoming-args"))
     345                 :             :     return VIRTUAL_INCOMING_ARGS_REGNUM;
     346                 :         315 :   if (!strcmp (name, "virtual-stack-vars"))
     347                 :             :     return VIRTUAL_STACK_VARS_REGNUM;
     348                 :         277 :   if (!strcmp (name, "virtual-stack-dynamic"))
     349                 :             :     return VIRTUAL_STACK_DYNAMIC_REGNUM;
     350                 :         273 :   if (!strcmp (name, "virtual-outgoing-args"))
     351                 :             :     return VIRTUAL_OUTGOING_ARGS_REGNUM;
     352                 :         269 :   if (!strcmp (name, "virtual-cfa"))
     353                 :             :     return VIRTUAL_CFA_REGNUM;
     354                 :         265 :   if (!strcmp (name, "virtual-preferred-stack-boundary"))
     355                 :             :     return VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM;
     356                 :             :   /* TODO: handle "virtual-reg-%d".  */
     357                 :             : 
     358                 :             :   /* In compact mode, pseudos are printed with '< and '>' wrapping the regno,
     359                 :             :      offseting it by (LAST_VIRTUAL_REGISTER + 1), so that the
     360                 :             :      first non-virtual pseudo is dumped as "<0>".  */
     361                 :         261 :   if (name[0] == '<' && name[strlen (name) - 1] == '>')
     362                 :             :     {
     363                 :         257 :       int dump_num = atoi (name + 1);
     364                 :         257 :       return dump_num + LAST_VIRTUAL_REGISTER + 1;
     365                 :             :     }
     366                 :             : 
     367                 :             :   /* Not found.  */
     368                 :             :   return -1;
     369                 :             : }
     370                 :             : 
     371                 :             : /* class function_reader : public rtx_reader */
     372                 :             : 
     373                 :             : /* function_reader's constructor.  */
     374                 :             : 
     375                 :          94 : function_reader::function_reader ()
     376                 :             : : rtx_reader (true),
     377                 :          94 :   m_first_insn (NULL),
     378                 :          94 :   m_name (NULL),
     379                 :          94 :   m_have_crtl_directive (false),
     380                 :          94 :   m_bb_to_insert_after (NULL),
     381                 :          94 :   m_highest_bb_idx (EXIT_BLOCK)
     382                 :             : {
     383                 :          94 : }
     384                 :             : 
     385                 :             : /* function_reader's destructor.  */
     386                 :             : 
     387                 :          93 : function_reader::~function_reader ()
     388                 :             : {
     389                 :          93 :   int i;
     390                 :          93 :   fixup *f;
     391                 :         467 :   FOR_EACH_VEC_ELT (m_fixups, i, f)
     392                 :         374 :     delete f;
     393                 :             : 
     394                 :          93 :   free (m_name);
     395                 :          93 : }
     396                 :             : 
     397                 :             : /* Implementation of rtx_reader::handle_unknown_directive,
     398                 :             :    for parsing the remainder of a directive with name NAME
     399                 :             :    seen at START_LOC.
     400                 :             : 
     401                 :             :    Require a top-level "function" directive, as emitted by
     402                 :             :    print_rtx_function, and parse it.  */
     403                 :             : 
     404                 :             : void
     405                 :          94 : function_reader::handle_unknown_directive (file_location start_loc,
     406                 :             :                                            const char *name)
     407                 :             : {
     408                 :          94 :   if (strcmp (name, "function"))
     409                 :           0 :     fatal_at (start_loc, "expected 'function'");
     410                 :             : 
     411                 :          94 :   if (flag_lto)
     412                 :           0 :     error ("%<__RTL%> function cannot be compiled with %<-flto%>");
     413                 :             : 
     414                 :          94 :   parse_function ();
     415                 :          93 : }
     416                 :             : 
     417                 :             : /* Parse the output of print_rtx_function (or hand-written data in the
     418                 :             :    same format), having already parsed the "(function" heading, and
     419                 :             :    finishing immediately before the final ")".
     420                 :             : 
     421                 :             :    The "param" and "crtl" clauses are optional.  */
     422                 :             : 
     423                 :             : void
     424                 :          94 : function_reader::parse_function ()
     425                 :             : {
     426                 :          94 :   m_name = xstrdup (read_string (0));
     427                 :             : 
     428                 :          94 :   create_function ();
     429                 :             : 
     430                 :         366 :   while (1)
     431                 :             :     {
     432                 :         230 :       int c = read_skip_spaces ();
     433                 :         230 :       if (c == ')')
     434                 :             :         {
     435                 :          93 :           unread_char (c);
     436                 :          93 :           break;
     437                 :             :         }
     438                 :         137 :       unread_char (c);
     439                 :         137 :       require_char ('(');
     440                 :         137 :       file_location loc = get_current_location ();
     441                 :         137 :       struct md_name directive;
     442                 :         137 :       read_name (&directive);
     443                 :         137 :       if (strcmp (directive.string, "param") == 0)
     444                 :          22 :         parse_param ();
     445                 :         115 :       else if (strcmp (directive.string, "insn-chain") == 0)
     446                 :          94 :         parse_insn_chain ();
     447                 :          21 :       else if (strcmp (directive.string, "crtl") == 0)
     448                 :          21 :         parse_crtl (loc);
     449                 :             :       else
     450                 :           0 :         fatal_with_file_and_line ("unrecognized directive: %s",
     451                 :             :                                   directive.string);
     452                 :         136 :     }
     453                 :             : 
     454                 :          93 :   handle_insn_uids ();
     455                 :             : 
     456                 :          93 :   apply_fixups ();
     457                 :             : 
     458                 :             :   /* Rebuild the JUMP_LABEL field of any JUMP_INSNs in the chain, and the
     459                 :             :      LABEL_NUSES of any CODE_LABELs.
     460                 :             : 
     461                 :             :      This has to happen after apply_fixups, since only after then do
     462                 :             :      LABEL_REFs have their label_ref_label set up.  */
     463                 :          93 :   rebuild_jump_labels (get_insns ());
     464                 :             : 
     465                 :          93 :   crtl->init_stack_alignment ();
     466                 :          93 : }
     467                 :             : 
     468                 :             : /* Set up state for the function *before* fixups are applied.
     469                 :             : 
     470                 :             :    Create "cfun" and a decl for the function.
     471                 :             :    By default, every function decl is hardcoded as
     472                 :             :       int test_1 (int i, int j, int k);
     473                 :             :    Set up various other state:
     474                 :             :    - the cfg and basic blocks (edges are created later, *after* fixups
     475                 :             :    are applied).
     476                 :             :    - add the function to the callgraph.  */
     477                 :             : 
     478                 :             : void
     479                 :          94 : function_reader::create_function ()
     480                 :             : {
     481                 :             :   /* We start in cfgrtl mode, rather than cfglayout mode.  */
     482                 :          94 :   rtl_register_cfg_hooks ();
     483                 :             : 
     484                 :             :   /* When run from selftests or "rtl1", cfun is NULL.
     485                 :             :      When run from "cc1" for a C function tagged with __RTL, cfun is the
     486                 :             :      tagged function.  */
     487                 :          94 :   if (!cfun)
     488                 :             :     {
     489                 :         152 :       tree fn_name = get_identifier (m_name ? m_name : "test_1");
     490                 :          76 :       tree int_type = integer_type_node;
     491                 :          76 :       tree return_type = int_type;
     492                 :          76 :       tree arg_types[3] = {int_type, int_type, int_type};
     493                 :          76 :       tree fn_type = build_function_type_array (return_type, 3, arg_types);
     494                 :          76 :       tree fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, fn_name, fn_type);
     495                 :          76 :       tree resdecl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE,
     496                 :             :                                  return_type);
     497                 :          76 :       DECL_ARTIFICIAL (resdecl) = 1;
     498                 :          76 :       DECL_IGNORED_P (resdecl) = 1;
     499                 :          76 :       DECL_RESULT (fndecl) = resdecl;
     500                 :          76 :       allocate_struct_function (fndecl, false);
     501                 :             :       /* This sets cfun.  */
     502                 :          76 :       current_function_decl = fndecl;
     503                 :             :     }
     504                 :             : 
     505                 :          94 :   gcc_assert (cfun);
     506                 :          94 :   gcc_assert (current_function_decl);
     507                 :          94 :   tree fndecl = current_function_decl;
     508                 :             : 
     509                 :             :   /* Mark this function as being specified as __RTL.  */
     510                 :          94 :   cfun->curr_properties |= PROP_rtl;
     511                 :             : 
     512                 :             :   /* cc1 normally inits DECL_INITIAL (fndecl) to be error_mark_node.
     513                 :             :      Create a dummy block for it.  */
     514                 :          94 :   DECL_INITIAL (fndecl) = make_node (BLOCK);
     515                 :             : 
     516                 :          94 :   cfun->curr_properties = (PROP_cfg | PROP_rtl);
     517                 :             : 
     518                 :             :   /* Do we need this to force cgraphunit.cc to output the function? */
     519                 :          94 :   DECL_EXTERNAL (fndecl) = 0;
     520                 :          94 :   DECL_PRESERVE_P (fndecl) = 1;
     521                 :             : 
     522                 :             :   /* Add to cgraph.  */
     523                 :          94 :   cgraph_node::finalize_function (fndecl, false);
     524                 :             : 
     525                 :             :   /* Create bare-bones cfg.  This creates the entry and exit blocks.  */
     526                 :          94 :   init_empty_tree_cfg_for_function (cfun);
     527                 :          94 :   ENTRY_BLOCK_PTR_FOR_FN (cfun)->flags |= BB_RTL;
     528                 :          94 :   EXIT_BLOCK_PTR_FOR_FN (cfun)->flags |= BB_RTL;
     529                 :          94 :   init_rtl_bb_info (ENTRY_BLOCK_PTR_FOR_FN (cfun));
     530                 :          94 :   init_rtl_bb_info (EXIT_BLOCK_PTR_FOR_FN (cfun));
     531                 :          94 :   m_bb_to_insert_after = ENTRY_BLOCK_PTR_FOR_FN (cfun);
     532                 :             : 
     533                 :          94 : }
     534                 :             : 
     535                 :             : /* Look within the params of FNDECL for a param named NAME.
     536                 :             :    Return NULL_TREE if one isn't found.  */
     537                 :             : 
     538                 :             : static tree
     539                 :         277 : find_param_by_name (tree fndecl, const char *name)
     540                 :             : {
     541                 :         564 :   for (tree arg = DECL_ARGUMENTS (fndecl); arg; arg = TREE_CHAIN (arg))
     542                 :         467 :     if (id_equal (DECL_NAME (arg), name))
     543                 :             :       return arg;
     544                 :             :   return NULL_TREE;
     545                 :             : }
     546                 :             : 
     547                 :             : /* Parse the content of a "param" directive, having already parsed the
     548                 :             :    "(param".  Consume the trailing ')'.  */
     549                 :             : 
     550                 :             : void
     551                 :          22 : function_reader::parse_param ()
     552                 :             : {
     553                 :          22 :   require_char_ws ('"');
     554                 :          22 :   file_location loc = get_current_location ();
     555                 :          22 :   char *name = read_quoted_string ();
     556                 :             : 
     557                 :             :   /* Lookup param by name.  */
     558                 :          22 :   tree t_param = find_param_by_name (cfun->decl, name);
     559                 :          22 :   if (!t_param)
     560                 :           0 :     fatal_at (loc, "param not found: %s", name);
     561                 :             : 
     562                 :             :   /* Parse DECL_RTL.  */
     563                 :          22 :   require_char_ws ('(');
     564                 :          22 :   require_word_ws ("DECL_RTL");
     565                 :          22 :   DECL_WRTL_CHECK (t_param)->decl_with_rtl.rtl = parse_rtx ();
     566                 :          22 :   require_char_ws (')');
     567                 :             : 
     568                 :             :   /* Parse DECL_RTL_INCOMING.  */
     569                 :          22 :   require_char_ws ('(');
     570                 :          22 :   require_word_ws ("DECL_RTL_INCOMING");
     571                 :          22 :   DECL_INCOMING_RTL (t_param) = parse_rtx ();
     572                 :          22 :   require_char_ws (')');
     573                 :             : 
     574                 :          22 :   require_char_ws (')');
     575                 :          22 : }
     576                 :             : 
     577                 :             : /* Parse zero or more child insn elements within an
     578                 :             :    "insn-chain" element.  Consume the trailing ')'.  */
     579                 :             : 
     580                 :             : void
     581                 :          94 : function_reader::parse_insn_chain ()
     582                 :             : {
     583                 :         430 :   while (1)
     584                 :             :     {
     585                 :         262 :       int c = read_skip_spaces ();
     586                 :         262 :       file_location loc = get_current_location ();
     587                 :         262 :       if (c == ')')
     588                 :             :         break;
     589                 :         169 :       else if (c == '(')
     590                 :             :         {
     591                 :         169 :           struct md_name directive;
     592                 :         169 :           read_name (&directive);
     593                 :         169 :           if (strcmp (directive.string, "block") == 0)
     594                 :         129 :             parse_block ();
     595                 :             :           else
     596                 :          40 :             parse_insn (loc, directive.string);
     597                 :             :         }
     598                 :             :       else
     599                 :           0 :         fatal_at (loc, "expected '(' or ')'");
     600                 :         168 :     }
     601                 :             : 
     602                 :          93 :   create_edges ();
     603                 :          93 : }
     604                 :             : 
     605                 :             : /* Parse zero or more child directives (edges and insns) within a
     606                 :             :    "block" directive, having already parsed the "(block " heading.
     607                 :             :    Consume the trailing ')'.  */
     608                 :             : 
     609                 :             : void
     610                 :         129 : function_reader::parse_block ()
     611                 :             : {
     612                 :             :   /* Parse the index value from the dump.  This will be an integer;
     613                 :             :      we don't support "entry" or "exit" here (unlike for edges).  */
     614                 :         129 :   struct md_name name;
     615                 :         129 :   read_name (&name);
     616                 :         129 :   int bb_idx = atoi (name.string);
     617                 :             : 
     618                 :             :   /* The term "index" has two meanings for basic blocks in a CFG:
     619                 :             :      (a) the "index" field within struct basic_block_def.
     620                 :             :      (b) the index of a basic_block within the cfg's x_basic_block_info
     621                 :             :      vector, as accessed via BASIC_BLOCK_FOR_FN.
     622                 :             : 
     623                 :             :      These can get out-of-sync when basic blocks are optimized away.
     624                 :             :      They get back in sync by "compact_blocks".
     625                 :             :      We reconstruct cfun->cfg->x_basic_block_info->address () pointed
     626                 :             :      vector elements with NULL values in it for any missing basic blocks,
     627                 :             :      so that (a) == (b) for all of the blocks we create.  The
     628                 :             :      doubly-linked list of basic blocks (next_bb/prev_bb) skips over
     629                 :             :      these "holes".  */
     630                 :             : 
     631                 :         129 :   if (m_highest_bb_idx < bb_idx)
     632                 :         129 :     m_highest_bb_idx = bb_idx;
     633                 :             : 
     634                 :         129 :   size_t new_size = m_highest_bb_idx + 1;
     635                 :         129 :   if (basic_block_info_for_fn (cfun)->length () < new_size)
     636                 :           4 :     vec_safe_grow_cleared (basic_block_info_for_fn (cfun), new_size, true);
     637                 :             : 
     638                 :         129 :   last_basic_block_for_fn (cfun) = new_size;
     639                 :             : 
     640                 :             :   /* Create the basic block.
     641                 :             : 
     642                 :             :      We can't call create_basic_block and use the regular RTL block-creation
     643                 :             :      hooks, since this creates NOTE_INSN_BASIC_BLOCK instances.  We don't
     644                 :             :      want to do that; we want to use the notes we were provided with.  */
     645                 :         129 :   basic_block bb = alloc_block ();
     646                 :         129 :   init_rtl_bb_info (bb);
     647                 :         129 :   bb->index = bb_idx;
     648                 :         129 :   bb->flags = BB_NEW | BB_RTL;
     649                 :         129 :   link_block (bb, m_bb_to_insert_after);
     650                 :         129 :   m_bb_to_insert_after = bb;
     651                 :             : 
     652                 :         129 :   n_basic_blocks_for_fn (cfun)++;
     653                 :         129 :   SET_BASIC_BLOCK_FOR_FN (cfun, bb_idx, bb);
     654                 :         129 :   BB_SET_PARTITION (bb, BB_UNPARTITIONED);
     655                 :             : 
     656                 :             :   /* Handle insns, edge-from and edge-to directives.  */
     657                 :        1417 :   while (1)
     658                 :             :     {
     659                 :         773 :       int c = read_skip_spaces ();
     660                 :         773 :       file_location loc = get_current_location ();
     661                 :         773 :       if (c == ')')
     662                 :             :         break;
     663                 :         644 :       else if (c == '(')
     664                 :             :         {
     665                 :         644 :           struct md_name directive;
     666                 :         644 :           read_name (&directive);
     667                 :         644 :           if (strcmp (directive.string, "edge-from") == 0)
     668                 :         129 :             parse_edge (bb, true);
     669                 :         515 :           else if (strcmp (directive.string, "edge-to") == 0)
     670                 :         129 :             parse_edge (bb, false);
     671                 :             :           else
     672                 :             :             {
     673                 :         386 :               rtx_insn *insn = parse_insn (loc, directive.string);
     674                 :         386 :               set_block_for_insn (insn, bb);
     675                 :         386 :               if (!BB_HEAD (bb))
     676                 :         125 :                 BB_HEAD (bb) = insn;
     677                 :         386 :               BB_END (bb) = insn;
     678                 :             :             }
     679                 :             :         }
     680                 :             :       else
     681                 :           0 :         fatal_at (loc, "expected '(' or ')'");
     682                 :         644 :     }
     683                 :         129 : }
     684                 :             : 
     685                 :             : /* Subroutine of function_reader::parse_edge.
     686                 :             :    Parse a basic block index, handling "entry" and "exit".  */
     687                 :             : 
     688                 :             : int
     689                 :         258 : function_reader::parse_bb_idx ()
     690                 :             : {
     691                 :         258 :   struct md_name name;
     692                 :         258 :   read_name (&name);
     693                 :         258 :   if (strcmp (name.string, "entry") == 0)
     694                 :             :     return ENTRY_BLOCK;
     695                 :         181 :   if (strcmp (name.string, "exit") == 0)
     696                 :             :     return EXIT_BLOCK;
     697                 :         104 :   return atoi (name.string);
     698                 :             : }
     699                 :             : 
     700                 :             : /* Subroutine of parse_edge_flags.
     701                 :             :    Parse TOK, a token such as "FALLTHRU", converting to the flag value.
     702                 :             :    Issue an error if the token is unrecognized.  */
     703                 :             : 
     704                 :             : static int
     705                 :         234 : parse_edge_flag_token (const char *tok)
     706                 :             : {
     707                 :             : #define DEF_EDGE_FLAG(NAME,IDX)         \
     708                 :             :   do {                                          \
     709                 :             :     if (strcmp (tok, #NAME) == 0)               \
     710                 :             :       return EDGE_##NAME; \
     711                 :             :   } while (0);
     712                 :             : #include "cfg-flags.def"
     713                 :             : #undef DEF_EDGE_FLAG
     714                 :           0 :   error ("unrecognized edge flag: %qs", tok);
     715                 :           0 :   return 0;
     716                 :             : }
     717                 :             : 
     718                 :             : /* Subroutine of function_reader::parse_edge.
     719                 :             :    Parse STR and convert to a flag value (or issue an error).
     720                 :             :    The parser uses strtok and hence modifiers STR in-place.  */
     721                 :             : 
     722                 :             : static int
     723                 :         233 : parse_edge_flags (char *str)
     724                 :             : {
     725                 :         233 :   int result = 0;
     726                 :             : 
     727                 :         233 :   char *tok = strtok (str, "| ");
     728                 :         700 :   while (tok)
     729                 :             :     {
     730                 :         234 :       result |= parse_edge_flag_token (tok);
     731                 :         234 :       tok = strtok (NULL, "| ");
     732                 :             :     }
     733                 :             : 
     734                 :         233 :   return result;
     735                 :             : }
     736                 :             : 
     737                 :             : /* Parse an "edge-from" or "edge-to" directive within the "block"
     738                 :             :    directive for BLOCK, having already parsed the "(edge" heading.
     739                 :             :    Consume the final ")".  Record the edge within m_deferred_edges.
     740                 :             :    FROM is true for an "edge-from" directive, false for an "edge-to"
     741                 :             :    directive.  */
     742                 :             : 
     743                 :             : void
     744                 :         258 : function_reader::parse_edge (basic_block block, bool from)
     745                 :             : {
     746                 :         258 :   gcc_assert (block);
     747                 :         258 :   int this_bb_idx = block->index;
     748                 :         258 :   file_location loc = get_current_location ();
     749                 :         258 :   int other_bb_idx = parse_bb_idx ();
     750                 :             : 
     751                 :             :   /* "(edge-from 2)" means src = 2, dest = this_bb_idx, whereas
     752                 :             :      "(edge-to 3)" means src = this_bb_idx, dest = 3.  */
     753                 :         258 :   int src_idx = from ? other_bb_idx : this_bb_idx;
     754                 :         129 :   int dest_idx = from ? this_bb_idx : other_bb_idx;
     755                 :             : 
     756                 :             :   /* Optional "(flags)".  */
     757                 :         258 :   int flags = 0;
     758                 :         258 :   int c = read_skip_spaces ();
     759                 :         258 :   if (c == '(')
     760                 :             :     {
     761                 :         217 :       require_word_ws ("flags");
     762                 :         217 :       require_char_ws ('"');
     763                 :         217 :       char *str = read_quoted_string ();
     764                 :         217 :       flags = parse_edge_flags (str);
     765                 :         217 :       require_char_ws (')');
     766                 :             :     }
     767                 :             :   else
     768                 :          41 :     unread_char (c);
     769                 :             : 
     770                 :         258 :   require_char_ws (')');
     771                 :             : 
     772                 :             :   /* This BB already exists, but the other BB might not yet.
     773                 :             :      For now, save the edges, and create them at the end of insn-chain
     774                 :             :      processing. */
     775                 :             :   /* For now, only process the (edge-from) to this BB, and (edge-to)
     776                 :             :      that go to the exit block.
     777                 :             :      FIXME: we don't yet verify that the edge-from and edge-to directives
     778                 :             :      are consistent.  */
     779                 :         258 :   if (from || dest_idx == EXIT_BLOCK)
     780                 :         206 :     m_deferred_edges.safe_push (deferred_edge (loc, src_idx, dest_idx, flags));
     781                 :         258 : }
     782                 :             : 
     783                 :             : /* Parse an rtx instruction, having parsed the opening and parenthesis, and
     784                 :             :    name NAME, seen at START_LOC, by calling read_rtx_code, calling
     785                 :             :    set_first_insn and set_last_insn as appropriate, and
     786                 :             :    adding the insn to the insn chain.
     787                 :             :    Consume the trailing ')'.  */
     788                 :             : 
     789                 :             : rtx_insn *
     790                 :         426 : function_reader::parse_insn (file_location start_loc, const char *name)
     791                 :             : {
     792                 :         426 :   rtx x = read_rtx_code (name);
     793                 :         425 :   if (!x)
     794                 :           0 :     fatal_at (start_loc, "expected insn type; got '%s'", name);
     795                 :         425 :   rtx_insn *insn = dyn_cast <rtx_insn *> (x);
     796                 :         425 :   if (!insn)
     797                 :           0 :     fatal_at (start_loc, "expected insn type; got '%s'", name);
     798                 :             : 
     799                 :             :   /* Consume the trailing ')'.  */
     800                 :         425 :   require_char_ws (')');
     801                 :             : 
     802                 :         425 :   rtx_insn *last_insn = get_last_insn ();
     803                 :             : 
     804                 :             :   /* Add "insn" to the insn chain.  */
     805                 :         425 :   if (last_insn)
     806                 :             :     {
     807                 :         336 :       gcc_assert (NEXT_INSN (last_insn) == NULL);
     808                 :         336 :       SET_NEXT_INSN (last_insn) = insn;
     809                 :             :     }
     810                 :         425 :   SET_PREV_INSN (insn) = last_insn;
     811                 :             : 
     812                 :             :   /* Add it to the sequence.  */
     813                 :         425 :   set_last_insn (insn);
     814                 :         425 :   if (!m_first_insn)
     815                 :             :     {
     816                 :          89 :       m_first_insn = insn;
     817                 :          89 :       set_first_insn (insn);
     818                 :             :     }
     819                 :             : 
     820                 :         425 :   if (rtx_code_label *label = dyn_cast <rtx_code_label *> (insn))
     821                 :          28 :     maybe_set_max_label_num (label);
     822                 :             : 
     823                 :         425 :   return insn;
     824                 :             : }
     825                 :             : 
     826                 :             : /* Postprocessing subroutine for parse_insn_chain: all the basic blocks
     827                 :             :    should have been created by now; create the edges that were seen.  */
     828                 :             : 
     829                 :             : void
     830                 :          93 : function_reader::create_edges ()
     831                 :             : {
     832                 :          93 :   int i;
     833                 :          93 :   deferred_edge *de;
     834                 :         299 :   FOR_EACH_VEC_ELT (m_deferred_edges, i, de)
     835                 :             :     {
     836                 :             :       /* The BBs should already have been created by parse_block.  */
     837                 :         206 :       basic_block src = BASIC_BLOCK_FOR_FN (cfun, de->m_src_bb_idx);
     838                 :         206 :       if (!src)
     839                 :           0 :         fatal_at (de->m_loc, "error: block index %i not found",
     840                 :             :                   de->m_src_bb_idx);
     841                 :         206 :       basic_block dst = BASIC_BLOCK_FOR_FN (cfun, de->m_dest_bb_idx);
     842                 :         206 :       if (!dst)
     843                 :           0 :         fatal_at (de->m_loc, "error: block with index %i not found",
     844                 :             :                   de->m_dest_bb_idx);
     845                 :         206 :       unchecked_make_edge (src, dst, de->m_flags);
     846                 :             :     }
     847                 :          93 : }
     848                 :             : 
     849                 :             : /* Parse a "crtl" directive, having already parsed the "(crtl" heading
     850                 :             :    at location LOC.
     851                 :             :    Consume the final ")".  */
     852                 :             : 
     853                 :             : void
     854                 :          21 : function_reader::parse_crtl (file_location loc)
     855                 :             : {
     856                 :          21 :   if (m_have_crtl_directive)
     857                 :           0 :     error_at (loc, "more than one 'crtl' directive");
     858                 :          21 :   m_have_crtl_directive = true;
     859                 :             : 
     860                 :             :   /* return_rtx.  */
     861                 :          21 :   require_char_ws ('(');
     862                 :          21 :   require_word_ws ("return_rtx");
     863                 :          21 :   crtl->return_rtx = parse_rtx ();
     864                 :          21 :   require_char_ws (')');
     865                 :             : 
     866                 :          21 :   require_char_ws (')');
     867                 :          21 : }
     868                 :             : 
     869                 :             : /* Parse operand IDX of X, returning X, or an equivalent rtx
     870                 :             :    expression (for consolidating singletons).
     871                 :             :    This is an overridden implementation of rtx_reader::read_rtx_operand for
     872                 :             :    function_reader, handling various extra data printed by print_rtx,
     873                 :             :    and sometimes calling the base class implementation.  */
     874                 :             : 
     875                 :             : rtx
     876                 :        5138 : function_reader::read_rtx_operand (rtx x, int idx)
     877                 :             : {
     878                 :        5138 :   RTX_CODE code = GET_CODE (x);
     879                 :        5138 :   const char *format_ptr = GET_RTX_FORMAT (code);
     880                 :        5138 :   const char format_char = format_ptr[idx];
     881                 :        5138 :   struct md_name name;
     882                 :             : 
     883                 :             :   /* Override the regular parser for some format codes.  */
     884                 :        5138 :   switch (format_char)
     885                 :             :     {
     886                 :        1762 :     case 'e':
     887                 :        1762 :       if (idx == 7 && CALL_P (x))
     888                 :             :         {
     889                 :           5 :           m_in_call_function_usage = true;
     890                 :           5 :           rtx tem = rtx_reader::read_rtx_operand (x, idx);
     891                 :           5 :           m_in_call_function_usage = false;
     892                 :           5 :           return tem;
     893                 :             :         }
     894                 :             :       else
     895                 :        1757 :         return rtx_reader::read_rtx_operand (x, idx);
     896                 :         870 :       break;
     897                 :             : 
     898                 :         870 :     case 'u':
     899                 :         870 :       read_rtx_operand_u (x, idx);
     900                 :             :       /* Don't run regular parser for 'u'.  */
     901                 :         870 :       return x;
     902                 :             : 
     903                 :         804 :     case 'i':
     904                 :         804 :     case 'n':
     905                 :         804 :     case 'L':
     906                 :         804 :       read_rtx_operand_inL (x, idx, format_char);
     907                 :             :       /* Don't run regular parser for these codes.  */
     908                 :         804 :       return x;
     909                 :             : 
     910                 :         411 :     case 'B':
     911                 :         411 :       gcc_assert (is_compact ());
     912                 :             :       /* Compact mode doesn't store BBs.  */
     913                 :             :       /* Don't run regular parser.  */
     914                 :             :       return x;
     915                 :             : 
     916                 :         553 :     case 'r':
     917                 :             :       /* Don't run regular parser for 'r'.  */
     918                 :         553 :       return read_rtx_operand_r (x);
     919                 :             : 
     920                 :         738 :     default:
     921                 :         738 :       break;
     922                 :             :     }
     923                 :             : 
     924                 :             :   /* Call base class implementation.  */
     925                 :         738 :   x = rtx_reader::read_rtx_operand (x, idx);
     926                 :             : 
     927                 :             :   /* Handle any additional parsing needed to handle what the dump
     928                 :             :      could contain.  */
     929                 :         738 :   switch (format_char)
     930                 :             :     {
     931                 :         443 :     case '0':
     932                 :         443 :       x = extra_parsing_for_operand_code_0 (x, idx);
     933                 :         443 :       break;
     934                 :             : 
     935                 :         212 :     case 'w':
     936                 :         212 :       if (!is_compact ())
     937                 :             :         {
     938                 :             :           /* Strip away the redundant hex dump of the value.  */
     939                 :           0 :           require_char_ws ('[');
     940                 :           0 :           read_name (&name);
     941                 :           0 :           require_char_ws (']');
     942                 :             :         }
     943                 :             :       break;
     944                 :             : 
     945                 :             :     default:
     946                 :             :       break;
     947                 :             :     }
     948                 :             : 
     949                 :             :   return x;
     950                 :             : }
     951                 :             : 
     952                 :             : /* Parse operand IDX of X, of code 'u', when reading function dumps.
     953                 :             : 
     954                 :             :    The RTL file recorded the ID of an insn (or 0 for NULL); we
     955                 :             :    must store this as a pointer, but the insn might not have
     956                 :             :    been loaded yet.  Store the ID away for now, via a fixup.  */
     957                 :             : 
     958                 :             : void
     959                 :         870 : function_reader::read_rtx_operand_u (rtx x, int idx)
     960                 :             : {
     961                 :             :   /* In compact mode, the PREV/NEXT insn uids are not dumped, so skip
     962                 :             :      the "uu" when reading. */
     963                 :         870 :   if (is_compact () && GET_CODE (x) != LABEL_REF)
     964                 :         850 :     return;
     965                 :             : 
     966                 :          20 :   struct md_name name;
     967                 :          20 :   file_location loc = read_name (&name);
     968                 :          20 :   int insn_id = atoi (name.string);
     969                 :          20 :   if (insn_id)
     970                 :          20 :     add_fixup_insn_uid (loc, x, idx, insn_id);
     971                 :             : }
     972                 :             : 
     973                 :             : /* Read a name, looking for a match against a string found in array
     974                 :             :    STRINGS of size NUM_VALUES.
     975                 :             :    Return the index of the matched string, or emit an error.  */
     976                 :             : 
     977                 :             : int
     978                 :          10 : function_reader::parse_enum_value (int num_values, const char *const *strings)
     979                 :             : {
     980                 :          10 :   struct md_name name;
     981                 :          10 :   read_name (&name);
     982                 :         152 :   for (int i = 0; i < num_values; i++)
     983                 :             :     {
     984                 :         152 :       if (strcmp (name.string, strings[i]) == 0)
     985                 :             :         return i;
     986                 :             :     }
     987                 :           0 :   error ("unrecognized enum value: %qs", name.string);
     988                 :           0 :   return 0;
     989                 :             : }
     990                 :             : 
     991                 :             : /* Parse operand IDX of X, of code 'i' or 'n' (as specified by FORMAT_CHAR).
     992                 :             :    Special-cased handling of these, for reading function dumps.  */
     993                 :             : 
     994                 :             : void
     995                 :         804 : function_reader::read_rtx_operand_inL (rtx x, int idx, char format_char)
     996                 :             : {
     997                 :             :   /* Handle some of the extra information that print_rtx
     998                 :             :      can write out for these cases.  */
     999                 :             :   /* print_rtx only writes out operand 5 for notes
    1000                 :             :      for NOTE_KIND values NOTE_INSN_DELETED_LABEL
    1001                 :             :      and NOTE_INSN_DELETED_DEBUG_LABEL.  */
    1002                 :         804 :   if (idx == 5 && NOTE_P (x))
    1003                 :         663 :     return;
    1004                 :             : 
    1005                 :         691 :   if (idx == 4 && INSN_P (x))
    1006                 :             :     {
    1007                 :         270 :       maybe_read_location (as_a <rtx_insn *> (x));
    1008                 :         270 :       return;
    1009                 :             :     }
    1010                 :             : 
    1011                 :             :   /* INSN_CODEs aren't printed in compact mode, so don't attempt to
    1012                 :             :      parse them.  */
    1013                 :         421 :   if (is_compact ()
    1014                 :         421 :       && INSN_P (x)
    1015                 :         691 :       && &INSN_CODE (x) == &XINT (x, idx))
    1016                 :             :     {
    1017                 :         270 :       INSN_CODE (x) = -1;
    1018                 :         270 :       return;
    1019                 :             :     }
    1020                 :             : 
    1021                 :             :   /* Handle UNSPEC and UNSPEC_VOLATILE's operand 1.  */
    1022                 :             : #if !defined(GENERATOR_FILE) && NUM_UNSPECV_VALUES > 0
    1023                 :         151 :   if (idx == 1
    1024                 :          10 :       && GET_CODE (x) == UNSPEC_VOLATILE)
    1025                 :             :     {
    1026                 :           4 :       XINT (x, 1)
    1027                 :           4 :         = parse_enum_value (NUM_UNSPECV_VALUES, unspecv_strings);
    1028                 :           4 :       return;
    1029                 :             :     }
    1030                 :             : #endif
    1031                 :             : #if !defined(GENERATOR_FILE) && NUM_UNSPEC_VALUES > 0
    1032                 :           6 :   if (idx == 1
    1033                 :           6 :       && (GET_CODE (x) == UNSPEC
    1034                 :           6 :           || GET_CODE (x) == UNSPEC_VOLATILE))
    1035                 :             :     {
    1036                 :           6 :       XINT (x, 1)
    1037                 :           6 :         = parse_enum_value (NUM_UNSPEC_VALUES, unspec_strings);
    1038                 :           6 :       return;
    1039                 :             :     }
    1040                 :             : #endif
    1041                 :             : 
    1042                 :         141 :   struct md_name name;
    1043                 :         141 :   read_name (&name);
    1044                 :         141 :   int value;
    1045                 :         141 :   if (format_char == 'n')
    1046                 :         113 :     value = parse_note_insn_name (name.string);
    1047                 :             :   else
    1048                 :             :     {
    1049                 :          28 :       gcc_checking_assert (format_char == 'i');
    1050                 :          28 :       value = atoi (name.string);
    1051                 :             :     }
    1052                 :         141 :   XINT (x, idx) = value;
    1053                 :             : }
    1054                 :             : 
    1055                 :             : /* Parse the 'r' operand of X, returning X, or an equivalent rtx
    1056                 :             :    expression (for consolidating singletons).
    1057                 :             :    Special-cased handling of code 'r' for reading function dumps.  */
    1058                 :             : 
    1059                 :             : rtx
    1060                 :         553 : function_reader::read_rtx_operand_r (rtx x)
    1061                 :             : {
    1062                 :         553 :   struct md_name name;
    1063                 :         553 :   file_location loc = read_name (&name);
    1064                 :         553 :   int regno = lookup_reg_by_dump_name (name.string);
    1065                 :         553 :   if (regno == -1)
    1066                 :           0 :     fatal_at (loc, "unrecognized register: '%s'", name.string);
    1067                 :             : 
    1068                 :         553 :   set_regno_raw (x, regno, 1);
    1069                 :             : 
    1070                 :             :   /* Consolidate singletons.  */
    1071                 :         553 :   x = consolidate_singletons (x);
    1072                 :             : 
    1073                 :         553 :   ORIGINAL_REGNO (x) = regno;
    1074                 :             : 
    1075                 :             :   /* Parse extra stuff at end of 'r'.
    1076                 :             :      We may have zero, one, or two sections marked by square
    1077                 :             :      brackets.  */
    1078                 :         553 :   int ch = read_skip_spaces ();
    1079                 :         553 :   bool expect_original_regno = false;
    1080                 :         553 :   if (ch == '[')
    1081                 :             :     {
    1082                 :         162 :       file_location loc = get_current_location ();
    1083                 :         162 :       char *desc = read_until ("]", true);
    1084                 :         162 :       strip_trailing_whitespace (desc);
    1085                 :         162 :       const char *desc_start = desc;
    1086                 :             :       /* If ORIGINAL_REGNO (rtx) != regno, we will have:
    1087                 :             :          "orig:%i", ORIGINAL_REGNO (rtx).
    1088                 :             :          Consume it, we don't set ORIGINAL_REGNO, since we can
    1089                 :             :          get that from the 2nd copy later.  */
    1090                 :         162 :       if (startswith (desc, "orig:"))
    1091                 :             :         {
    1092                 :           4 :           expect_original_regno = true;
    1093                 :           4 :           desc_start += 5;
    1094                 :             :           /* Skip to any whitespace following the integer.  */
    1095                 :           4 :           const char *space = strchr (desc_start, ' ');
    1096                 :           4 :           if (space)
    1097                 :           4 :             desc_start = space + 1;
    1098                 :             :         }
    1099                 :             :       /* Any remaining text may be the REG_EXPR.  Alternatively we have
    1100                 :             :          no REG_ATTRS, and instead we have ORIGINAL_REGNO.  */
    1101                 :         162 :       if (ISDIGIT (*desc_start))
    1102                 :             :         {
    1103                 :             :           /* Assume we have ORIGINAL_REGNO.  */
    1104                 :          12 :           ORIGINAL_REGNO (x) = atoi (desc_start);
    1105                 :             :         }
    1106                 :             :       else
    1107                 :             :         {
    1108                 :             :           /* Assume we have REG_EXPR.  */
    1109                 :         150 :           add_fixup_expr (loc, x, desc_start);
    1110                 :             :         }
    1111                 :         162 :       free (desc);
    1112                 :             :     }
    1113                 :             :   else
    1114                 :         391 :     unread_char (ch);
    1115                 :         553 :   if (expect_original_regno)
    1116                 :             :     {
    1117                 :           4 :       require_char_ws ('[');
    1118                 :           4 :       char *desc = read_until ("]", true);
    1119                 :           4 :       ORIGINAL_REGNO (x) = atoi (desc);
    1120                 :           4 :       free (desc);
    1121                 :             :     }
    1122                 :             : 
    1123                 :         553 :   return x;
    1124                 :             : }
    1125                 :             : 
    1126                 :             : /* Additional parsing for format code '0' in dumps, handling a variety
    1127                 :             :    of special-cases in print_rtx, when parsing operand IDX of X.
    1128                 :             :    Return X, or possibly a reallocated copy of X.  */
    1129                 :             : 
    1130                 :             : rtx
    1131                 :         443 : function_reader::extra_parsing_for_operand_code_0 (rtx x, int idx)
    1132                 :             : {
    1133                 :         443 :   RTX_CODE code = GET_CODE (x);
    1134                 :         443 :   int c;
    1135                 :         443 :   struct md_name name;
    1136                 :             : 
    1137                 :         443 :   if (idx == 1 && code == SYMBOL_REF)
    1138                 :             :     {
    1139                 :             :       /* Possibly wrote " [flags %#x]", SYMBOL_REF_FLAGS (in_rtx).  */
    1140                 :          14 :       c = read_skip_spaces ();
    1141                 :          14 :       if (c == '[')
    1142                 :             :         {
    1143                 :          14 :           file_location loc = read_name (&name);
    1144                 :          14 :           if (strcmp (name.string, "flags"))
    1145                 :           0 :             error_at (loc, "was expecting `%s'", "flags");
    1146                 :          14 :           read_name (&name);
    1147                 :          14 :           SYMBOL_REF_FLAGS (x) = strtol (name.string, NULL, 16);
    1148                 :             : 
    1149                 :             :           /* The standard RTX_CODE_SIZE (SYMBOL_REF) used when allocating
    1150                 :             :              x doesn't have space for the block_symbol information, so
    1151                 :             :              we must reallocate it if this flag is set.  */
    1152                 :          14 :           if (SYMBOL_REF_HAS_BLOCK_INFO_P (x))
    1153                 :             :             {
    1154                 :             :               /* Emulate the allocation normally done by
    1155                 :             :                  varasm.cc:create_block_symbol.  */
    1156                 :           4 :               unsigned int size = RTX_HDR_SIZE + sizeof (struct block_symbol);
    1157                 :           4 :               rtx new_x = (rtx) ggc_internal_alloc (size);
    1158                 :             : 
    1159                 :             :               /* Copy data over from the smaller SYMBOL_REF.  */
    1160                 :           4 :               memcpy (new_x, x, RTX_CODE_SIZE (SYMBOL_REF));
    1161                 :           4 :               x = new_x;
    1162                 :             : 
    1163                 :             :               /* We can't reconstruct SYMBOL_REF_BLOCK; set it to NULL.  */
    1164                 :           4 :               SYMBOL_REF_BLOCK (x) = NULL;
    1165                 :             : 
    1166                 :             :               /* Zero the offset.  */
    1167                 :           4 :               SYMBOL_REF_BLOCK_OFFSET (x) = 0;
    1168                 :             :             }
    1169                 :             : 
    1170                 :          14 :           require_char (']');
    1171                 :             :         }
    1172                 :             :       else
    1173                 :           0 :         unread_char (c);
    1174                 :             : 
    1175                 :             :       /* If X had a non-NULL SYMBOL_REF_DECL,
    1176                 :             :          rtx_writer::print_rtx_operand_code_0 would have dumped it
    1177                 :             :          using print_node_brief.
    1178                 :             :          Skip the content for now.  */
    1179                 :          14 :       c = read_skip_spaces ();
    1180                 :          14 :       if (c == '<')
    1181                 :             :         {
    1182                 :         512 :           while (1)
    1183                 :             :             {
    1184                 :         512 :               char ch = read_char ();
    1185                 :         512 :               if (ch == '>')
    1186                 :             :                 break;
    1187                 :             :             }
    1188                 :             :         }
    1189                 :             :       else
    1190                 :           0 :         unread_char (c);
    1191                 :             :     }
    1192                 :         429 :   else if (idx == 3 && code == NOTE)
    1193                 :             :     {
    1194                 :             :       /* Note-specific data appears for operand 3, which annoyingly
    1195                 :             :          is before the enum specifying which kind of note we have
    1196                 :             :          (operand 4).  */
    1197                 :         113 :       c = read_skip_spaces ();
    1198                 :         113 :       if (c == '[')
    1199                 :             :         {
    1200                 :             :           /* Possibly data for a NOTE_INSN_BASIC_BLOCK, of the form:
    1201                 :             :              [bb %d].  */
    1202                 :          65 :           file_location bb_loc = read_name (&name);
    1203                 :          65 :           if (strcmp (name.string, "bb"))
    1204                 :           0 :             error_at (bb_loc, "was expecting `%s'", "bb");
    1205                 :          65 :           read_name (&name);
    1206                 :          65 :           int bb_idx = atoi (name.string);
    1207                 :          65 :           add_fixup_note_insn_basic_block (bb_loc, x, idx,
    1208                 :             :                                            bb_idx);
    1209                 :          65 :           require_char_ws (']');
    1210                 :             :         }
    1211                 :             :       else
    1212                 :          48 :         unread_char (c);
    1213                 :             :     }
    1214                 :             : 
    1215                 :         443 :   return x;
    1216                 :             : }
    1217                 :             : 
    1218                 :             : /* Implementation of rtx_reader::handle_any_trailing_information.
    1219                 :             :    Handle the various additional information that print-rtl.cc can
    1220                 :             :    write after the regular fields, when parsing X.  */
    1221                 :             : 
    1222                 :             : void
    1223                 :        2029 : function_reader::handle_any_trailing_information (rtx x)
    1224                 :             : {
    1225                 :        2029 :   struct md_name name;
    1226                 :             : 
    1227                 :        2029 :   switch (GET_CODE (x))
    1228                 :             :     {
    1229                 :         161 :       case MEM:
    1230                 :         161 :         {
    1231                 :         161 :           int ch;
    1232                 :         161 :           require_char_ws ('[');
    1233                 :         161 :           read_name (&name);
    1234                 :         161 :           set_mem_alias_set (x, atoi (name.string));
    1235                 :             :           /* We have either a MEM_EXPR, or a space.  */
    1236                 :         161 :           if (peek_char () != ' ')
    1237                 :             :             {
    1238                 :         139 :               file_location loc = get_current_location ();
    1239                 :         139 :               char *desc = read_until (" +", false);
    1240                 :         139 :               add_fixup_expr (loc, consolidate_singletons (x), desc);
    1241                 :         139 :               free (desc);
    1242                 :             :             }
    1243                 :             :           else
    1244                 :          22 :             read_char ();
    1245                 :             : 
    1246                 :             :           /* We may optionally have '+' for MEM_OFFSET_KNOWN_P.  */
    1247                 :         161 :           ch = read_skip_spaces ();
    1248                 :         161 :           if (ch == '+')
    1249                 :             :             {
    1250                 :         134 :               read_name (&name);
    1251                 :         134 :               set_mem_offset (x, atoi (name.string));
    1252                 :             :             }
    1253                 :             :           else
    1254                 :          27 :             unread_char (ch);
    1255                 :             : 
    1256                 :             :           /* Handle optional " S" for MEM_SIZE.  */
    1257                 :         161 :           ch = read_skip_spaces ();
    1258                 :         161 :           if (ch == 'S')
    1259                 :             :             {
    1260                 :         141 :               read_name (&name);
    1261                 :         141 :               set_mem_size (x, atoi (name.string));
    1262                 :             :             }
    1263                 :             :           else
    1264                 :          20 :             unread_char (ch);
    1265                 :             : 
    1266                 :             :           /* Handle optional " A" for MEM_ALIGN.  */
    1267                 :         161 :           ch = read_skip_spaces ();
    1268                 :         161 :           if (ch == 'A' && peek_char () != 'S')
    1269                 :             :             {
    1270                 :         157 :               read_name (&name);
    1271                 :         157 :               set_mem_align (x, atoi (name.string));
    1272                 :             :             }
    1273                 :             :           else
    1274                 :           4 :             unread_char (ch);
    1275                 :             : 
    1276                 :             :           /* Handle optional " AS" for MEM_ADDR_SPACE.  */
    1277                 :         161 :           ch = read_skip_spaces ();
    1278                 :         161 :           if (ch == 'A' && peek_char () == 'S')
    1279                 :             :             {
    1280                 :           8 :               read_char ();
    1281                 :           8 :               read_name (&name);
    1282                 :           8 :               set_mem_addr_space (x, atoi (name.string));
    1283                 :             :             }
    1284                 :             :           else
    1285                 :         153 :             unread_char (ch);
    1286                 :             : 
    1287                 :         161 :           require_char (']');
    1288                 :             :         }
    1289                 :         161 :         break;
    1290                 :             : 
    1291                 :          64 :       case CODE_LABEL:
    1292                 :             :         /* Assume that LABEL_NUSES was not dumped.  */
    1293                 :             :         /* TODO: parse LABEL_KIND.  */
    1294                 :             :         /* For now, skip until closing ')'.  */
    1295                 :          64 :         do
    1296                 :             :           {
    1297                 :          64 :             char ch = read_char ();
    1298                 :          64 :             if (ch == ')')
    1299                 :             :               {
    1300                 :          28 :                 unread_char (ch);
    1301                 :          28 :                 break;
    1302                 :             :               }
    1303                 :             :           }
    1304                 :             :         while (1);
    1305                 :          28 :         break;
    1306                 :             : 
    1307                 :             :       default:
    1308                 :             :         break;
    1309                 :             :     }
    1310                 :        2029 : }
    1311                 :             : 
    1312                 :             : /* Parse a tree dump for a MEM_EXPR in DESC and turn it back into a tree.
    1313                 :             :    We handle "<retval>" and param names within cfun, but for anything else
    1314                 :             :    we "cheat" by building a global VAR_DECL of type "int" with that name
    1315                 :             :    (returning the same global for a name if we see the same name more
    1316                 :             :    than once).  */
    1317                 :             : 
    1318                 :             : tree
    1319                 :         289 : function_reader::parse_mem_expr (const char *desc)
    1320                 :             : {
    1321                 :         289 :   tree fndecl = cfun->decl;
    1322                 :             : 
    1323                 :         289 :   if (strcmp (desc, "<retval>") == 0)
    1324                 :          34 :     return DECL_RESULT (fndecl);
    1325                 :             : 
    1326                 :         255 :   tree param = find_param_by_name (fndecl, desc);
    1327                 :         255 :   if (param)
    1328                 :             :     return param;
    1329                 :             : 
    1330                 :             :   /* Search within decls we already created.
    1331                 :             :      FIXME: use a hash rather than linear search.  */
    1332                 :             :   int i;
    1333                 :             :   tree t;
    1334                 :         144 :   FOR_EACH_VEC_ELT (m_fake_scope, i, t)
    1335                 :          99 :     if (id_equal (DECL_NAME (t), desc))
    1336                 :             :       return t;
    1337                 :             : 
    1338                 :             :   /* Not found?  Create it.
    1339                 :             :      This allows mimicking of real data but avoids having to specify
    1340                 :             :      e.g. names of locals, params etc.
    1341                 :             :      Though this way we don't know if we have a PARM_DECL vs a VAR_DECL,
    1342                 :             :      and we don't know the types.  Fake it by making everything be
    1343                 :             :      a VAR_DECL of "int" type.  */
    1344                 :          45 :   t = build_decl (UNKNOWN_LOCATION, VAR_DECL,
    1345                 :             :                   get_identifier (desc),
    1346                 :             :                   integer_type_node);
    1347                 :          45 :   m_fake_scope.safe_push (t);
    1348                 :          45 :   return t;
    1349                 :             : }
    1350                 :             : 
    1351                 :             : /* Record that at LOC we saw an insn uid INSN_UID for the operand with index
    1352                 :             :    OPERAND_IDX within INSN, so that the pointer value can be fixed up in
    1353                 :             :    later post-processing.  */
    1354                 :             : 
    1355                 :             : void
    1356                 :          20 : function_reader::add_fixup_insn_uid (file_location loc, rtx insn, int operand_idx,
    1357                 :             :                                      int insn_uid)
    1358                 :             : {
    1359                 :          20 :   m_fixups.safe_push (new fixup_insn_uid (loc, insn, operand_idx, insn_uid));
    1360                 :          20 : }
    1361                 :             : 
    1362                 :             : /* Record that at LOC we saw an basic block index BB_IDX for the operand with index
    1363                 :             :    OPERAND_IDX within INSN, so that the pointer value can be fixed up in
    1364                 :             :    later post-processing.  */
    1365                 :             : 
    1366                 :             : void
    1367                 :          65 : function_reader::add_fixup_note_insn_basic_block (file_location loc, rtx insn,
    1368                 :             :                                                   int operand_idx, int bb_idx)
    1369                 :             : {
    1370                 :         195 :   m_fixups.safe_push (new fixup_note_insn_basic_block (loc, insn, operand_idx,
    1371                 :          65 :                                                        bb_idx));
    1372                 :          65 : }
    1373                 :             : 
    1374                 :             : /* Placeholder hook for recording source location information seen in a dump.
    1375                 :             :    This is empty for now.  */
    1376                 :             : 
    1377                 :             : void
    1378                 :         236 : function_reader::add_fixup_source_location (file_location, rtx_insn *,
    1379                 :             :                                             const char *, int, int)
    1380                 :             : {
    1381                 :         236 : }
    1382                 :             : 
    1383                 :             : /* Record that at LOC we saw textual description DESC of the MEM_EXPR or REG_EXPR
    1384                 :             :    of INSN, so that the fields can be fixed up in later post-processing.  */
    1385                 :             : 
    1386                 :             : void
    1387                 :         289 : function_reader::add_fixup_expr (file_location loc, rtx insn,
    1388                 :             :                                  const char *desc)
    1389                 :             : {
    1390                 :         289 :   gcc_assert (desc);
    1391                 :             :   /* Fail early if the RTL reader erroneously hands us an int.  */
    1392                 :         289 :   gcc_assert (!ISDIGIT (desc[0]));
    1393                 :             : 
    1394                 :         289 :   m_fixups.safe_push (new fixup_expr (loc, insn, desc));
    1395                 :         289 : }
    1396                 :             : 
    1397                 :             : /* Helper function for consolidate_reg.  Return the global rtx for
    1398                 :             :    the register with regno REGNO.  */
    1399                 :             : 
    1400                 :             : static rtx
    1401                 :        1106 : lookup_global_register (int regno)
    1402                 :             : {
    1403                 :             :   /* We can't use a switch here, as some of the REGNUMs might not be constants
    1404                 :             :      for some targets.  */
    1405                 :        1106 :   if (regno == STACK_POINTER_REGNUM)
    1406                 :           8 :       return stack_pointer_rtx;
    1407                 :             :   else if (regno ==  FRAME_POINTER_REGNUM)
    1408                 :         136 :     return frame_pointer_rtx;
    1409                 :             :   else if (regno == HARD_FRAME_POINTER_REGNUM)
    1410                 :          34 :     return hard_frame_pointer_rtx;
    1411                 :             :   else if (regno == ARG_POINTER_REGNUM)
    1412                 :           0 :     return arg_pointer_rtx;
    1413                 :             :   else if (regno == VIRTUAL_INCOMING_ARGS_REGNUM)
    1414                 :           0 :     return virtual_incoming_args_rtx;
    1415                 :             :   else if (regno == VIRTUAL_STACK_VARS_REGNUM)
    1416                 :          68 :     return virtual_stack_vars_rtx;
    1417                 :             :   else if (regno == VIRTUAL_STACK_DYNAMIC_REGNUM)
    1418                 :           0 :     return virtual_stack_dynamic_rtx;
    1419                 :             :   else if (regno == VIRTUAL_OUTGOING_ARGS_REGNUM)
    1420                 :           0 :     return virtual_outgoing_args_rtx;
    1421                 :             :   else if (regno == VIRTUAL_CFA_REGNUM)
    1422                 :           0 :     return virtual_cfa_rtx;
    1423                 :             :   else if (regno == VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM)
    1424                 :           0 :     return virtual_preferred_stack_boundary_rtx;
    1425                 :             : #ifdef return_ADDRESS_POINTER_REGNUM
    1426                 :             :   else if (regno == RETURN_ADDRESS_POINTER_REGNUM)
    1427                 :             :     return return_address_pointer_rtx;
    1428                 :             : #endif
    1429                 :             : 
    1430                 :             :   return NULL;
    1431                 :             : }
    1432                 :             : 
    1433                 :             : /* Ensure that the backend can cope with a REG with regno REGNO.
    1434                 :             :    Normally REG instances are created by gen_reg_rtx which updates
    1435                 :             :    regno_reg_rtx, growing it as necessary.
    1436                 :             :    The REG instances created from the dumpfile weren't created this
    1437                 :             :    way, so we need to manually update regno_reg_rtx.  */
    1438                 :             : 
    1439                 :             : static void
    1440                 :        1106 : ensure_regno (int regno)
    1441                 :             : {
    1442                 :        1106 :   if (reg_rtx_no < regno + 1)
    1443                 :          95 :     reg_rtx_no = regno + 1;
    1444                 :             : 
    1445                 :        1106 :   crtl->emit.ensure_regno_capacity ();
    1446                 :        1106 :   gcc_assert (regno < crtl->emit.regno_pointer_align_length);
    1447                 :        1106 : }
    1448                 :             : 
    1449                 :             : /* Helper function for consolidate_singletons, for handling REG instances.
    1450                 :             :    Given REG instance X of some regno, return the singleton rtx for that
    1451                 :             :    regno, if it exists, or X.  */
    1452                 :             : 
    1453                 :             : static rtx
    1454                 :        1106 : consolidate_reg (rtx x)
    1455                 :             : {
    1456                 :        1106 :   gcc_assert (GET_CODE (x) == REG);
    1457                 :             : 
    1458                 :        1106 :   unsigned int regno = REGNO (x);
    1459                 :             : 
    1460                 :        1106 :   ensure_regno (regno);
    1461                 :             : 
    1462                 :             :   /* Some register numbers have their rtx created in init_emit_regs
    1463                 :             :      e.g. stack_pointer_rtx for STACK_POINTER_REGNUM.
    1464                 :             :      Consolidate on this.  */
    1465                 :        1106 :   rtx global_reg = lookup_global_register (regno);
    1466                 :        1106 :   if (global_reg)
    1467                 :             :     return global_reg;
    1468                 :             : 
    1469                 :             :   /* Populate regno_reg_rtx if necessary.  */
    1470                 :         860 :   if (regno_reg_rtx[regno] == NULL)
    1471                 :         142 :     regno_reg_rtx[regno] = x;
    1472                 :             :   /* Use it.  */
    1473                 :         860 :   gcc_assert (GET_CODE (regno_reg_rtx[regno]) == REG);
    1474                 :         860 :   gcc_assert (REGNO (regno_reg_rtx[regno]) == regno);
    1475                 :         860 :   if (GET_MODE (x) == GET_MODE (regno_reg_rtx[regno]))
    1476                 :         546 :     return regno_reg_rtx[regno];
    1477                 :             : 
    1478                 :             :   return x;
    1479                 :             : }
    1480                 :             : 
    1481                 :             : /* When reading RTL function dumps, we must consolidate some
    1482                 :             :    rtx so that we use singletons where singletons are expected
    1483                 :             :    (e.g. we don't want multiple "(const_int 0 [0])" rtx, since
    1484                 :             :    these are tested via pointer equality against const0_rtx.
    1485                 :             : 
    1486                 :             :    Return the equivalent singleton rtx for X, if any, otherwise X.  */
    1487                 :             : 
    1488                 :             : rtx
    1489                 :        2412 : function_reader::consolidate_singletons (rtx x)
    1490                 :             : {
    1491                 :        2412 :   if (!x)
    1492                 :             :     return x;
    1493                 :             : 
    1494                 :        2306 :   switch (GET_CODE (x))
    1495                 :             :     {
    1496                 :          28 :     case PC: return pc_rtx;
    1497                 :           4 :     case RETURN: return ret_rtx;
    1498                 :           5 :     case SIMPLE_RETURN: return simple_return_rtx;
    1499                 :             : 
    1500                 :        1106 :     case REG:
    1501                 :        1106 :       return consolidate_reg (x);
    1502                 :             : 
    1503                 :         212 :     case CONST_INT:
    1504                 :         212 :       return gen_rtx_CONST_INT (GET_MODE (x), INTVAL (x));
    1505                 :             : 
    1506                 :           1 :     case CONST_VECTOR:
    1507                 :           1 :       return gen_rtx_CONST_VECTOR (GET_MODE (x), XVEC (x, 0));
    1508                 :             : 
    1509                 :             :     default:
    1510                 :             :       break;
    1511                 :             :     }
    1512                 :             : 
    1513                 :             :   return x;
    1514                 :             : }
    1515                 :             : 
    1516                 :             : /* Parse an rtx directive, including both the opening/closing parentheses,
    1517                 :             :    and the name.  */
    1518                 :             : 
    1519                 :             : rtx
    1520                 :          65 : function_reader::parse_rtx ()
    1521                 :             : {
    1522                 :          65 :   require_char_ws ('(');
    1523                 :          65 :   struct md_name directive;
    1524                 :          65 :   read_name (&directive);
    1525                 :          65 :   rtx result
    1526                 :          65 :     = consolidate_singletons (read_rtx_code (directive.string));
    1527                 :          65 :   require_char_ws (')');
    1528                 :             : 
    1529                 :          65 :   return result;
    1530                 :             : }
    1531                 :             : 
    1532                 :             : /* Implementation of rtx_reader::postprocess for reading function dumps.
    1533                 :             :    Return the equivalent singleton rtx for X, if any, otherwise X.  */
    1534                 :             : 
    1535                 :             : rtx
    1536                 :        1655 : function_reader::postprocess (rtx x)
    1537                 :             : {
    1538                 :        1655 :   return consolidate_singletons (x);
    1539                 :             : }
    1540                 :             : 
    1541                 :             : /* Implementation of rtx_reader::finalize_string for reading function dumps.
    1542                 :             :    Make a GC-managed copy of STRINGBUF.  */
    1543                 :             : 
    1544                 :             : const char *
    1545                 :          18 : function_reader::finalize_string (char *stringbuf)
    1546                 :             : {
    1547                 :          18 :   return ggc_strdup (stringbuf);
    1548                 :             : }
    1549                 :             : 
    1550                 :             : /* Attempt to parse optional location information for insn INSN, as
    1551                 :             :    potentially written out by rtx_writer::print_rtx_operand_code_i.
    1552                 :             :    We look for a quoted string followed by a colon.  */
    1553                 :             : 
    1554                 :             : void
    1555                 :         270 : function_reader::maybe_read_location (rtx_insn *insn)
    1556                 :             : {
    1557                 :         270 :   file_location loc = get_current_location ();
    1558                 :             : 
    1559                 :             :   /* Attempt to parse a quoted string.  */
    1560                 :         270 :   int ch = read_skip_spaces ();
    1561                 :         270 :   if (ch == '"')
    1562                 :             :     {
    1563                 :         236 :       char *filename = read_quoted_string ();
    1564                 :         236 :       require_char (':');
    1565                 :         236 :       struct md_name line_num;
    1566                 :         236 :       read_name (&line_num);
    1567                 :             : 
    1568                 :         236 :       int column = 0;
    1569                 :         236 :       int ch = read_char ();
    1570                 :         236 :       if (ch == ':')
    1571                 :             :         {
    1572                 :           0 :           struct md_name column_num;
    1573                 :           0 :           read_name (&column_num);
    1574                 :           0 :           column = atoi (column_num.string);
    1575                 :             :         }
    1576                 :             :       else
    1577                 :         236 :         unread_char (ch);
    1578                 :         236 :       add_fixup_source_location (loc, insn, filename,
    1579                 :         236 :                                  atoi (line_num.string),
    1580                 :             :                                  column);
    1581                 :             :     }
    1582                 :             :   else
    1583                 :          34 :     unread_char (ch);
    1584                 :         270 : }
    1585                 :             : 
    1586                 :             : /* Postprocessing subroutine of function_reader::parse_function.
    1587                 :             :    Populate m_insns_by_uid.  */
    1588                 :             : 
    1589                 :             : void
    1590                 :          93 : function_reader::handle_insn_uids ()
    1591                 :             : {
    1592                 :             :   /* Locate the currently assigned INSN_UID values, storing
    1593                 :             :      them in m_insns_by_uid.  */
    1594                 :          93 :   int max_uid = 0;
    1595                 :         518 :   for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
    1596                 :             :     {
    1597                 :         425 :       if (m_insns_by_uid.get (INSN_UID (insn)))
    1598                 :           0 :         error ("duplicate insn UID: %i", INSN_UID (insn));
    1599                 :         425 :       m_insns_by_uid.put (INSN_UID (insn), insn);
    1600                 :         425 :       if (INSN_UID (insn) > max_uid)
    1601                 :             :         max_uid = INSN_UID (insn);
    1602                 :             :     }
    1603                 :             : 
    1604                 :             :   /* Ensure x_cur_insn_uid is 1 more than the biggest insn UID seen.
    1605                 :             :      This is normally updated by the various make_*insn_raw functions.  */
    1606                 :          93 :   crtl->emit.x_cur_insn_uid = max_uid + 1;
    1607                 :          93 : }
    1608                 :             : 
    1609                 :             : /* Apply all of the recorded fixups.  */
    1610                 :             : 
    1611                 :             : void
    1612                 :          93 : function_reader::apply_fixups ()
    1613                 :             : {
    1614                 :          93 :   int i;
    1615                 :          93 :   fixup *f;
    1616                 :         467 :   FOR_EACH_VEC_ELT (m_fixups, i, f)
    1617                 :         374 :     f->apply (this);
    1618                 :          93 : }
    1619                 :             : 
    1620                 :             : /* Given a UID value, try to locate a pointer to the corresponding
    1621                 :             :    rtx_insn *, or NULL if it can't be found.  */
    1622                 :             : 
    1623                 :             : rtx_insn **
    1624                 :          20 : function_reader::get_insn_by_uid (int uid)
    1625                 :             : {
    1626                 :          20 :   return m_insns_by_uid.get (uid);
    1627                 :             : }
    1628                 :             : 
    1629                 :             : /* Run the RTL dump parser, parsing a dump located at PATH.
    1630                 :             :    Return true iff the file was successfully parsed.  */
    1631                 :             : 
    1632                 :             : bool
    1633                 :          76 : read_rtl_function_body (const char *path)
    1634                 :             : {
    1635                 :          76 :   initialize_rtl ();
    1636                 :          76 :   crtl->abi = &default_function_abi;
    1637                 :          76 :   init_emit ();
    1638                 :          76 :   init_varasm_status ();
    1639                 :             : 
    1640                 :          76 :   function_reader reader;
    1641                 :          76 :   if (!reader.read_file (path))
    1642                 :             :     return false;
    1643                 :             : 
    1644                 :             :   return true;
    1645                 :          76 : }
    1646                 :             : 
    1647                 :             : /* Run the RTL dump parser on the range of lines between START_LOC and
    1648                 :             :    END_LOC (including those lines).  */
    1649                 :             : 
    1650                 :             : bool
    1651                 :          18 : read_rtl_function_body_from_file_range (location_t start_loc,
    1652                 :             :                                         location_t end_loc)
    1653                 :             : {
    1654                 :          18 :   expanded_location exploc_start = expand_location (start_loc);
    1655                 :          18 :   expanded_location exploc_end = expand_location (end_loc);
    1656                 :             : 
    1657                 :          18 :   if (exploc_start.file != exploc_end.file)
    1658                 :             :     {
    1659                 :           0 :       error_at (end_loc, "start/end of RTL fragment are in different files");
    1660                 :           0 :       return false;
    1661                 :             :     }
    1662                 :          18 :   if (exploc_start.line >= exploc_end.line)
    1663                 :             :     {
    1664                 :           0 :       error_at (end_loc,
    1665                 :             :                 "start of RTL fragment must be on an earlier line than end");
    1666                 :           0 :       return false;
    1667                 :             :     }
    1668                 :             : 
    1669                 :          18 :   initialize_rtl ();
    1670                 :          18 :   crtl->abi = &fndecl_abi (cfun->decl).base_abi ();
    1671                 :          18 :   init_emit ();
    1672                 :          18 :   init_varasm_status ();
    1673                 :             : 
    1674                 :          18 :   function_reader reader;
    1675                 :          18 :   if (!reader.read_file_fragment (exploc_start.file, exploc_start.line,
    1676                 :             :                                   exploc_end.line - 1))
    1677                 :             :     return false;
    1678                 :             : 
    1679                 :             :   return true;
    1680                 :          17 : }
    1681                 :             : 
    1682                 :             : #if CHECKING_P
    1683                 :             : 
    1684                 :             : namespace selftest {
    1685                 :             : 
    1686                 :             : /* Verify that parse_edge_flags works.  */
    1687                 :             : 
    1688                 :             : static void
    1689                 :           4 : test_edge_flags ()
    1690                 :             : {
    1691                 :             :   /* parse_edge_flags modifies its input (due to strtok), so we must make
    1692                 :             :      a copy of the literals.  */
    1693                 :             : #define ASSERT_PARSE_EDGE_FLAGS(EXPECTED, STR) \
    1694                 :             :   do { \
    1695                 :             :     char *str = xstrdup (STR); \
    1696                 :             :     ASSERT_EQ (EXPECTED, parse_edge_flags (str)); \
    1697                 :             :     free (str); \
    1698                 :             :   } while (0)
    1699                 :             : 
    1700                 :           4 :   ASSERT_PARSE_EDGE_FLAGS (0, "");
    1701                 :           4 :   ASSERT_PARSE_EDGE_FLAGS (EDGE_FALLTHRU, "FALLTHRU");
    1702                 :           4 :   ASSERT_PARSE_EDGE_FLAGS (EDGE_ABNORMAL_CALL, "ABNORMAL_CALL");
    1703                 :           4 :   ASSERT_PARSE_EDGE_FLAGS (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL,
    1704                 :             :                            "ABNORMAL | ABNORMAL_CALL");
    1705                 :             : 
    1706                 :             : #undef  ASSERT_PARSE_EDGE_FLAGS
    1707                 :           4 : }
    1708                 :             : 
    1709                 :             : /* Verify that lookup_reg_by_dump_name works.  */
    1710                 :             : 
    1711                 :             : static void
    1712                 :           4 : test_parsing_regnos ()
    1713                 :             : {
    1714                 :           4 :   ASSERT_EQ (-1, lookup_reg_by_dump_name ("this is not a register"));
    1715                 :             : 
    1716                 :             :   /* Verify lookup of virtual registers.  */
    1717                 :           4 :   ASSERT_EQ (VIRTUAL_INCOMING_ARGS_REGNUM,
    1718                 :             :     lookup_reg_by_dump_name ("virtual-incoming-args"));
    1719                 :           4 :   ASSERT_EQ (VIRTUAL_STACK_VARS_REGNUM,
    1720                 :             :     lookup_reg_by_dump_name ("virtual-stack-vars"));
    1721                 :           4 :   ASSERT_EQ (VIRTUAL_STACK_DYNAMIC_REGNUM,
    1722                 :             :     lookup_reg_by_dump_name ("virtual-stack-dynamic"));
    1723                 :           4 :   ASSERT_EQ (VIRTUAL_OUTGOING_ARGS_REGNUM,
    1724                 :             :     lookup_reg_by_dump_name ("virtual-outgoing-args"));
    1725                 :           4 :   ASSERT_EQ (VIRTUAL_CFA_REGNUM,
    1726                 :             :     lookup_reg_by_dump_name ("virtual-cfa"));
    1727                 :           4 :   ASSERT_EQ (VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM,
    1728                 :             :     lookup_reg_by_dump_name ("virtual-preferred-stack-boundary"));
    1729                 :             : 
    1730                 :             :   /* Verify lookup of non-virtual pseudos.  */
    1731                 :           4 :   ASSERT_EQ (LAST_VIRTUAL_REGISTER + 1, lookup_reg_by_dump_name ("<0>"));
    1732                 :           4 :   ASSERT_EQ (LAST_VIRTUAL_REGISTER + 2, lookup_reg_by_dump_name ("<1>"));
    1733                 :           4 : }
    1734                 :             : 
    1735                 :             : /* Verify that edge E is as expected, with the src and dest basic blocks
    1736                 :             :    having indices EXPECTED_SRC_IDX and EXPECTED_DEST_IDX respectively, and
    1737                 :             :    the edge having flags equal to EXPECTED_FLAGS.
    1738                 :             :    Use LOC as the effective location when reporting failures.  */
    1739                 :             : 
    1740                 :             : static void
    1741                 :          72 : assert_edge_at (const location &loc, edge e, int expected_src_idx,
    1742                 :             :                 int expected_dest_idx, int expected_flags)
    1743                 :             : {
    1744                 :          72 :   ASSERT_EQ_AT (loc, expected_src_idx, e->src->index);
    1745                 :          72 :   ASSERT_EQ_AT (loc, expected_dest_idx, e->dest->index);
    1746                 :          72 :   ASSERT_EQ_AT (loc, expected_flags, e->flags);
    1747                 :          72 : }
    1748                 :             : 
    1749                 :             : /* Verify that edge EDGE is as expected, with the src and dest basic blocks
    1750                 :             :    having indices EXPECTED_SRC_IDX and EXPECTED_DEST_IDX respectively, and
    1751                 :             :    the edge having flags equal to EXPECTED_FLAGS.  */
    1752                 :             : 
    1753                 :             : #define ASSERT_EDGE(EDGE, EXPECTED_SRC_IDX, EXPECTED_DEST_IDX,          \
    1754                 :             :                     EXPECTED_FLAGS)                                     \
    1755                 :             :   assert_edge_at (SELFTEST_LOCATION, EDGE, EXPECTED_SRC_IDX, \
    1756                 :             :                   EXPECTED_DEST_IDX, EXPECTED_FLAGS)
    1757                 :             : 
    1758                 :             : /* Verify that we can load RTL dumps.  */
    1759                 :             : 
    1760                 :             : static void
    1761                 :           4 : test_loading_dump_fragment_1 ()
    1762                 :             : {
    1763                 :             :   // TODO: filter on target?
    1764                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("asr_div1.rtl"));
    1765                 :             : 
    1766                 :             :   /* Verify that the insns were loaded correctly.  */
    1767                 :           4 :   rtx_insn *insn_1 = get_insns ();
    1768                 :           4 :   ASSERT_TRUE (insn_1);
    1769                 :           4 :   ASSERT_EQ (1, INSN_UID (insn_1));
    1770                 :           4 :   ASSERT_EQ (INSN, GET_CODE (insn_1));
    1771                 :           4 :   ASSERT_EQ (SET, GET_CODE (PATTERN (insn_1)));
    1772                 :           4 :   ASSERT_EQ (NULL, PREV_INSN (insn_1));
    1773                 :             : 
    1774                 :           4 :   rtx_insn *insn_2 = NEXT_INSN (insn_1);
    1775                 :           4 :   ASSERT_TRUE (insn_2);
    1776                 :           4 :   ASSERT_EQ (2, INSN_UID (insn_2));
    1777                 :           4 :   ASSERT_EQ (INSN, GET_CODE (insn_2));
    1778                 :           4 :   ASSERT_EQ (insn_1, PREV_INSN (insn_2));
    1779                 :           4 :   ASSERT_EQ (NULL, NEXT_INSN (insn_2));
    1780                 :             : 
    1781                 :             :   /* Verify that registers were loaded correctly.  */
    1782                 :           4 :   rtx insn_1_dest = SET_DEST (PATTERN (insn_1));
    1783                 :           4 :   ASSERT_EQ (REG, GET_CODE (insn_1_dest));
    1784                 :           4 :   ASSERT_EQ ((LAST_VIRTUAL_REGISTER + 1) + 2, REGNO (insn_1_dest));
    1785                 :           4 :   rtx insn_1_src = SET_SRC (PATTERN (insn_1));
    1786                 :           4 :   ASSERT_EQ (LSHIFTRT, GET_CODE (insn_1_src));
    1787                 :           4 :   rtx reg = XEXP (insn_1_src, 0);
    1788                 :           4 :   ASSERT_EQ (REG, GET_CODE (reg));
    1789                 :           4 :   ASSERT_EQ (LAST_VIRTUAL_REGISTER + 1, REGNO (reg));
    1790                 :             : 
    1791                 :             :   /* Verify that get_insn_by_uid works.  */
    1792                 :           4 :   ASSERT_EQ (insn_1, get_insn_by_uid (1));
    1793                 :           4 :   ASSERT_EQ (insn_2, get_insn_by_uid (2));
    1794                 :             : 
    1795                 :             :   /* Verify that basic blocks were created.  */
    1796                 :           4 :   ASSERT_EQ (2, BLOCK_FOR_INSN (insn_1)->index);
    1797                 :           4 :   ASSERT_EQ (2, BLOCK_FOR_INSN (insn_2)->index);
    1798                 :             : 
    1799                 :             :   /* Verify that the CFG was recreated.  */
    1800                 :           4 :   ASSERT_TRUE (cfun);
    1801                 :           4 :   verify_three_block_rtl_cfg (cfun);
    1802                 :           4 :   basic_block bb2 = BASIC_BLOCK_FOR_FN (cfun, 2);
    1803                 :           4 :   ASSERT_TRUE (bb2 != NULL);
    1804                 :           4 :   ASSERT_EQ (BB_RTL, bb2->flags & BB_RTL);
    1805                 :           4 :   ASSERT_EQ (2, bb2->index);
    1806                 :           4 :   ASSERT_EQ (insn_1, BB_HEAD (bb2));
    1807                 :           4 :   ASSERT_EQ (insn_2, BB_END (bb2));
    1808                 :           4 : }
    1809                 :             : 
    1810                 :             : /* Verify loading another RTL dump.  */
    1811                 :             : 
    1812                 :             : static void
    1813                 :           4 : test_loading_dump_fragment_2 ()
    1814                 :             : {
    1815                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("simple-cse.rtl"));
    1816                 :             : 
    1817                 :           4 :   rtx_insn *insn_1 = get_insn_by_uid (1);
    1818                 :           4 :   rtx_insn *insn_2 = get_insn_by_uid (2);
    1819                 :           4 :   rtx_insn *insn_3 = get_insn_by_uid (3);
    1820                 :             : 
    1821                 :           4 :   rtx set1 = single_set (insn_1);
    1822                 :           4 :   ASSERT_NE (NULL, set1);
    1823                 :           4 :   rtx set2 = single_set (insn_2);
    1824                 :           4 :   ASSERT_NE (NULL, set2);
    1825                 :           4 :   rtx set3 = single_set (insn_3);
    1826                 :           4 :   ASSERT_NE (NULL, set3);
    1827                 :             : 
    1828                 :           4 :   rtx src1 = SET_SRC (set1);
    1829                 :           4 :   ASSERT_EQ (PLUS, GET_CODE (src1));
    1830                 :             : 
    1831                 :           4 :   rtx src2 = SET_SRC (set2);
    1832                 :           4 :   ASSERT_EQ (PLUS, GET_CODE (src2));
    1833                 :             : 
    1834                 :             :   /* Both src1 and src2 refer to "(reg:SI %0)".
    1835                 :             :      Verify that we have pointer equality.  */
    1836                 :           4 :   rtx lhs1 = XEXP (src1, 0);
    1837                 :           4 :   rtx lhs2 = XEXP (src2, 0);
    1838                 :           4 :   ASSERT_EQ (lhs1, lhs2);
    1839                 :             : 
    1840                 :             :   /* Verify that the CFG was recreated. */
    1841                 :           4 :   ASSERT_TRUE (cfun);
    1842                 :           4 :   verify_three_block_rtl_cfg (cfun);
    1843                 :           4 : }
    1844                 :             : 
    1845                 :             : /* Verify that CODE_LABEL insns are loaded correctly.  */
    1846                 :             : 
    1847                 :             : static void
    1848                 :           4 : test_loading_labels ()
    1849                 :             : {
    1850                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("example-labels.rtl"));
    1851                 :             : 
    1852                 :           4 :   rtx_insn *insn_100 = get_insn_by_uid (100);
    1853                 :           4 :   ASSERT_EQ (CODE_LABEL, GET_CODE (insn_100));
    1854                 :           4 :   ASSERT_EQ (100, INSN_UID (insn_100));
    1855                 :           4 :   ASSERT_EQ (NULL, LABEL_NAME (insn_100));
    1856                 :           4 :   ASSERT_EQ (0, LABEL_NUSES (insn_100));
    1857                 :           4 :   ASSERT_EQ (30, CODE_LABEL_NUMBER (insn_100));
    1858                 :             : 
    1859                 :           4 :   rtx_insn *insn_200 = get_insn_by_uid (200);
    1860                 :           4 :   ASSERT_EQ (CODE_LABEL, GET_CODE (insn_200));
    1861                 :           4 :   ASSERT_EQ (200, INSN_UID (insn_200));
    1862                 :           4 :   ASSERT_STREQ ("some_label_name", LABEL_NAME (insn_200));
    1863                 :           4 :   ASSERT_EQ (0, LABEL_NUSES (insn_200));
    1864                 :           4 :   ASSERT_EQ (40, CODE_LABEL_NUMBER (insn_200));
    1865                 :             : 
    1866                 :             :   /* Ensure that the presence of CODE_LABEL_NUMBER == 40
    1867                 :             :      means that the next label num to be handed out will be 41.  */
    1868                 :           4 :   ASSERT_EQ (41, max_label_num ());
    1869                 :             : 
    1870                 :             :   /* Ensure that label names read from a dump are GC-managed
    1871                 :             :      and are found through the insn.  */
    1872                 :           4 :   ggc_collect (GGC_COLLECT_FORCE);
    1873                 :           4 :   ASSERT_TRUE (ggc_marked_p (insn_200));
    1874                 :           4 :   ASSERT_TRUE (ggc_marked_p (LABEL_NAME (insn_200)));
    1875                 :           4 : }
    1876                 :             : 
    1877                 :             : /* Verify that the loader copes with an insn with a mode.  */
    1878                 :             : 
    1879                 :             : static void
    1880                 :           4 : test_loading_insn_with_mode ()
    1881                 :             : {
    1882                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("insn-with-mode.rtl"));
    1883                 :           4 :   rtx_insn *insn = get_insns ();
    1884                 :           4 :   ASSERT_EQ (INSN, GET_CODE (insn));
    1885                 :             : 
    1886                 :             :   /* Verify that the "TI" mode was set from "insn:TI".  */
    1887                 :           4 :   ASSERT_EQ (TImode, GET_MODE (insn));
    1888                 :           4 : }
    1889                 :             : 
    1890                 :             : /* Verify that the loader copes with a jump_insn to a label_ref.  */
    1891                 :             : 
    1892                 :             : static void
    1893                 :           4 : test_loading_jump_to_label_ref ()
    1894                 :             : {
    1895                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("jump-to-label-ref.rtl"));
    1896                 :             : 
    1897                 :           4 :   rtx_insn *jump_insn = get_insn_by_uid (1);
    1898                 :           4 :   ASSERT_EQ (JUMP_INSN, GET_CODE (jump_insn));
    1899                 :             : 
    1900                 :           4 :   rtx_insn *barrier = get_insn_by_uid (2);
    1901                 :           4 :   ASSERT_EQ (BARRIER, GET_CODE (barrier));
    1902                 :             : 
    1903                 :           4 :   rtx_insn *code_label = get_insn_by_uid (100);
    1904                 :           4 :   ASSERT_EQ (CODE_LABEL, GET_CODE (code_label));
    1905                 :             : 
    1906                 :             :   /* Verify the jump_insn. */
    1907                 :           4 :   ASSERT_EQ (4, BLOCK_FOR_INSN (jump_insn)->index);
    1908                 :           4 :   ASSERT_EQ (SET, GET_CODE (PATTERN (jump_insn)));
    1909                 :             :   /* Ensure that the "(pc)" is using the global singleton.  */
    1910                 :           4 :   ASSERT_RTX_PTR_EQ (pc_rtx, SET_DEST (PATTERN (jump_insn)));
    1911                 :           4 :   rtx label_ref = SET_SRC (PATTERN (jump_insn));
    1912                 :           4 :   ASSERT_EQ (LABEL_REF, GET_CODE (label_ref));
    1913                 :           4 :   ASSERT_EQ (code_label, label_ref_label (label_ref));
    1914                 :           4 :   ASSERT_EQ (code_label, JUMP_LABEL (jump_insn));
    1915                 :             : 
    1916                 :             :   /* Verify the code_label. */
    1917                 :           4 :   ASSERT_EQ (5, BLOCK_FOR_INSN (code_label)->index);
    1918                 :           4 :   ASSERT_EQ (NULL, LABEL_NAME (code_label));
    1919                 :           4 :   ASSERT_EQ (1, LABEL_NUSES (code_label));
    1920                 :             : 
    1921                 :             :   /* Verify the generated CFG.  */
    1922                 :             : 
    1923                 :             :   /* Locate blocks.  */
    1924                 :           4 :   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
    1925                 :           4 :   ASSERT_TRUE (entry != NULL);
    1926                 :           4 :   ASSERT_EQ (ENTRY_BLOCK, entry->index);
    1927                 :             : 
    1928                 :           4 :   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (cfun);
    1929                 :           4 :   ASSERT_TRUE (exit != NULL);
    1930                 :           4 :   ASSERT_EQ (EXIT_BLOCK, exit->index);
    1931                 :             : 
    1932                 :           4 :   basic_block bb4 = (*cfun->cfg->x_basic_block_info)[4];
    1933                 :           4 :   basic_block bb5 = (*cfun->cfg->x_basic_block_info)[5];
    1934                 :           4 :   ASSERT_EQ (4, bb4->index);
    1935                 :           4 :   ASSERT_EQ (5, bb5->index);
    1936                 :             : 
    1937                 :             :   /* Entry block.  */
    1938                 :           4 :   ASSERT_EQ (NULL, entry->preds);
    1939                 :           4 :   ASSERT_EQ (1, entry->succs->length ());
    1940                 :           4 :   ASSERT_EDGE ((*entry->succs)[0], 0, 4, EDGE_FALLTHRU);
    1941                 :             : 
    1942                 :             :   /* bb4.  */
    1943                 :           4 :   ASSERT_EQ (1, bb4->preds->length ());
    1944                 :           4 :   ASSERT_EDGE ((*bb4->preds)[0], 0, 4, EDGE_FALLTHRU);
    1945                 :           4 :   ASSERT_EQ (1, bb4->succs->length ());
    1946                 :           4 :   ASSERT_EDGE ((*bb4->succs)[0], 4, 5, 0x0);
    1947                 :             : 
    1948                 :             :   /* bb5.  */
    1949                 :           4 :   ASSERT_EQ (1, bb5->preds->length ());
    1950                 :           4 :   ASSERT_EDGE ((*bb5->preds)[0], 4, 5, 0x0);
    1951                 :           4 :   ASSERT_EQ (1, bb5->succs->length ());
    1952                 :           4 :   ASSERT_EDGE ((*bb5->succs)[0], 5, 1, EDGE_FALLTHRU);
    1953                 :             : 
    1954                 :             :   /* Exit block.  */
    1955                 :           4 :   ASSERT_EQ (1, exit->preds->length ());
    1956                 :           4 :   ASSERT_EDGE ((*exit->preds)[0], 5, 1, EDGE_FALLTHRU);
    1957                 :           4 :   ASSERT_EQ (NULL, exit->succs);
    1958                 :           4 : }
    1959                 :             : 
    1960                 :             : /* Verify that the loader copes with a jump_insn to a label_ref
    1961                 :             :    marked "return".  */
    1962                 :             : 
    1963                 :             : static void
    1964                 :           4 : test_loading_jump_to_return ()
    1965                 :             : {
    1966                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("jump-to-return.rtl"));
    1967                 :             : 
    1968                 :           4 :   rtx_insn *jump_insn = get_insn_by_uid (1);
    1969                 :           4 :   ASSERT_EQ (JUMP_INSN, GET_CODE (jump_insn));
    1970                 :           4 :   ASSERT_RTX_PTR_EQ (ret_rtx, JUMP_LABEL (jump_insn));
    1971                 :           4 : }
    1972                 :             : 
    1973                 :             : /* Verify that the loader copes with a jump_insn to a label_ref
    1974                 :             :    marked "simple_return".  */
    1975                 :             : 
    1976                 :             : static void
    1977                 :           4 : test_loading_jump_to_simple_return ()
    1978                 :             : {
    1979                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION,
    1980                 :           4 :                    locate_file ("jump-to-simple-return.rtl"));
    1981                 :             : 
    1982                 :           4 :   rtx_insn *jump_insn = get_insn_by_uid (1);
    1983                 :           4 :   ASSERT_EQ (JUMP_INSN, GET_CODE (jump_insn));
    1984                 :           4 :   ASSERT_RTX_PTR_EQ (simple_return_rtx, JUMP_LABEL (jump_insn));
    1985                 :           4 : }
    1986                 :             : 
    1987                 :             : /* Verify that the loader copes with a NOTE_INSN_BASIC_BLOCK.  */
    1988                 :             : 
    1989                 :             : static void
    1990                 :           4 : test_loading_note_insn_basic_block ()
    1991                 :             : {
    1992                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION,
    1993                 :           4 :                    locate_file ("note_insn_basic_block.rtl"));
    1994                 :             : 
    1995                 :           4 :   rtx_insn *note = get_insn_by_uid (1);
    1996                 :           4 :   ASSERT_EQ (NOTE, GET_CODE (note));
    1997                 :           4 :   ASSERT_EQ (2, BLOCK_FOR_INSN (note)->index);
    1998                 :             : 
    1999                 :           4 :   ASSERT_EQ (NOTE_INSN_BASIC_BLOCK, NOTE_KIND (note));
    2000                 :           4 :   ASSERT_EQ (2, NOTE_BASIC_BLOCK (note)->index);
    2001                 :           4 :   ASSERT_EQ (BASIC_BLOCK_FOR_FN (cfun, 2), NOTE_BASIC_BLOCK (note));
    2002                 :           4 : }
    2003                 :             : 
    2004                 :             : /* Verify that the loader copes with a NOTE_INSN_DELETED.  */
    2005                 :             : 
    2006                 :             : static void
    2007                 :           4 : test_loading_note_insn_deleted ()
    2008                 :             : {
    2009                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("note-insn-deleted.rtl"));
    2010                 :             : 
    2011                 :           4 :   rtx_insn *note = get_insn_by_uid (1);
    2012                 :           4 :   ASSERT_EQ (NOTE, GET_CODE (note));
    2013                 :           4 :   ASSERT_EQ (NOTE_INSN_DELETED, NOTE_KIND (note));
    2014                 :           4 : }
    2015                 :             : 
    2016                 :             : /* Verify that the const_int values are consolidated, since
    2017                 :             :    pointer equality corresponds to value equality.
    2018                 :             :    TODO: do this for all in CASE_CONST_UNIQUE.  */
    2019                 :             : 
    2020                 :             : static void
    2021                 :           4 : test_loading_const_int ()
    2022                 :             : {
    2023                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("const-int.rtl"));
    2024                 :             : 
    2025                 :             :   /* Verify that const_int values below MAX_SAVED_CONST_INT use
    2026                 :             :      the global values.  */
    2027                 :           4 :   ASSERT_EQ (const0_rtx, SET_SRC (PATTERN (get_insn_by_uid (1))));
    2028                 :           4 :   ASSERT_EQ (const1_rtx, SET_SRC (PATTERN (get_insn_by_uid (2))));
    2029                 :           4 :   ASSERT_EQ (constm1_rtx, SET_SRC (PATTERN (get_insn_by_uid (3))));
    2030                 :             : 
    2031                 :             :   /* Verify that other const_int values are consolidated. */
    2032                 :           4 :   rtx int256 = gen_rtx_CONST_INT (SImode, 256);
    2033                 :           4 :   ASSERT_EQ (int256, SET_SRC (PATTERN (get_insn_by_uid (4))));
    2034                 :           4 : }
    2035                 :             : 
    2036                 :             : /* Verify that the loader copes with a SYMBOL_REF.  */
    2037                 :             : 
    2038                 :             : static void
    2039                 :           4 : test_loading_symbol_ref ()
    2040                 :             : {
    2041                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("symbol-ref.rtl"));
    2042                 :             : 
    2043                 :           4 :   rtx_insn *insn = get_insns ();
    2044                 :             : 
    2045                 :           4 :   rtx high = SET_SRC (PATTERN (insn));
    2046                 :           4 :   ASSERT_EQ (HIGH, GET_CODE (high));
    2047                 :             : 
    2048                 :           4 :   rtx symbol_ref = XEXP (high, 0);
    2049                 :           4 :   ASSERT_EQ (SYMBOL_REF, GET_CODE (symbol_ref));
    2050                 :             : 
    2051                 :             :   /* Verify that "[flags 0xc0]" was parsed.  */
    2052                 :           4 :   ASSERT_EQ (0xc0, SYMBOL_REF_FLAGS (symbol_ref));
    2053                 :             :   /* TODO: we don't yet load SYMBOL_REF_DECL.  */
    2054                 :           4 : }
    2055                 :             : 
    2056                 :             : /* Verify that the loader can rebuild a CFG.  */
    2057                 :             : 
    2058                 :             : static void
    2059                 :           4 : test_loading_cfg ()
    2060                 :             : {
    2061                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("cfg-test.rtl"));
    2062                 :             : 
    2063                 :           4 :   ASSERT_STREQ ("cfg_test", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
    2064                 :             : 
    2065                 :           4 :   ASSERT_TRUE (cfun);
    2066                 :             : 
    2067                 :           4 :   ASSERT_TRUE (cfun->cfg != NULL);
    2068                 :           4 :   ASSERT_EQ (6, n_basic_blocks_for_fn (cfun));
    2069                 :           4 :   ASSERT_EQ (6, n_edges_for_fn (cfun));
    2070                 :             : 
    2071                 :             :   /* The "fake" basic blocks.  */
    2072                 :           4 :   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
    2073                 :           4 :   ASSERT_TRUE (entry != NULL);
    2074                 :           4 :   ASSERT_EQ (ENTRY_BLOCK, entry->index);
    2075                 :             : 
    2076                 :           4 :   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (cfun);
    2077                 :           4 :   ASSERT_TRUE (exit != NULL);
    2078                 :           4 :   ASSERT_EQ (EXIT_BLOCK, exit->index);
    2079                 :             : 
    2080                 :             :   /* The "real" basic blocks.  */
    2081                 :           4 :   basic_block bb2 = (*cfun->cfg->x_basic_block_info)[2];
    2082                 :           4 :   basic_block bb3 = (*cfun->cfg->x_basic_block_info)[3];
    2083                 :           4 :   basic_block bb4 = (*cfun->cfg->x_basic_block_info)[4];
    2084                 :           4 :   basic_block bb5 = (*cfun->cfg->x_basic_block_info)[5];
    2085                 :             : 
    2086                 :           4 :   ASSERT_EQ (2, bb2->index);
    2087                 :           4 :   ASSERT_EQ (3, bb3->index);
    2088                 :           4 :   ASSERT_EQ (4, bb4->index);
    2089                 :           4 :   ASSERT_EQ (5, bb5->index);
    2090                 :             : 
    2091                 :             :   /* Verify connectivity.  */
    2092                 :             : 
    2093                 :             :   /* Entry block.  */
    2094                 :           4 :   ASSERT_EQ (NULL, entry->preds);
    2095                 :           4 :   ASSERT_EQ (1, entry->succs->length ());
    2096                 :           4 :   ASSERT_EDGE ((*entry->succs)[0], 0, 2, EDGE_FALLTHRU);
    2097                 :             : 
    2098                 :             :   /* bb2.  */
    2099                 :           4 :   ASSERT_EQ (1, bb2->preds->length ());
    2100                 :           4 :   ASSERT_EDGE ((*bb2->preds)[0], 0, 2, EDGE_FALLTHRU);
    2101                 :           4 :   ASSERT_EQ (2, bb2->succs->length ());
    2102                 :           4 :   ASSERT_EDGE ((*bb2->succs)[0], 2, 3, EDGE_TRUE_VALUE);
    2103                 :           4 :   ASSERT_EDGE ((*bb2->succs)[1], 2, 4, EDGE_FALSE_VALUE);
    2104                 :             : 
    2105                 :             :   /* bb3.  */
    2106                 :           4 :   ASSERT_EQ (1, bb3->preds->length ());
    2107                 :           4 :   ASSERT_EDGE ((*bb3->preds)[0], 2, 3, EDGE_TRUE_VALUE);
    2108                 :           4 :   ASSERT_EQ (1, bb3->succs->length ());
    2109                 :           4 :   ASSERT_EDGE ((*bb3->succs)[0], 3, 5, EDGE_FALLTHRU);
    2110                 :             : 
    2111                 :             :   /* bb4.  */
    2112                 :           4 :   ASSERT_EQ (1, bb4->preds->length ());
    2113                 :           4 :   ASSERT_EDGE ((*bb4->preds)[0], 2, 4, EDGE_FALSE_VALUE);
    2114                 :           4 :   ASSERT_EQ (1, bb4->succs->length ());
    2115                 :           4 :   ASSERT_EDGE ((*bb4->succs)[0], 4, 5, EDGE_FALLTHRU);
    2116                 :             : 
    2117                 :             :   /* bb5.  */
    2118                 :           4 :   ASSERT_EQ (2, bb5->preds->length ());
    2119                 :           4 :   ASSERT_EDGE ((*bb5->preds)[0], 3, 5, EDGE_FALLTHRU);
    2120                 :           4 :   ASSERT_EDGE ((*bb5->preds)[1], 4, 5, EDGE_FALLTHRU);
    2121                 :           4 :   ASSERT_EQ (1, bb5->succs->length ());
    2122                 :           4 :   ASSERT_EDGE ((*bb5->succs)[0], 5, 1, EDGE_FALLTHRU);
    2123                 :             : 
    2124                 :             :   /* Exit block.  */
    2125                 :           4 :   ASSERT_EQ (1, exit->preds->length ());
    2126                 :           4 :   ASSERT_EDGE ((*exit->preds)[0], 5, 1, EDGE_FALLTHRU);
    2127                 :           4 :   ASSERT_EQ (NULL, exit->succs);
    2128                 :           4 : }
    2129                 :             : 
    2130                 :             : /* Verify that the loader copes with sparse block indices.
    2131                 :             :    This testcase loads a file with a "(block 42)".  */
    2132                 :             : 
    2133                 :             : static void
    2134                 :           4 : test_loading_bb_index ()
    2135                 :             : {
    2136                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("bb-index.rtl"));
    2137                 :             : 
    2138                 :           4 :   ASSERT_STREQ ("test_bb_index", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
    2139                 :             : 
    2140                 :           4 :   ASSERT_TRUE (cfun);
    2141                 :             : 
    2142                 :           4 :   ASSERT_TRUE (cfun->cfg != NULL);
    2143                 :           4 :   ASSERT_EQ (3, n_basic_blocks_for_fn (cfun));
    2144                 :           4 :   ASSERT_EQ (43, basic_block_info_for_fn (cfun)->length ());
    2145                 :           4 :   ASSERT_EQ (2, n_edges_for_fn (cfun));
    2146                 :             : 
    2147                 :           4 :   ASSERT_EQ (NULL, (*cfun->cfg->x_basic_block_info)[41]);
    2148                 :           4 :   basic_block bb42 = (*cfun->cfg->x_basic_block_info)[42];
    2149                 :           4 :   ASSERT_NE (NULL, bb42);
    2150                 :           4 :   ASSERT_EQ (42, bb42->index);
    2151                 :           4 : }
    2152                 :             : 
    2153                 :             : /* Verify that function_reader::handle_any_trailing_information correctly
    2154                 :             :    parses all the possible items emitted for a MEM.  */
    2155                 :             : 
    2156                 :             : static void
    2157                 :           4 : test_loading_mem ()
    2158                 :             : {
    2159                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("mem.rtl"));
    2160                 :             : 
    2161                 :           4 :   ASSERT_STREQ ("test_mem", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
    2162                 :           4 :   ASSERT_TRUE (cfun);
    2163                 :             : 
    2164                 :             :   /* Verify parsing of "[42 i+17 S8 A128 AS5]".  */
    2165                 :           4 :   rtx_insn *insn_1 = get_insn_by_uid (1);
    2166                 :           4 :   rtx set1 = single_set (insn_1);
    2167                 :           4 :   rtx mem1 = SET_DEST (set1);
    2168                 :           4 :   ASSERT_EQ (42, MEM_ALIAS_SET (mem1));
    2169                 :             :   /* "+17".  */
    2170                 :           4 :   ASSERT_TRUE (MEM_OFFSET_KNOWN_P (mem1));
    2171                 :           4 :   ASSERT_KNOWN_EQ (17, MEM_OFFSET (mem1));
    2172                 :             :   /* "S8".  */
    2173                 :           4 :   ASSERT_KNOWN_EQ (8, MEM_SIZE (mem1));
    2174                 :             :   /* "A128.  */
    2175                 :           4 :   ASSERT_EQ (128, MEM_ALIGN (mem1));
    2176                 :             :   /* "AS5.  */
    2177                 :           4 :   ASSERT_EQ (5, MEM_ADDR_SPACE (mem1));
    2178                 :             : 
    2179                 :             :   /* Verify parsing of "43 i+18 S9 AS6"
    2180                 :             :      (an address space without an alignment).  */
    2181                 :           4 :   rtx_insn *insn_2 = get_insn_by_uid (2);
    2182                 :           4 :   rtx set2 = single_set (insn_2);
    2183                 :           4 :   rtx mem2 = SET_DEST (set2);
    2184                 :           4 :   ASSERT_EQ (43, MEM_ALIAS_SET (mem2));
    2185                 :             :   /* "+18".  */
    2186                 :           4 :   ASSERT_TRUE (MEM_OFFSET_KNOWN_P (mem2));
    2187                 :           4 :   ASSERT_KNOWN_EQ (18, MEM_OFFSET (mem2));
    2188                 :             :   /* "S9".  */
    2189                 :           4 :   ASSERT_KNOWN_EQ (9, MEM_SIZE (mem2));
    2190                 :             :   /* "AS6.  */
    2191                 :           4 :   ASSERT_EQ (6, MEM_ADDR_SPACE (mem2));
    2192                 :           4 : }
    2193                 :             : 
    2194                 :             : /* Verify that "repeated xN" is read correctly.  */
    2195                 :             : 
    2196                 :             : static void
    2197                 :           4 : test_loading_repeat ()
    2198                 :             : {
    2199                 :           4 :   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("repeat.rtl"));
    2200                 :             : 
    2201                 :           4 :   rtx_insn *insn_1 = get_insn_by_uid (1);
    2202                 :           4 :   ASSERT_EQ (PARALLEL, GET_CODE (PATTERN (insn_1)));
    2203                 :           4 :   ASSERT_EQ (64, XVECLEN (PATTERN (insn_1), 0));
    2204                 :         260 :   for (int i = 0; i < 64; i++)
    2205                 :         256 :     ASSERT_EQ (const0_rtx, XVECEXP (PATTERN (insn_1), 0, i));
    2206                 :           4 : }
    2207                 :             : 
    2208                 :             : /* Run all of the selftests within this file.  */
    2209                 :             : 
    2210                 :             : void
    2211                 :           4 : read_rtl_function_cc_tests ()
    2212                 :             : {
    2213                 :           4 :   test_edge_flags ();
    2214                 :           4 :   test_parsing_regnos ();
    2215                 :           4 :   test_loading_dump_fragment_1 ();
    2216                 :           4 :   test_loading_dump_fragment_2 ();
    2217                 :           4 :   test_loading_labels ();
    2218                 :           4 :   test_loading_insn_with_mode ();
    2219                 :           4 :   test_loading_jump_to_label_ref ();
    2220                 :           4 :   test_loading_jump_to_return ();
    2221                 :           4 :   test_loading_jump_to_simple_return ();
    2222                 :           4 :   test_loading_note_insn_basic_block ();
    2223                 :           4 :   test_loading_note_insn_deleted ();
    2224                 :           4 :   test_loading_const_int ();
    2225                 :           4 :   test_loading_symbol_ref ();
    2226                 :           4 :   test_loading_cfg ();
    2227                 :           4 :   test_loading_bb_index ();
    2228                 :           4 :   test_loading_mem ();
    2229                 :           4 :   test_loading_repeat ();
    2230                 :           4 : }
    2231                 :             : 
    2232                 :             : } // namespace selftest
    2233                 :             : 
    2234                 :             : #endif /* #if CHECKING_P */
        

Generated by: LCOV version 2.1-beta

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