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