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