annotate gcc/read-rtl-function.c @ 111:04ced10e8804

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