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 	  return rtx_reader::read_rtx_operand (x, idx);
890 	  m_in_call_function_usage = false;
891 	}
892       else
893 	return rtx_reader::read_rtx_operand (x, idx);
894       break;
895 
896     case 'u':
897       read_rtx_operand_u (x, idx);
898       /* Don't run regular parser for 'u'.  */
899       return x;
900 
901     case 'i':
902     case 'n':
903       read_rtx_operand_i_or_n (x, idx, format_char);
904       /* Don't run regular parser for these codes.  */
905       return x;
906 
907     case 'B':
908       gcc_assert (is_compact ());
909       /* Compact mode doesn't store BBs.  */
910       /* Don't run regular parser.  */
911       return x;
912 
913     case 'r':
914       /* Don't run regular parser for 'r'.  */
915       return read_rtx_operand_r (x);
916 
917     default:
918       break;
919     }
920 
921   /* Call base class implementation.  */
922   x = rtx_reader::read_rtx_operand (x, idx);
923 
924   /* Handle any additional parsing needed to handle what the dump
925      could contain.  */
926   switch (format_char)
927     {
928     case '0':
929       x = extra_parsing_for_operand_code_0 (x, idx);
930       break;
931 
932     case 'w':
933       if (!is_compact ())
934 	{
935 	  /* Strip away the redundant hex dump of the value.  */
936 	  require_char_ws ('[');
937 	  read_name (&name);
938 	  require_char_ws (']');
939 	}
940       break;
941 
942     default:
943       break;
944     }
945 
946   return x;
947 }
948 
949 /* Parse operand IDX of X, of code 'u', when reading function dumps.
950 
951    The RTL file recorded the ID of an insn (or 0 for NULL); we
952    must store this as a pointer, but the insn might not have
953    been loaded yet.  Store the ID away for now, via a fixup.  */
954 
955 void
read_rtx_operand_u(rtx x,int idx)956 function_reader::read_rtx_operand_u (rtx x, int idx)
957 {
958   /* In compact mode, the PREV/NEXT insn uids are not dumped, so skip
959      the "uu" when reading. */
960   if (is_compact () && GET_CODE (x) != LABEL_REF)
961     return;
962 
963   struct md_name name;
964   file_location loc = read_name (&name);
965   int insn_id = atoi (name.string);
966   if (insn_id)
967     add_fixup_insn_uid (loc, x, idx, insn_id);
968 }
969 
970 /* Read a name, looking for a match against a string found in array
971    STRINGS of size NUM_VALUES.
972    Return the index of the matched string, or emit an error.  */
973 
974 int
parse_enum_value(int num_values,const char * const * strings)975 function_reader::parse_enum_value (int num_values, const char *const *strings)
976 {
977   struct md_name name;
978   read_name (&name);
979   for (int i = 0; i < num_values; i++)
980     {
981       if (strcmp (name.string, strings[i]) == 0)
982 	return i;
983     }
984   error ("unrecognized enum value: %qs", name.string);
985   return 0;
986 }
987 
988 /* Parse operand IDX of X, of code 'i' or 'n' (as specified by FORMAT_CHAR).
989    Special-cased handling of these, for reading function dumps.  */
990 
991 void
read_rtx_operand_i_or_n(rtx x,int idx,char format_char)992 function_reader::read_rtx_operand_i_or_n (rtx x, int idx,
993 					  char format_char)
994 {
995   /* Handle some of the extra information that print_rtx
996      can write out for these cases.  */
997   /* print_rtx only writes out operand 5 for notes
998      for NOTE_KIND values NOTE_INSN_DELETED_LABEL
999      and NOTE_INSN_DELETED_DEBUG_LABEL.  */
1000   if (idx == 5 && NOTE_P (x))
1001     return;
1002 
1003   if (idx == 4 && INSN_P (x))
1004     {
1005       maybe_read_location (as_a <rtx_insn *> (x));
1006       return;
1007     }
1008 
1009   /* INSN_CODEs aren't printed in compact mode, so don't attempt to
1010      parse them.  */
1011   if (is_compact ()
1012       && INSN_P (x)
1013       && &INSN_CODE (x) == &XINT (x, idx))
1014     {
1015       INSN_CODE (x) = -1;
1016       return;
1017     }
1018 
1019   /* Handle UNSPEC and UNSPEC_VOLATILE's operand 1.  */
1020 #if !defined(GENERATOR_FILE) && NUM_UNSPECV_VALUES > 0
1021   if (idx == 1
1022       && GET_CODE (x) == UNSPEC_VOLATILE)
1023     {
1024       XINT (x, 1)
1025 	= parse_enum_value (NUM_UNSPECV_VALUES, unspecv_strings);
1026       return;
1027     }
1028 #endif
1029 #if !defined(GENERATOR_FILE) && NUM_UNSPEC_VALUES > 0
1030   if (idx == 1
1031       && (GET_CODE (x) == UNSPEC
1032 	  || GET_CODE (x) == UNSPEC_VOLATILE))
1033     {
1034       XINT (x, 1)
1035 	= parse_enum_value (NUM_UNSPEC_VALUES, unspec_strings);
1036       return;
1037     }
1038 #endif
1039 
1040   struct md_name name;
1041   read_name (&name);
1042   int value;
1043   if (format_char == 'n')
1044     value = parse_note_insn_name (name.string);
1045   else
1046     value = atoi (name.string);
1047   XINT (x, idx) = value;
1048 }
1049 
1050 /* Parse the 'r' operand of X, returning X, or an equivalent rtx
1051    expression (for consolidating singletons).
1052    Special-cased handling of code 'r' for reading function dumps.  */
1053 
1054 rtx
read_rtx_operand_r(rtx x)1055 function_reader::read_rtx_operand_r (rtx x)
1056 {
1057   struct md_name name;
1058   file_location loc = read_name (&name);
1059   int regno = lookup_reg_by_dump_name (name.string);
1060   if (regno == -1)
1061     fatal_at (loc, "unrecognized register: '%s'", name.string);
1062 
1063   set_regno_raw (x, regno, 1);
1064 
1065   /* Consolidate singletons.  */
1066   x = consolidate_singletons (x);
1067 
1068   ORIGINAL_REGNO (x) = regno;
1069 
1070   /* Parse extra stuff at end of 'r'.
1071      We may have zero, one, or two sections marked by square
1072      brackets.  */
1073   int ch = read_skip_spaces ();
1074   bool expect_original_regno = false;
1075   if (ch == '[')
1076     {
1077       file_location loc = get_current_location ();
1078       char *desc = read_until ("]", true);
1079       strip_trailing_whitespace (desc);
1080       const char *desc_start = desc;
1081       /* If ORIGINAL_REGNO (rtx) != regno, we will have:
1082 	 "orig:%i", ORIGINAL_REGNO (rtx).
1083 	 Consume it, we don't set ORIGINAL_REGNO, since we can
1084 	 get that from the 2nd copy later.  */
1085       if (strncmp (desc, "orig:", 5) == 0)
1086 	{
1087 	  expect_original_regno = true;
1088 	  desc_start += 5;
1089 	  /* Skip to any whitespace following the integer.  */
1090 	  const char *space = strchr (desc_start, ' ');
1091 	  if (space)
1092 	    desc_start = space + 1;
1093 	}
1094       /* Any remaining text may be the REG_EXPR.  Alternatively we have
1095 	 no REG_ATTRS, and instead we have ORIGINAL_REGNO.  */
1096       if (ISDIGIT (*desc_start))
1097 	{
1098 	  /* Assume we have ORIGINAL_REGNO.  */
1099 	  ORIGINAL_REGNO (x) = atoi (desc_start);
1100 	}
1101       else
1102 	{
1103 	  /* Assume we have REG_EXPR.  */
1104 	  add_fixup_expr (loc, x, desc_start);
1105 	}
1106       free (desc);
1107     }
1108   else
1109     unread_char (ch);
1110   if (expect_original_regno)
1111     {
1112       require_char_ws ('[');
1113       char *desc = read_until ("]", true);
1114       ORIGINAL_REGNO (x) = atoi (desc);
1115       free (desc);
1116     }
1117 
1118   return x;
1119 }
1120 
1121 /* Additional parsing for format code '0' in dumps, handling a variety
1122    of special-cases in print_rtx, when parsing operand IDX of X.
1123    Return X, or possibly a reallocated copy of X.  */
1124 
1125 rtx
extra_parsing_for_operand_code_0(rtx x,int idx)1126 function_reader::extra_parsing_for_operand_code_0 (rtx x, int idx)
1127 {
1128   RTX_CODE code = GET_CODE (x);
1129   int c;
1130   struct md_name name;
1131 
1132   if (idx == 1 && code == SYMBOL_REF)
1133     {
1134       /* Possibly wrote " [flags %#x]", SYMBOL_REF_FLAGS (in_rtx).  */
1135       c = read_skip_spaces ();
1136       if (c == '[')
1137 	{
1138 	  file_location loc = read_name (&name);
1139 	  if (strcmp (name.string, "flags"))
1140 	    error_at (loc, "was expecting `%s'", "flags");
1141 	  read_name (&name);
1142 	  SYMBOL_REF_FLAGS (x) = strtol (name.string, NULL, 16);
1143 
1144 	  /* The standard RTX_CODE_SIZE (SYMBOL_REF) used when allocating
1145 	     x doesn't have space for the block_symbol information, so
1146 	     we must reallocate it if this flag is set.  */
1147 	  if (SYMBOL_REF_HAS_BLOCK_INFO_P (x))
1148 	    {
1149 	      /* Emulate the allocation normally done by
1150 		 varasm.c:create_block_symbol.  */
1151 	      unsigned int size = RTX_HDR_SIZE + sizeof (struct block_symbol);
1152 	      rtx new_x = (rtx) ggc_internal_alloc (size);
1153 
1154 	      /* Copy data over from the smaller SYMBOL_REF.  */
1155 	      memcpy (new_x, x, RTX_CODE_SIZE (SYMBOL_REF));
1156 	      x = new_x;
1157 
1158 	      /* We can't reconstruct SYMBOL_REF_BLOCK; set it to NULL.  */
1159 	      SYMBOL_REF_BLOCK (x) = NULL;
1160 
1161 	      /* Zero the offset.  */
1162 	      SYMBOL_REF_BLOCK_OFFSET (x) = 0;
1163 	    }
1164 
1165 	  require_char (']');
1166 	}
1167       else
1168 	unread_char (c);
1169 
1170       /* If X had a non-NULL SYMBOL_REF_DECL,
1171 	 rtx_writer::print_rtx_operand_code_0 would have dumped it
1172 	 using print_node_brief.
1173 	 Skip the content for now.  */
1174       c = read_skip_spaces ();
1175       if (c == '<')
1176 	{
1177 	  while (1)
1178 	    {
1179 	      char ch = read_char ();
1180 	      if (ch == '>')
1181 		break;
1182 	    }
1183 	}
1184       else
1185 	unread_char (c);
1186     }
1187   else if (idx == 3 && code == NOTE)
1188     {
1189       /* Note-specific data appears for operand 3, which annoyingly
1190 	 is before the enum specifying which kind of note we have
1191 	 (operand 4).  */
1192       c = read_skip_spaces ();
1193       if (c == '[')
1194 	{
1195 	  /* Possibly data for a NOTE_INSN_BASIC_BLOCK, of the form:
1196 	     [bb %d].  */
1197 	  file_location bb_loc = read_name (&name);
1198 	  if (strcmp (name.string, "bb"))
1199 	    error_at (bb_loc, "was expecting `%s'", "bb");
1200 	  read_name (&name);
1201 	  int bb_idx = atoi (name.string);
1202 	  add_fixup_note_insn_basic_block (bb_loc, x, idx,
1203 					   bb_idx);
1204 	  require_char_ws (']');
1205 	}
1206       else
1207 	unread_char (c);
1208     }
1209 
1210   return x;
1211 }
1212 
1213 /* Implementation of rtx_reader::handle_any_trailing_information.
1214    Handle the various additional information that print-rtl.c can
1215    write after the regular fields, when parsing X.  */
1216 
1217 void
handle_any_trailing_information(rtx x)1218 function_reader::handle_any_trailing_information (rtx x)
1219 {
1220   struct md_name name;
1221 
1222   switch (GET_CODE (x))
1223     {
1224       case MEM:
1225 	{
1226 	  int ch;
1227 	  require_char_ws ('[');
1228 	  read_name (&name);
1229 	  set_mem_alias_set (x, atoi (name.string));
1230 	  /* We have either a MEM_EXPR, or a space.  */
1231 	  if (peek_char () != ' ')
1232 	    {
1233 	      file_location loc = get_current_location ();
1234 	      char *desc = read_until (" +", false);
1235 	      add_fixup_expr (loc, consolidate_singletons (x), desc);
1236 	      free (desc);
1237 	    }
1238 	  else
1239 	    read_char ();
1240 
1241 	  /* We may optionally have '+' for MEM_OFFSET_KNOWN_P.  */
1242 	  ch = read_skip_spaces ();
1243 	  if (ch == '+')
1244 	    {
1245 	      read_name (&name);
1246 	      set_mem_offset (x, atoi (name.string));
1247 	    }
1248 	  else
1249 	    unread_char (ch);
1250 
1251 	  /* Handle optional " S" for MEM_SIZE.  */
1252 	  ch = read_skip_spaces ();
1253 	  if (ch == 'S')
1254 	    {
1255 	      read_name (&name);
1256 	      set_mem_size (x, atoi (name.string));
1257 	    }
1258 	  else
1259 	    unread_char (ch);
1260 
1261 	  /* Handle optional " A" for MEM_ALIGN.  */
1262 	  ch = read_skip_spaces ();
1263 	  if (ch == 'A' && peek_char () != 'S')
1264 	    {
1265 	      read_name (&name);
1266 	      set_mem_align (x, atoi (name.string));
1267 	    }
1268 	  else
1269 	    unread_char (ch);
1270 
1271 	  /* Handle optional " AS" for MEM_ADDR_SPACE.  */
1272 	  ch = read_skip_spaces ();
1273 	  if (ch == 'A' && peek_char () == 'S')
1274 	    {
1275 	      read_char ();
1276 	      read_name (&name);
1277 	      set_mem_addr_space (x, atoi (name.string));
1278 	    }
1279 	  else
1280 	    unread_char (ch);
1281 
1282 	  require_char (']');
1283 	}
1284 	break;
1285 
1286       case CODE_LABEL:
1287 	/* Assume that LABEL_NUSES was not dumped.  */
1288 	/* TODO: parse LABEL_KIND.  */
1289 	/* For now, skip until closing ')'.  */
1290 	do
1291 	  {
1292 	    char ch = read_char ();
1293 	    if (ch == ')')
1294 	      {
1295 		unread_char (ch);
1296 		break;
1297 	      }
1298 	  }
1299 	while (1);
1300 	break;
1301 
1302       default:
1303 	break;
1304     }
1305 }
1306 
1307 /* Parse a tree dump for a MEM_EXPR in DESC and turn it back into a tree.
1308    We handle "<retval>" and param names within cfun, but for anything else
1309    we "cheat" by building a global VAR_DECL of type "int" with that name
1310    (returning the same global for a name if we see the same name more
1311    than once).  */
1312 
1313 tree
parse_mem_expr(const char * desc)1314 function_reader::parse_mem_expr (const char *desc)
1315 {
1316   tree fndecl = cfun->decl;
1317 
1318   if (strcmp (desc, "<retval>") == 0)
1319     return DECL_RESULT (fndecl);
1320 
1321   tree param = find_param_by_name (fndecl, desc);
1322   if (param)
1323     return param;
1324 
1325   /* Search within decls we already created.
1326      FIXME: use a hash rather than linear search.  */
1327   int i;
1328   tree t;
1329   FOR_EACH_VEC_ELT (m_fake_scope, i, t)
1330     if (id_equal (DECL_NAME (t), desc))
1331       return t;
1332 
1333   /* Not found?  Create it.
1334      This allows mimicking of real data but avoids having to specify
1335      e.g. names of locals, params etc.
1336      Though this way we don't know if we have a PARM_DECL vs a VAR_DECL,
1337      and we don't know the types.  Fake it by making everything be
1338      a VAR_DECL of "int" type.  */
1339   t = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1340 		  get_identifier (desc),
1341 		  integer_type_node);
1342   m_fake_scope.safe_push (t);
1343   return t;
1344 }
1345 
1346 /* Record that at LOC we saw an insn uid INSN_UID for the operand with index
1347    OPERAND_IDX within INSN, so that the pointer value can be fixed up in
1348    later post-processing.  */
1349 
1350 void
add_fixup_insn_uid(file_location loc,rtx insn,int operand_idx,int insn_uid)1351 function_reader::add_fixup_insn_uid (file_location loc, rtx insn, int operand_idx,
1352 				     int insn_uid)
1353 {
1354   m_fixups.safe_push (new fixup_insn_uid (loc, insn, operand_idx, insn_uid));
1355 }
1356 
1357 /* Record that at LOC we saw an basic block index BB_IDX for the operand with index
1358    OPERAND_IDX within INSN, so that the pointer value can be fixed up in
1359    later post-processing.  */
1360 
1361 void
add_fixup_note_insn_basic_block(file_location loc,rtx insn,int operand_idx,int bb_idx)1362 function_reader::add_fixup_note_insn_basic_block (file_location loc, rtx insn,
1363 						  int operand_idx, int bb_idx)
1364 {
1365   m_fixups.safe_push (new fixup_note_insn_basic_block (loc, insn, operand_idx,
1366 						       bb_idx));
1367 }
1368 
1369 /* Placeholder hook for recording source location information seen in a dump.
1370    This is empty for now.  */
1371 
1372 void
add_fixup_source_location(file_location,rtx_insn *,const char *,int,int)1373 function_reader::add_fixup_source_location (file_location, rtx_insn *,
1374 					    const char *, int, int)
1375 {
1376 }
1377 
1378 /* Record that at LOC we saw textual description DESC of the MEM_EXPR or REG_EXPR
1379    of INSN, so that the fields can be fixed up in later post-processing.  */
1380 
1381 void
add_fixup_expr(file_location loc,rtx insn,const char * desc)1382 function_reader::add_fixup_expr (file_location loc, rtx insn,
1383 				 const char *desc)
1384 {
1385   gcc_assert (desc);
1386   /* Fail early if the RTL reader erroneously hands us an int.  */
1387   gcc_assert (!ISDIGIT (desc[0]));
1388 
1389   m_fixups.safe_push (new fixup_expr (loc, insn, desc));
1390 }
1391 
1392 /* Helper function for consolidate_reg.  Return the global rtx for
1393    the register with regno REGNO.  */
1394 
1395 static rtx
lookup_global_register(int regno)1396 lookup_global_register (int regno)
1397 {
1398   /* We can't use a switch here, as some of the REGNUMs might not be constants
1399      for some targets.  */
1400   if (regno == STACK_POINTER_REGNUM)
1401       return stack_pointer_rtx;
1402   else if (regno ==  FRAME_POINTER_REGNUM)
1403     return frame_pointer_rtx;
1404   else if (regno == HARD_FRAME_POINTER_REGNUM)
1405     return hard_frame_pointer_rtx;
1406   else if (regno == ARG_POINTER_REGNUM)
1407     return arg_pointer_rtx;
1408   else if (regno == VIRTUAL_INCOMING_ARGS_REGNUM)
1409     return virtual_incoming_args_rtx;
1410   else if (regno == VIRTUAL_STACK_VARS_REGNUM)
1411     return virtual_stack_vars_rtx;
1412   else if (regno == VIRTUAL_STACK_DYNAMIC_REGNUM)
1413     return virtual_stack_dynamic_rtx;
1414   else if (regno == VIRTUAL_OUTGOING_ARGS_REGNUM)
1415     return virtual_outgoing_args_rtx;
1416   else if (regno == VIRTUAL_CFA_REGNUM)
1417     return virtual_cfa_rtx;
1418   else if (regno == VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM)
1419     return virtual_preferred_stack_boundary_rtx;
1420 #ifdef return_ADDRESS_POINTER_REGNUM
1421   else if (regno == RETURN_ADDRESS_POINTER_REGNUM)
1422     return return_address_pointer_rtx;
1423 #endif
1424 
1425   return NULL;
1426 }
1427 
1428 /* Ensure that the backend can cope with a REG with regno REGNO.
1429    Normally REG instances are created by gen_reg_rtx which updates
1430    regno_reg_rtx, growing it as necessary.
1431    The REG instances created from the dumpfile weren't created this
1432    way, so we need to manually update regno_reg_rtx.  */
1433 
1434 static void
ensure_regno(int regno)1435 ensure_regno (int regno)
1436 {
1437   if (reg_rtx_no < regno + 1)
1438     reg_rtx_no = regno + 1;
1439 
1440   crtl->emit.ensure_regno_capacity ();
1441   gcc_assert (regno < crtl->emit.regno_pointer_align_length);
1442 }
1443 
1444 /* Helper function for consolidate_singletons, for handling REG instances.
1445    Given REG instance X of some regno, return the singleton rtx for that
1446    regno, if it exists, or X.  */
1447 
1448 static rtx
consolidate_reg(rtx x)1449 consolidate_reg (rtx x)
1450 {
1451   gcc_assert (GET_CODE (x) == REG);
1452 
1453   unsigned int regno = REGNO (x);
1454 
1455   ensure_regno (regno);
1456 
1457   /* Some register numbers have their rtx created in init_emit_regs
1458      e.g. stack_pointer_rtx for STACK_POINTER_REGNUM.
1459      Consolidate on this.  */
1460   rtx global_reg = lookup_global_register (regno);
1461   if (global_reg)
1462     return global_reg;
1463 
1464   /* Populate regno_reg_rtx if necessary.  */
1465   if (regno_reg_rtx[regno] == NULL)
1466     regno_reg_rtx[regno] = x;
1467   /* Use it.  */
1468   gcc_assert (GET_CODE (regno_reg_rtx[regno]) == REG);
1469   gcc_assert (REGNO (regno_reg_rtx[regno]) == regno);
1470   if (GET_MODE (x) == GET_MODE (regno_reg_rtx[regno]))
1471     return regno_reg_rtx[regno];
1472 
1473   return x;
1474 }
1475 
1476 /* When reading RTL function dumps, we must consolidate some
1477    rtx so that we use singletons where singletons are expected
1478    (e.g. we don't want multiple "(const_int 0 [0])" rtx, since
1479    these are tested via pointer equality against const0_rtx.
1480 
1481    Return the equivalent singleton rtx for X, if any, otherwise X.  */
1482 
1483 rtx
consolidate_singletons(rtx x)1484 function_reader::consolidate_singletons (rtx x)
1485 {
1486   if (!x)
1487     return x;
1488 
1489   switch (GET_CODE (x))
1490     {
1491     case PC: return pc_rtx;
1492     case RETURN: return ret_rtx;
1493     case SIMPLE_RETURN: return simple_return_rtx;
1494     case CC0: return cc0_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     default:
1503       break;
1504     }
1505 
1506   return x;
1507 }
1508 
1509 /* Parse an rtx directive, including both the opening/closing parentheses,
1510    and the name.  */
1511 
1512 rtx
parse_rtx()1513 function_reader::parse_rtx ()
1514 {
1515   require_char_ws ('(');
1516   struct md_name directive;
1517   read_name (&directive);
1518   rtx result
1519     = consolidate_singletons (read_rtx_code (directive.string));
1520   require_char_ws (')');
1521 
1522   return result;
1523 }
1524 
1525 /* Implementation of rtx_reader::postprocess for reading function dumps.
1526    Return the equivalent singleton rtx for X, if any, otherwise X.  */
1527 
1528 rtx
postprocess(rtx x)1529 function_reader::postprocess (rtx x)
1530 {
1531   return consolidate_singletons (x);
1532 }
1533 
1534 /* Implementation of rtx_reader::finalize_string for reading function dumps.
1535    Make a GC-managed copy of STRINGBUF.  */
1536 
1537 const char *
finalize_string(char * stringbuf)1538 function_reader::finalize_string (char *stringbuf)
1539 {
1540   return ggc_strdup (stringbuf);
1541 }
1542 
1543 /* Attempt to parse optional location information for insn INSN, as
1544    potentially written out by rtx_writer::print_rtx_operand_code_i.
1545    We look for a quoted string followed by a colon.  */
1546 
1547 void
maybe_read_location(rtx_insn * insn)1548 function_reader::maybe_read_location (rtx_insn *insn)
1549 {
1550   file_location loc = get_current_location ();
1551 
1552   /* Attempt to parse a quoted string.  */
1553   int ch = read_skip_spaces ();
1554   if (ch == '"')
1555     {
1556       char *filename = read_quoted_string ();
1557       require_char (':');
1558       struct md_name line_num;
1559       read_name (&line_num);
1560 
1561       int column = 0;
1562       int ch = read_char ();
1563       if (ch == ':')
1564 	{
1565 	  struct md_name column_num;
1566 	  read_name (&column_num);
1567 	  column = atoi (column_num.string);
1568 	}
1569       else
1570 	unread_char (ch);
1571       add_fixup_source_location (loc, insn, filename,
1572 				 atoi (line_num.string),
1573 				 column);
1574     }
1575   else
1576     unread_char (ch);
1577 }
1578 
1579 /* Postprocessing subroutine of function_reader::parse_function.
1580    Populate m_insns_by_uid.  */
1581 
1582 void
handle_insn_uids()1583 function_reader::handle_insn_uids ()
1584 {
1585   /* Locate the currently assigned INSN_UID values, storing
1586      them in m_insns_by_uid.  */
1587   int max_uid = 0;
1588   for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
1589     {
1590       if (m_insns_by_uid.get (INSN_UID (insn)))
1591 	error ("duplicate insn UID: %i", INSN_UID (insn));
1592       m_insns_by_uid.put (INSN_UID (insn), insn);
1593       if (INSN_UID (insn) > max_uid)
1594 	max_uid = INSN_UID (insn);
1595     }
1596 
1597   /* Ensure x_cur_insn_uid is 1 more than the biggest insn UID seen.
1598      This is normally updated by the various make_*insn_raw functions.  */
1599   crtl->emit.x_cur_insn_uid = max_uid + 1;
1600 }
1601 
1602 /* Apply all of the recorded fixups.  */
1603 
1604 void
apply_fixups()1605 function_reader::apply_fixups ()
1606 {
1607   int i;
1608   fixup *f;
1609   FOR_EACH_VEC_ELT (m_fixups, i, f)
1610     f->apply (this);
1611 }
1612 
1613 /* Given a UID value, try to locate a pointer to the corresponding
1614    rtx_insn *, or NULL if it can't be found.  */
1615 
1616 rtx_insn **
get_insn_by_uid(int uid)1617 function_reader::get_insn_by_uid (int uid)
1618 {
1619   return m_insns_by_uid.get (uid);
1620 }
1621 
1622 /* Run the RTL dump parser, parsing a dump located at PATH.
1623    Return true iff the file was successfully parsed.  */
1624 
1625 bool
read_rtl_function_body(const char * path)1626 read_rtl_function_body (const char *path)
1627 {
1628   initialize_rtl ();
1629   crtl->abi = &default_function_abi;
1630   init_emit ();
1631   init_varasm_status ();
1632 
1633   function_reader reader;
1634   if (!reader.read_file (path))
1635     return false;
1636 
1637   return true;
1638 }
1639 
1640 /* Run the RTL dump parser on the range of lines between START_LOC and
1641    END_LOC (including those lines).  */
1642 
1643 bool
read_rtl_function_body_from_file_range(location_t start_loc,location_t end_loc)1644 read_rtl_function_body_from_file_range (location_t start_loc,
1645 					location_t end_loc)
1646 {
1647   expanded_location exploc_start = expand_location (start_loc);
1648   expanded_location exploc_end = expand_location (end_loc);
1649 
1650   if (exploc_start.file != exploc_end.file)
1651     {
1652       error_at (end_loc, "start/end of RTL fragment are in different files");
1653       return false;
1654     }
1655   if (exploc_start.line >= exploc_end.line)
1656     {
1657       error_at (end_loc,
1658 		"start of RTL fragment must be on an earlier line than end");
1659       return false;
1660     }
1661 
1662   initialize_rtl ();
1663   crtl->abi = &fndecl_abi (cfun->decl).base_abi ();
1664   init_emit ();
1665   init_varasm_status ();
1666 
1667   function_reader reader;
1668   if (!reader.read_file_fragment (exploc_start.file, exploc_start.line,
1669 				  exploc_end.line - 1))
1670     return false;
1671 
1672   return true;
1673 }
1674 
1675 #if CHECKING_P
1676 
1677 namespace selftest {
1678 
1679 /* Verify that parse_edge_flags works.  */
1680 
1681 static void
test_edge_flags()1682 test_edge_flags ()
1683 {
1684   /* parse_edge_flags modifies its input (due to strtok), so we must make
1685      a copy of the literals.  */
1686 #define ASSERT_PARSE_EDGE_FLAGS(EXPECTED, STR) \
1687   do { \
1688     char *str = xstrdup (STR); \
1689     ASSERT_EQ (EXPECTED, parse_edge_flags (str)); \
1690     free (str); \
1691   } while (0)
1692 
1693   ASSERT_PARSE_EDGE_FLAGS (0, "");
1694   ASSERT_PARSE_EDGE_FLAGS (EDGE_FALLTHRU, "FALLTHRU");
1695   ASSERT_PARSE_EDGE_FLAGS (EDGE_ABNORMAL_CALL, "ABNORMAL_CALL");
1696   ASSERT_PARSE_EDGE_FLAGS (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL,
1697 			   "ABNORMAL | ABNORMAL_CALL");
1698 
1699 #undef  ASSERT_PARSE_EDGE_FLAGS
1700 }
1701 
1702 /* Verify that lookup_reg_by_dump_name works.  */
1703 
1704 static void
test_parsing_regnos()1705 test_parsing_regnos ()
1706 {
1707   ASSERT_EQ (-1, lookup_reg_by_dump_name ("this is not a register"));
1708 
1709   /* Verify lookup of virtual registers.  */
1710   ASSERT_EQ (VIRTUAL_INCOMING_ARGS_REGNUM,
1711     lookup_reg_by_dump_name ("virtual-incoming-args"));
1712   ASSERT_EQ (VIRTUAL_STACK_VARS_REGNUM,
1713     lookup_reg_by_dump_name ("virtual-stack-vars"));
1714   ASSERT_EQ (VIRTUAL_STACK_DYNAMIC_REGNUM,
1715     lookup_reg_by_dump_name ("virtual-stack-dynamic"));
1716   ASSERT_EQ (VIRTUAL_OUTGOING_ARGS_REGNUM,
1717     lookup_reg_by_dump_name ("virtual-outgoing-args"));
1718   ASSERT_EQ (VIRTUAL_CFA_REGNUM,
1719     lookup_reg_by_dump_name ("virtual-cfa"));
1720   ASSERT_EQ (VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM,
1721     lookup_reg_by_dump_name ("virtual-preferred-stack-boundary"));
1722 
1723   /* Verify lookup of non-virtual pseudos.  */
1724   ASSERT_EQ (LAST_VIRTUAL_REGISTER + 1, lookup_reg_by_dump_name ("<0>"));
1725   ASSERT_EQ (LAST_VIRTUAL_REGISTER + 2, lookup_reg_by_dump_name ("<1>"));
1726 }
1727 
1728 /* Verify that edge E is as expected, with the src and dest basic blocks
1729    having indices EXPECTED_SRC_IDX and EXPECTED_DEST_IDX respectively, and
1730    the edge having flags equal to EXPECTED_FLAGS.
1731    Use LOC as the effective location when reporting failures.  */
1732 
1733 static void
assert_edge_at(const location & loc,edge e,int expected_src_idx,int expected_dest_idx,int expected_flags)1734 assert_edge_at (const location &loc, edge e, int expected_src_idx,
1735 		int expected_dest_idx, int expected_flags)
1736 {
1737   ASSERT_EQ_AT (loc, expected_src_idx, e->src->index);
1738   ASSERT_EQ_AT (loc, expected_dest_idx, e->dest->index);
1739   ASSERT_EQ_AT (loc, expected_flags, e->flags);
1740 }
1741 
1742 /* Verify that edge EDGE is as expected, with the src and dest basic blocks
1743    having indices EXPECTED_SRC_IDX and EXPECTED_DEST_IDX respectively, and
1744    the edge having flags equal to EXPECTED_FLAGS.  */
1745 
1746 #define ASSERT_EDGE(EDGE, EXPECTED_SRC_IDX, EXPECTED_DEST_IDX,		\
1747 		    EXPECTED_FLAGS)					\
1748   assert_edge_at (SELFTEST_LOCATION, EDGE, EXPECTED_SRC_IDX, \
1749 		  EXPECTED_DEST_IDX, EXPECTED_FLAGS)
1750 
1751 /* Verify that we can load RTL dumps.  */
1752 
1753 static void
test_loading_dump_fragment_1()1754 test_loading_dump_fragment_1 ()
1755 {
1756   // TODO: filter on target?
1757   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("asr_div1.rtl"));
1758 
1759   /* Verify that the insns were loaded correctly.  */
1760   rtx_insn *insn_1 = get_insns ();
1761   ASSERT_TRUE (insn_1);
1762   ASSERT_EQ (1, INSN_UID (insn_1));
1763   ASSERT_EQ (INSN, GET_CODE (insn_1));
1764   ASSERT_EQ (SET, GET_CODE (PATTERN (insn_1)));
1765   ASSERT_EQ (NULL, PREV_INSN (insn_1));
1766 
1767   rtx_insn *insn_2 = NEXT_INSN (insn_1);
1768   ASSERT_TRUE (insn_2);
1769   ASSERT_EQ (2, INSN_UID (insn_2));
1770   ASSERT_EQ (INSN, GET_CODE (insn_2));
1771   ASSERT_EQ (insn_1, PREV_INSN (insn_2));
1772   ASSERT_EQ (NULL, NEXT_INSN (insn_2));
1773 
1774   /* Verify that registers were loaded correctly.  */
1775   rtx insn_1_dest = SET_DEST (PATTERN (insn_1));
1776   ASSERT_EQ (REG, GET_CODE (insn_1_dest));
1777   ASSERT_EQ ((LAST_VIRTUAL_REGISTER + 1) + 2, REGNO (insn_1_dest));
1778   rtx insn_1_src = SET_SRC (PATTERN (insn_1));
1779   ASSERT_EQ (LSHIFTRT, GET_CODE (insn_1_src));
1780   rtx reg = XEXP (insn_1_src, 0);
1781   ASSERT_EQ (REG, GET_CODE (reg));
1782   ASSERT_EQ (LAST_VIRTUAL_REGISTER + 1, REGNO (reg));
1783 
1784   /* Verify that get_insn_by_uid works.  */
1785   ASSERT_EQ (insn_1, get_insn_by_uid (1));
1786   ASSERT_EQ (insn_2, get_insn_by_uid (2));
1787 
1788   /* Verify that basic blocks were created.  */
1789   ASSERT_EQ (2, BLOCK_FOR_INSN (insn_1)->index);
1790   ASSERT_EQ (2, BLOCK_FOR_INSN (insn_2)->index);
1791 
1792   /* Verify that the CFG was recreated.  */
1793   ASSERT_TRUE (cfun);
1794   verify_three_block_rtl_cfg (cfun);
1795   basic_block bb2 = BASIC_BLOCK_FOR_FN (cfun, 2);
1796   ASSERT_TRUE (bb2 != NULL);
1797   ASSERT_EQ (BB_RTL, bb2->flags & BB_RTL);
1798   ASSERT_EQ (2, bb2->index);
1799   ASSERT_EQ (insn_1, BB_HEAD (bb2));
1800   ASSERT_EQ (insn_2, BB_END (bb2));
1801 }
1802 
1803 /* Verify loading another RTL dump.  */
1804 
1805 static void
test_loading_dump_fragment_2()1806 test_loading_dump_fragment_2 ()
1807 {
1808   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("simple-cse.rtl"));
1809 
1810   rtx_insn *insn_1 = get_insn_by_uid (1);
1811   rtx_insn *insn_2 = get_insn_by_uid (2);
1812   rtx_insn *insn_3 = get_insn_by_uid (3);
1813 
1814   rtx set1 = single_set (insn_1);
1815   ASSERT_NE (NULL, set1);
1816   rtx set2 = single_set (insn_2);
1817   ASSERT_NE (NULL, set2);
1818   rtx set3 = single_set (insn_3);
1819   ASSERT_NE (NULL, set3);
1820 
1821   rtx src1 = SET_SRC (set1);
1822   ASSERT_EQ (PLUS, GET_CODE (src1));
1823 
1824   rtx src2 = SET_SRC (set2);
1825   ASSERT_EQ (PLUS, GET_CODE (src2));
1826 
1827   /* Both src1 and src2 refer to "(reg:SI %0)".
1828      Verify that we have pointer equality.  */
1829   rtx lhs1 = XEXP (src1, 0);
1830   rtx lhs2 = XEXP (src2, 0);
1831   ASSERT_EQ (lhs1, lhs2);
1832 
1833   /* Verify that the CFG was recreated. */
1834   ASSERT_TRUE (cfun);
1835   verify_three_block_rtl_cfg (cfun);
1836 }
1837 
1838 /* Verify that CODE_LABEL insns are loaded correctly.  */
1839 
1840 static void
test_loading_labels()1841 test_loading_labels ()
1842 {
1843   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("example-labels.rtl"));
1844 
1845   rtx_insn *insn_100 = get_insn_by_uid (100);
1846   ASSERT_EQ (CODE_LABEL, GET_CODE (insn_100));
1847   ASSERT_EQ (100, INSN_UID (insn_100));
1848   ASSERT_EQ (NULL, LABEL_NAME (insn_100));
1849   ASSERT_EQ (0, LABEL_NUSES (insn_100));
1850   ASSERT_EQ (30, CODE_LABEL_NUMBER (insn_100));
1851 
1852   rtx_insn *insn_200 = get_insn_by_uid (200);
1853   ASSERT_EQ (CODE_LABEL, GET_CODE (insn_200));
1854   ASSERT_EQ (200, INSN_UID (insn_200));
1855   ASSERT_STREQ ("some_label_name", LABEL_NAME (insn_200));
1856   ASSERT_EQ (0, LABEL_NUSES (insn_200));
1857   ASSERT_EQ (40, CODE_LABEL_NUMBER (insn_200));
1858 
1859   /* Ensure that the presence of CODE_LABEL_NUMBER == 40
1860      means that the next label num to be handed out will be 41.  */
1861   ASSERT_EQ (41, max_label_num ());
1862 
1863   /* Ensure that label names read from a dump are GC-managed
1864      and are found through the insn.  */
1865   forcibly_ggc_collect ();
1866   ASSERT_TRUE (ggc_marked_p (insn_200));
1867   ASSERT_TRUE (ggc_marked_p (LABEL_NAME (insn_200)));
1868 }
1869 
1870 /* Verify that the loader copes with an insn with a mode.  */
1871 
1872 static void
test_loading_insn_with_mode()1873 test_loading_insn_with_mode ()
1874 {
1875   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("insn-with-mode.rtl"));
1876   rtx_insn *insn = get_insns ();
1877   ASSERT_EQ (INSN, GET_CODE (insn));
1878 
1879   /* Verify that the "TI" mode was set from "insn:TI".  */
1880   ASSERT_EQ (TImode, GET_MODE (insn));
1881 }
1882 
1883 /* Verify that the loader copes with a jump_insn to a label_ref.  */
1884 
1885 static void
test_loading_jump_to_label_ref()1886 test_loading_jump_to_label_ref ()
1887 {
1888   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("jump-to-label-ref.rtl"));
1889 
1890   rtx_insn *jump_insn = get_insn_by_uid (1);
1891   ASSERT_EQ (JUMP_INSN, GET_CODE (jump_insn));
1892 
1893   rtx_insn *barrier = get_insn_by_uid (2);
1894   ASSERT_EQ (BARRIER, GET_CODE (barrier));
1895 
1896   rtx_insn *code_label = get_insn_by_uid (100);
1897   ASSERT_EQ (CODE_LABEL, GET_CODE (code_label));
1898 
1899   /* Verify the jump_insn. */
1900   ASSERT_EQ (4, BLOCK_FOR_INSN (jump_insn)->index);
1901   ASSERT_EQ (SET, GET_CODE (PATTERN (jump_insn)));
1902   /* Ensure that the "(pc)" is using the global singleton.  */
1903   ASSERT_RTX_PTR_EQ (pc_rtx, SET_DEST (PATTERN (jump_insn)));
1904   rtx label_ref = SET_SRC (PATTERN (jump_insn));
1905   ASSERT_EQ (LABEL_REF, GET_CODE (label_ref));
1906   ASSERT_EQ (code_label, label_ref_label (label_ref));
1907   ASSERT_EQ (code_label, JUMP_LABEL (jump_insn));
1908 
1909   /* Verify the code_label. */
1910   ASSERT_EQ (5, BLOCK_FOR_INSN (code_label)->index);
1911   ASSERT_EQ (NULL, LABEL_NAME (code_label));
1912   ASSERT_EQ (1, LABEL_NUSES (code_label));
1913 
1914   /* Verify the generated CFG.  */
1915 
1916   /* Locate blocks.  */
1917   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
1918   ASSERT_TRUE (entry != NULL);
1919   ASSERT_EQ (ENTRY_BLOCK, entry->index);
1920 
1921   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (cfun);
1922   ASSERT_TRUE (exit != NULL);
1923   ASSERT_EQ (EXIT_BLOCK, exit->index);
1924 
1925   basic_block bb4 = (*cfun->cfg->x_basic_block_info)[4];
1926   basic_block bb5 = (*cfun->cfg->x_basic_block_info)[5];
1927   ASSERT_EQ (4, bb4->index);
1928   ASSERT_EQ (5, bb5->index);
1929 
1930   /* Entry block.  */
1931   ASSERT_EQ (NULL, entry->preds);
1932   ASSERT_EQ (1, entry->succs->length ());
1933   ASSERT_EDGE ((*entry->succs)[0], 0, 4, EDGE_FALLTHRU);
1934 
1935   /* bb4.  */
1936   ASSERT_EQ (1, bb4->preds->length ());
1937   ASSERT_EDGE ((*bb4->preds)[0], 0, 4, EDGE_FALLTHRU);
1938   ASSERT_EQ (1, bb4->succs->length ());
1939   ASSERT_EDGE ((*bb4->succs)[0], 4, 5, 0x0);
1940 
1941   /* bb5.  */
1942   ASSERT_EQ (1, bb5->preds->length ());
1943   ASSERT_EDGE ((*bb5->preds)[0], 4, 5, 0x0);
1944   ASSERT_EQ (1, bb5->succs->length ());
1945   ASSERT_EDGE ((*bb5->succs)[0], 5, 1, EDGE_FALLTHRU);
1946 
1947   /* Exit block.  */
1948   ASSERT_EQ (1, exit->preds->length ());
1949   ASSERT_EDGE ((*exit->preds)[0], 5, 1, EDGE_FALLTHRU);
1950   ASSERT_EQ (NULL, exit->succs);
1951 }
1952 
1953 /* Verify that the loader copes with a jump_insn to a label_ref
1954    marked "return".  */
1955 
1956 static void
test_loading_jump_to_return()1957 test_loading_jump_to_return ()
1958 {
1959   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("jump-to-return.rtl"));
1960 
1961   rtx_insn *jump_insn = get_insn_by_uid (1);
1962   ASSERT_EQ (JUMP_INSN, GET_CODE (jump_insn));
1963   ASSERT_RTX_PTR_EQ (ret_rtx, JUMP_LABEL (jump_insn));
1964 }
1965 
1966 /* Verify that the loader copes with a jump_insn to a label_ref
1967    marked "simple_return".  */
1968 
1969 static void
test_loading_jump_to_simple_return()1970 test_loading_jump_to_simple_return ()
1971 {
1972   rtl_dump_test t (SELFTEST_LOCATION,
1973 		   locate_file ("jump-to-simple-return.rtl"));
1974 
1975   rtx_insn *jump_insn = get_insn_by_uid (1);
1976   ASSERT_EQ (JUMP_INSN, GET_CODE (jump_insn));
1977   ASSERT_RTX_PTR_EQ (simple_return_rtx, JUMP_LABEL (jump_insn));
1978 }
1979 
1980 /* Verify that the loader copes with a NOTE_INSN_BASIC_BLOCK.  */
1981 
1982 static void
test_loading_note_insn_basic_block()1983 test_loading_note_insn_basic_block ()
1984 {
1985   rtl_dump_test t (SELFTEST_LOCATION,
1986 		   locate_file ("note_insn_basic_block.rtl"));
1987 
1988   rtx_insn *note = get_insn_by_uid (1);
1989   ASSERT_EQ (NOTE, GET_CODE (note));
1990   ASSERT_EQ (2, BLOCK_FOR_INSN (note)->index);
1991 
1992   ASSERT_EQ (NOTE_INSN_BASIC_BLOCK, NOTE_KIND (note));
1993   ASSERT_EQ (2, NOTE_BASIC_BLOCK (note)->index);
1994   ASSERT_EQ (BASIC_BLOCK_FOR_FN (cfun, 2), NOTE_BASIC_BLOCK (note));
1995 }
1996 
1997 /* Verify that the loader copes with a NOTE_INSN_DELETED.  */
1998 
1999 static void
test_loading_note_insn_deleted()2000 test_loading_note_insn_deleted ()
2001 {
2002   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("note-insn-deleted.rtl"));
2003 
2004   rtx_insn *note = get_insn_by_uid (1);
2005   ASSERT_EQ (NOTE, GET_CODE (note));
2006   ASSERT_EQ (NOTE_INSN_DELETED, NOTE_KIND (note));
2007 }
2008 
2009 /* Verify that the const_int values are consolidated, since
2010    pointer equality corresponds to value equality.
2011    TODO: do this for all in CASE_CONST_UNIQUE.  */
2012 
2013 static void
test_loading_const_int()2014 test_loading_const_int ()
2015 {
2016   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("const-int.rtl"));
2017 
2018   /* Verify that const_int values below MAX_SAVED_CONST_INT use
2019      the global values.  */
2020   ASSERT_EQ (const0_rtx, SET_SRC (PATTERN (get_insn_by_uid (1))));
2021   ASSERT_EQ (const1_rtx, SET_SRC (PATTERN (get_insn_by_uid (2))));
2022   ASSERT_EQ (constm1_rtx, SET_SRC (PATTERN (get_insn_by_uid (3))));
2023 
2024   /* Verify that other const_int values are consolidated. */
2025   rtx int256 = gen_rtx_CONST_INT (SImode, 256);
2026   ASSERT_EQ (int256, SET_SRC (PATTERN (get_insn_by_uid (4))));
2027 }
2028 
2029 /* Verify that the loader copes with a SYMBOL_REF.  */
2030 
2031 static void
test_loading_symbol_ref()2032 test_loading_symbol_ref ()
2033 {
2034   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("symbol-ref.rtl"));
2035 
2036   rtx_insn *insn = get_insns ();
2037 
2038   rtx high = SET_SRC (PATTERN (insn));
2039   ASSERT_EQ (HIGH, GET_CODE (high));
2040 
2041   rtx symbol_ref = XEXP (high, 0);
2042   ASSERT_EQ (SYMBOL_REF, GET_CODE (symbol_ref));
2043 
2044   /* Verify that "[flags 0xc0]" was parsed.  */
2045   ASSERT_EQ (0xc0, SYMBOL_REF_FLAGS (symbol_ref));
2046   /* TODO: we don't yet load SYMBOL_REF_DECL.  */
2047 }
2048 
2049 /* Verify that the loader can rebuild a CFG.  */
2050 
2051 static void
test_loading_cfg()2052 test_loading_cfg ()
2053 {
2054   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("cfg-test.rtl"));
2055 
2056   ASSERT_STREQ ("cfg_test", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
2057 
2058   ASSERT_TRUE (cfun);
2059 
2060   ASSERT_TRUE (cfun->cfg != NULL);
2061   ASSERT_EQ (6, n_basic_blocks_for_fn (cfun));
2062   ASSERT_EQ (6, n_edges_for_fn (cfun));
2063 
2064   /* The "fake" basic blocks.  */
2065   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
2066   ASSERT_TRUE (entry != NULL);
2067   ASSERT_EQ (ENTRY_BLOCK, entry->index);
2068 
2069   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (cfun);
2070   ASSERT_TRUE (exit != NULL);
2071   ASSERT_EQ (EXIT_BLOCK, exit->index);
2072 
2073   /* The "real" basic blocks.  */
2074   basic_block bb2 = (*cfun->cfg->x_basic_block_info)[2];
2075   basic_block bb3 = (*cfun->cfg->x_basic_block_info)[3];
2076   basic_block bb4 = (*cfun->cfg->x_basic_block_info)[4];
2077   basic_block bb5 = (*cfun->cfg->x_basic_block_info)[5];
2078 
2079   ASSERT_EQ (2, bb2->index);
2080   ASSERT_EQ (3, bb3->index);
2081   ASSERT_EQ (4, bb4->index);
2082   ASSERT_EQ (5, bb5->index);
2083 
2084   /* Verify connectivity.  */
2085 
2086   /* Entry block.  */
2087   ASSERT_EQ (NULL, entry->preds);
2088   ASSERT_EQ (1, entry->succs->length ());
2089   ASSERT_EDGE ((*entry->succs)[0], 0, 2, EDGE_FALLTHRU);
2090 
2091   /* bb2.  */
2092   ASSERT_EQ (1, bb2->preds->length ());
2093   ASSERT_EDGE ((*bb2->preds)[0], 0, 2, EDGE_FALLTHRU);
2094   ASSERT_EQ (2, bb2->succs->length ());
2095   ASSERT_EDGE ((*bb2->succs)[0], 2, 3, EDGE_TRUE_VALUE);
2096   ASSERT_EDGE ((*bb2->succs)[1], 2, 4, EDGE_FALSE_VALUE);
2097 
2098   /* bb3.  */
2099   ASSERT_EQ (1, bb3->preds->length ());
2100   ASSERT_EDGE ((*bb3->preds)[0], 2, 3, EDGE_TRUE_VALUE);
2101   ASSERT_EQ (1, bb3->succs->length ());
2102   ASSERT_EDGE ((*bb3->succs)[0], 3, 5, EDGE_FALLTHRU);
2103 
2104   /* bb4.  */
2105   ASSERT_EQ (1, bb4->preds->length ());
2106   ASSERT_EDGE ((*bb4->preds)[0], 2, 4, EDGE_FALSE_VALUE);
2107   ASSERT_EQ (1, bb4->succs->length ());
2108   ASSERT_EDGE ((*bb4->succs)[0], 4, 5, EDGE_FALLTHRU);
2109 
2110   /* bb5.  */
2111   ASSERT_EQ (2, bb5->preds->length ());
2112   ASSERT_EDGE ((*bb5->preds)[0], 3, 5, EDGE_FALLTHRU);
2113   ASSERT_EDGE ((*bb5->preds)[1], 4, 5, EDGE_FALLTHRU);
2114   ASSERT_EQ (1, bb5->succs->length ());
2115   ASSERT_EDGE ((*bb5->succs)[0], 5, 1, EDGE_FALLTHRU);
2116 
2117   /* Exit block.  */
2118   ASSERT_EQ (1, exit->preds->length ());
2119   ASSERT_EDGE ((*exit->preds)[0], 5, 1, EDGE_FALLTHRU);
2120   ASSERT_EQ (NULL, exit->succs);
2121 }
2122 
2123 /* Verify that the loader copes with sparse block indices.
2124    This testcase loads a file with a "(block 42)".  */
2125 
2126 static void
test_loading_bb_index()2127 test_loading_bb_index ()
2128 {
2129   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("bb-index.rtl"));
2130 
2131   ASSERT_STREQ ("test_bb_index", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
2132 
2133   ASSERT_TRUE (cfun);
2134 
2135   ASSERT_TRUE (cfun->cfg != NULL);
2136   ASSERT_EQ (3, n_basic_blocks_for_fn (cfun));
2137   ASSERT_EQ (43, basic_block_info_for_fn (cfun)->length ());
2138   ASSERT_EQ (2, n_edges_for_fn (cfun));
2139 
2140   ASSERT_EQ (NULL, (*cfun->cfg->x_basic_block_info)[41]);
2141   basic_block bb42 = (*cfun->cfg->x_basic_block_info)[42];
2142   ASSERT_NE (NULL, bb42);
2143   ASSERT_EQ (42, bb42->index);
2144 }
2145 
2146 /* Verify that function_reader::handle_any_trailing_information correctly
2147    parses all the possible items emitted for a MEM.  */
2148 
2149 static void
test_loading_mem()2150 test_loading_mem ()
2151 {
2152   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("mem.rtl"));
2153 
2154   ASSERT_STREQ ("test_mem", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
2155   ASSERT_TRUE (cfun);
2156 
2157   /* Verify parsing of "[42 i+17 S8 A128 AS5]".  */
2158   rtx_insn *insn_1 = get_insn_by_uid (1);
2159   rtx set1 = single_set (insn_1);
2160   rtx mem1 = SET_DEST (set1);
2161   ASSERT_EQ (42, MEM_ALIAS_SET (mem1));
2162   /* "+17".  */
2163   ASSERT_TRUE (MEM_OFFSET_KNOWN_P (mem1));
2164   ASSERT_KNOWN_EQ (17, MEM_OFFSET (mem1));
2165   /* "S8".  */
2166   ASSERT_KNOWN_EQ (8, MEM_SIZE (mem1));
2167   /* "A128.  */
2168   ASSERT_EQ (128, MEM_ALIGN (mem1));
2169   /* "AS5.  */
2170   ASSERT_EQ (5, MEM_ADDR_SPACE (mem1));
2171 
2172   /* Verify parsing of "43 i+18 S9 AS6"
2173      (an address space without an alignment).  */
2174   rtx_insn *insn_2 = get_insn_by_uid (2);
2175   rtx set2 = single_set (insn_2);
2176   rtx mem2 = SET_DEST (set2);
2177   ASSERT_EQ (43, MEM_ALIAS_SET (mem2));
2178   /* "+18".  */
2179   ASSERT_TRUE (MEM_OFFSET_KNOWN_P (mem2));
2180   ASSERT_KNOWN_EQ (18, MEM_OFFSET (mem2));
2181   /* "S9".  */
2182   ASSERT_KNOWN_EQ (9, MEM_SIZE (mem2));
2183   /* "AS6.  */
2184   ASSERT_EQ (6, MEM_ADDR_SPACE (mem2));
2185 }
2186 
2187 /* Verify that "repeated xN" is read correctly.  */
2188 
2189 static void
test_loading_repeat()2190 test_loading_repeat ()
2191 {
2192   rtl_dump_test t (SELFTEST_LOCATION, locate_file ("repeat.rtl"));
2193 
2194   rtx_insn *insn_1 = get_insn_by_uid (1);
2195   ASSERT_EQ (PARALLEL, GET_CODE (PATTERN (insn_1)));
2196   ASSERT_EQ (64, XVECLEN (PATTERN (insn_1), 0));
2197   for (int i = 0; i < 64; i++)
2198     ASSERT_EQ (const0_rtx, XVECEXP (PATTERN (insn_1), 0, i));
2199 }
2200 
2201 /* Run all of the selftests within this file.  */
2202 
2203 void
read_rtl_function_c_tests()2204 read_rtl_function_c_tests ()
2205 {
2206   test_edge_flags ();
2207   test_parsing_regnos ();
2208   test_loading_dump_fragment_1 ();
2209   test_loading_dump_fragment_2 ();
2210   test_loading_labels ();
2211   test_loading_insn_with_mode ();
2212   test_loading_jump_to_label_ref ();
2213   test_loading_jump_to_return ();
2214   test_loading_jump_to_simple_return ();
2215   test_loading_note_insn_basic_block ();
2216   test_loading_note_insn_deleted ();
2217   test_loading_const_int ();
2218   test_loading_symbol_ref ();
2219   test_loading_cfg ();
2220   test_loading_bb_index ();
2221   test_loading_mem ();
2222   test_loading_repeat ();
2223 }
2224 
2225 } // namespace selftest
2226 
2227 #endif /* #if CHECKING_P */
2228