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