Line data Source code
1 : /* Print RTL for GCC.
2 : Copyright (C) 1987-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation; either version 3, or (at your option) any later
9 : version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
20 : /* This file is compiled twice: once for the generator programs,
21 : once for the compiler. */
22 : #ifdef GENERATOR_FILE
23 : #include "bconfig.h"
24 : #else
25 : #include "config.h"
26 : #endif
27 :
28 : #include "system.h"
29 : #include "coretypes.h"
30 : #include "tm.h"
31 : #include "rtl.h"
32 :
33 : /* These headers all define things which are not available in
34 : generator programs. */
35 : #ifndef GENERATOR_FILE
36 : #include "alias.h"
37 : #include "tree.h"
38 : #include "basic-block.h"
39 : #include "print-tree.h"
40 : #include "flags.h"
41 : #include "predict.h"
42 : #include "function.h"
43 : #include "cfg.h"
44 : #include "diagnostic.h"
45 : #include "tree-pretty-print.h"
46 : #include "alloc-pool.h"
47 : #include "cselib.h"
48 : #include "dumpfile.h" /* for dump_flags */
49 : #include "dwarf2out.h"
50 : #include "pretty-print.h"
51 : #endif
52 :
53 : #include "dumpfile.h"
54 : #include "cfghooks.h"
55 : #include "print-rtl.h"
56 : #include "rtl-iter.h"
57 : #include "json.h"
58 :
59 : #include "custom-sarif-properties/cfg.h"
60 :
61 : /* Disable warnings about quoting issues in the pp_xxx calls below
62 : that (intentionally) don't follow GCC diagnostic conventions. */
63 : #if __GNUC__ >= 10
64 : # pragma GCC diagnostic push
65 : # pragma GCC diagnostic ignored "-Wformat-diag"
66 : #endif
67 :
68 : /* String printed at beginning of each RTL when it is dumped.
69 : This string is set to ASM_COMMENT_START when the RTL is dumped in
70 : the assembly output file. */
71 : const char *print_rtx_head = "";
72 :
73 : #ifdef GENERATOR_FILE
74 : /* These are defined from the .opt file when not used in generator
75 : programs. */
76 :
77 : /* Nonzero means suppress output of instruction numbers
78 : in debugging dumps.
79 : This must be defined here so that programs like gencodes can be linked. */
80 : int flag_dump_unnumbered = 0;
81 :
82 : /* Nonzero means suppress output of instruction numbers for previous
83 : and next insns in debugging dumps.
84 : This must be defined here so that programs like gencodes can be linked. */
85 : int flag_dump_unnumbered_links = 0;
86 : #endif
87 :
88 : /* Constructor for rtx_writer. */
89 :
90 301268 : rtx_writer::rtx_writer (FILE *outf, int ind, bool simple, bool compact,
91 : rtx_reuse_manager *reuse_manager ATTRIBUTE_UNUSED)
92 301268 : : m_outfile (outf), m_indent (ind), m_sawclose (false),
93 301268 : m_in_call_function_usage (false), m_simple (simple), m_compact (compact)
94 : #ifndef GENERATOR_FILE
95 301268 : , m_rtx_reuse_manager (reuse_manager)
96 : #endif
97 : {
98 301268 : }
99 :
100 : #ifndef GENERATOR_FILE
101 :
102 : /* rtx_reuse_manager's ctor. */
103 :
104 12 : rtx_reuse_manager::rtx_reuse_manager ()
105 12 : : m_next_id (0)
106 : {
107 12 : }
108 :
109 : /* Determine if X is of a kind suitable for dumping via reuse_rtx. */
110 :
111 : static bool
112 140 : uses_rtx_reuse_p (const_rtx x)
113 : {
114 140 : if (x == NULL)
115 : return false;
116 :
117 120 : switch (GET_CODE (x))
118 : {
119 : case DEBUG_EXPR:
120 : case VALUE:
121 : case SCRATCH:
122 : return true;
123 :
124 : /* We don't use reuse_rtx for consts. */
125 : CASE_CONST_UNIQUE:
126 : default:
127 : return false;
128 : }
129 : }
130 :
131 : /* Traverse X and its descendents, determining if we see any rtx more than
132 : once. Any rtx suitable for "reuse_rtx" that is seen more than once is
133 : assigned an ID. */
134 :
135 : void
136 52 : rtx_reuse_manager::preprocess (const_rtx x)
137 : {
138 52 : subrtx_iterator::array_type array;
139 192 : FOR_EACH_SUBRTX (iter, array, x, NONCONST)
140 260 : if (uses_rtx_reuse_p (*iter))
141 : {
142 28 : if (int *count = m_rtx_occurrence_count.get (*iter))
143 : {
144 12 : if (*(count++) == 1)
145 12 : m_rtx_reuse_ids.put (*iter, m_next_id++);
146 : }
147 : else
148 16 : m_rtx_occurrence_count.put (*iter, 1);
149 : }
150 52 : }
151 :
152 : /* Return true iff X has been assigned a reuse ID. If it has,
153 : and OUT is non-NULL, then write the reuse ID to *OUT. */
154 :
155 : bool
156 144 : rtx_reuse_manager::has_reuse_id (const_rtx x, int *out)
157 : {
158 144 : int *id = m_rtx_reuse_ids.get (x);
159 144 : if (id)
160 : {
161 40 : if (out)
162 40 : *out = *id;
163 : return true;
164 : }
165 : else
166 : return false;
167 : }
168 :
169 : /* Determine if set_seen_def has been called for the given reuse ID. */
170 :
171 : bool
172 32 : rtx_reuse_manager::seen_def_p (int reuse_id)
173 : {
174 32 : return bitmap_bit_p (m_defs_seen, reuse_id);
175 : }
176 :
177 : /* Record that the definition of the given reuse ID has been seen. */
178 :
179 : void
180 12 : rtx_reuse_manager::set_seen_def (int reuse_id)
181 : {
182 12 : bitmap_set_bit (m_defs_seen, reuse_id);
183 12 : }
184 :
185 : #endif /* #ifndef GENERATOR_FILE */
186 :
187 : #ifndef GENERATOR_FILE
188 : void
189 277440 : print_mem_expr (FILE *outfile, const_tree expr)
190 : {
191 277440 : fputc (' ', outfile);
192 277440 : print_generic_expr (outfile, const_cast<tree> (expr), dump_flags | TDF_SLIM);
193 277440 : }
194 : #endif
195 :
196 : /* Print X to FILE. */
197 :
198 : static void
199 110640 : print_poly_int (FILE *file, poly_int64 x)
200 : {
201 110640 : HOST_WIDE_INT const_x;
202 2621 : if (x.is_constant (&const_x))
203 108019 : fprintf (file, HOST_WIDE_INT_PRINT_DEC, const_x);
204 : else
205 : {
206 : fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC, x.coeffs[0]);
207 : for (int i = 1; i < NUM_POLY_INT_COEFFS; ++i)
208 : fprintf (file, ", " HOST_WIDE_INT_PRINT_DEC, x.coeffs[i]);
209 : fprintf (file, "]");
210 : }
211 0 : }
212 :
213 : /* Subroutine of print_rtx_operand for handling code '0'.
214 : 0 indicates a field for internal use that should not be printed.
215 : However there are various special cases, such as the third field
216 : of a NOTE, where it indicates that the field has several different
217 : valid contents. */
218 :
219 : void
220 301404 : rtx_writer::print_rtx_operand_code_0 (const_rtx in_rtx ATTRIBUTE_UNUSED,
221 : int idx ATTRIBUTE_UNUSED)
222 : {
223 : #ifndef GENERATOR_FILE
224 301404 : if (idx == 1 && GET_CODE (in_rtx) == SYMBOL_REF)
225 : {
226 33117 : int flags = SYMBOL_REF_FLAGS (in_rtx);
227 33117 : if (flags)
228 33055 : fprintf (m_outfile, " [flags %#x]", flags);
229 33117 : tree decl = SYMBOL_REF_DECL (in_rtx);
230 32798 : if (decl)
231 32796 : print_node_brief (m_outfile, "", decl, dump_flags);
232 : }
233 268287 : else if (idx == 3 && NOTE_P (in_rtx))
234 : {
235 85083 : switch (NOTE_KIND (in_rtx))
236 : {
237 286 : case NOTE_INSN_EH_REGION_BEG:
238 286 : case NOTE_INSN_EH_REGION_END:
239 286 : if (flag_dump_unnumbered)
240 286 : fprintf (m_outfile, " #");
241 : else
242 0 : fprintf (m_outfile, " %d", NOTE_EH_HANDLER (in_rtx));
243 286 : m_sawclose = true;
244 286 : break;
245 :
246 4 : case NOTE_INSN_BLOCK_BEG:
247 4 : case NOTE_INSN_BLOCK_END:
248 4 : dump_addr (m_outfile, " ", NOTE_BLOCK (in_rtx));
249 4 : m_sawclose = true;
250 4 : break;
251 :
252 36614 : case NOTE_INSN_BASIC_BLOCK:
253 36614 : {
254 36614 : basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
255 36614 : if (bb != 0)
256 36523 : fprintf (m_outfile, " [bb %d]", bb->index);
257 : break;
258 : }
259 :
260 38 : case NOTE_INSN_DELETED_LABEL:
261 38 : case NOTE_INSN_DELETED_DEBUG_LABEL:
262 38 : {
263 38 : const char *label = NOTE_DELETED_LABEL_NAME (in_rtx);
264 38 : if (label)
265 38 : fprintf (m_outfile, " (\"%s\")", label);
266 : else
267 0 : fprintf (m_outfile, " \"\"");
268 : }
269 : break;
270 :
271 76 : case NOTE_INSN_SWITCH_TEXT_SECTIONS:
272 76 : {
273 76 : basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
274 76 : if (bb != 0)
275 0 : fprintf (m_outfile, " [bb %d]", bb->index);
276 : break;
277 : }
278 :
279 1892 : case NOTE_INSN_VAR_LOCATION:
280 1892 : fputc (' ', m_outfile);
281 1892 : print_rtx (NOTE_VAR_LOCATION (in_rtx));
282 1892 : break;
283 :
284 301 : case NOTE_INSN_CFI:
285 301 : fputc ('\n', m_outfile);
286 301 : output_cfi_directive (m_outfile, NOTE_CFI (in_rtx));
287 301 : fputc ('\t', m_outfile);
288 301 : break;
289 :
290 738 : case NOTE_INSN_BEGIN_STMT:
291 738 : case NOTE_INSN_INLINE_ENTRY:
292 : #ifndef GENERATOR_FILE
293 738 : {
294 738 : expanded_location xloc
295 738 : = expand_location (NOTE_MARKER_LOCATION (in_rtx));
296 738 : fprintf (m_outfile, " %s:%i", xloc.file, xloc.line);
297 : }
298 : #endif
299 738 : break;
300 :
301 : default:
302 : break;
303 : }
304 : }
305 183204 : else if (idx == 7 && JUMP_P (in_rtx) && JUMP_LABEL (in_rtx) != NULL
306 22949 : && !m_compact)
307 : {
308 : /* Output the JUMP_LABEL reference. */
309 22949 : fprintf (m_outfile, "\n%s%*s -> ", print_rtx_head, m_indent * 2, "");
310 22949 : if (GET_CODE (JUMP_LABEL (in_rtx)) == RETURN)
311 0 : fprintf (m_outfile, "return");
312 22949 : else if (GET_CODE (JUMP_LABEL (in_rtx)) == SIMPLE_RETURN)
313 6282 : fprintf (m_outfile, "simple_return");
314 : else
315 16667 : fprintf (m_outfile, "%d", INSN_UID (JUMP_LABEL (in_rtx)));
316 : }
317 160255 : else if (idx == 0 && GET_CODE (in_rtx) == VALUE)
318 : {
319 1228 : cselib_val *val = CSELIB_VAL_PTR (in_rtx);
320 :
321 1228 : fprintf (m_outfile, " %u:%u", CSELIB_VAL_UID (in_rtx), val->hash);
322 1228 : dump_addr (m_outfile, " @", in_rtx);
323 1228 : dump_addr (m_outfile, "/", (void*)val);
324 1228 : }
325 2292 : else if (idx == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
326 : {
327 3944 : fprintf (m_outfile, " D#%i",
328 1972 : DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (in_rtx)));
329 : }
330 320 : else if (idx == 0 && GET_CODE (in_rtx) == ENTRY_VALUE)
331 : {
332 320 : m_indent += 2;
333 320 : if (!m_sawclose)
334 320 : fprintf (m_outfile, " ");
335 320 : print_rtx (ENTRY_VALUE_EXP (in_rtx));
336 320 : m_indent -= 2;
337 : }
338 : #endif
339 301404 : }
340 :
341 : /* Subroutine of print_rtx_operand for handling code 'e'.
342 : Also called by print_rtx_operand_code_u for handling code 'u'
343 : for LABEL_REFs when they don't reference a CODE_LABEL. */
344 :
345 : void
346 1420972 : rtx_writer::print_rtx_operand_code_e (const_rtx in_rtx, int idx)
347 : {
348 1420972 : m_indent += 2;
349 1420972 : if (idx == 6 && INSN_P (in_rtx))
350 : /* Put REG_NOTES on their own line. */
351 184274 : fprintf (m_outfile, "\n%s%*s",
352 : print_rtx_head, m_indent * 2, "");
353 1420972 : if (!m_sawclose)
354 959701 : fprintf (m_outfile, " ");
355 1420972 : if (idx == 7 && CALL_P (in_rtx))
356 : {
357 9663 : m_in_call_function_usage = true;
358 9663 : print_rtx (XEXP (in_rtx, idx));
359 9663 : m_in_call_function_usage = false;
360 : }
361 : else
362 1411309 : print_rtx (XEXP (in_rtx, idx));
363 1420972 : m_indent -= 2;
364 1420972 : }
365 :
366 : /* Subroutine of print_rtx_operand for handling codes 'E' and 'V'. */
367 :
368 : void
369 36371 : rtx_writer::print_rtx_operand_codes_E_and_V (const_rtx in_rtx, int idx)
370 : {
371 36371 : m_indent += 2;
372 36371 : if (m_sawclose)
373 : {
374 258 : fprintf (m_outfile, "\n%s%*s",
375 : print_rtx_head, m_indent * 2, "");
376 258 : m_sawclose = false;
377 : }
378 36371 : if (GET_CODE (in_rtx) == CONST_VECTOR
379 36371 : && !GET_MODE_NUNITS (GET_MODE (in_rtx)).is_constant ()
380 : && CONST_VECTOR_DUPLICATE_P (in_rtx))
381 : fprintf (m_outfile, " repeat");
382 36371 : fputs (" [", m_outfile);
383 36371 : if (XVEC (in_rtx, idx) != NULL)
384 : {
385 36371 : m_indent += 2;
386 36371 : if (XVECLEN (in_rtx, idx))
387 36228 : m_sawclose = true;
388 :
389 36371 : int barrier = XVECLEN (in_rtx, idx);
390 36371 : if (GET_CODE (in_rtx) == CONST_VECTOR
391 36371 : && !GET_MODE_NUNITS (GET_MODE (in_rtx)).is_constant ())
392 : barrier = CONST_VECTOR_NPATTERNS (in_rtx);
393 :
394 112438 : for (int j = 0; j < XVECLEN (in_rtx, idx); j++)
395 : {
396 76067 : int j1;
397 :
398 76067 : if (j == barrier)
399 : {
400 0 : fprintf (m_outfile, "\n%s%*s",
401 0 : print_rtx_head, m_indent * 2, "");
402 0 : if (!CONST_VECTOR_STEPPED_P (in_rtx))
403 0 : fprintf (m_outfile, "repeat [");
404 0 : else if (CONST_VECTOR_NPATTERNS (in_rtx) == 1)
405 0 : fprintf (m_outfile, "stepped [");
406 : else
407 0 : fprintf (m_outfile, "stepped (interleave %d) [",
408 0 : CONST_VECTOR_NPATTERNS (in_rtx));
409 0 : m_indent += 2;
410 : }
411 :
412 76067 : print_rtx (XVECEXP (in_rtx, idx, j));
413 76067 : int limit = MIN (barrier, XVECLEN (in_rtx, idx));
414 78550 : for (j1 = j + 1; j1 < limit; j1++)
415 42322 : if (XVECEXP (in_rtx, idx, j) != XVECEXP (in_rtx, idx, j1))
416 : break;
417 :
418 76067 : if (j1 != j + 1)
419 : {
420 393 : fprintf (m_outfile, " repeated x%i", j1 - j);
421 393 : j = j1 - 1;
422 : }
423 : }
424 :
425 36371 : if (barrier < XVECLEN (in_rtx, idx))
426 : {
427 0 : m_indent -= 2;
428 0 : fprintf (m_outfile, "\n%s%*s]", print_rtx_head, m_indent * 2, "");
429 : }
430 :
431 36371 : m_indent -= 2;
432 : }
433 36371 : if (m_sawclose)
434 36228 : fprintf (m_outfile, "\n%s%*s", print_rtx_head, m_indent * 2, "");
435 :
436 36371 : fputs ("]", m_outfile);
437 36371 : m_sawclose = true;
438 36371 : m_indent -= 2;
439 36371 : }
440 :
441 : /* Subroutine of print_rtx_operand for handling code 'L'. */
442 :
443 : void
444 184564 : rtx_writer::print_rtx_operand_code_L (const_rtx in_rtx, int idx)
445 : {
446 184564 : if (idx == 4 && INSN_P (in_rtx))
447 : {
448 : #ifndef GENERATOR_FILE
449 184298 : const rtx_insn *in_insn = as_a <const rtx_insn *> (in_rtx);
450 :
451 : /* Pretty-print insn locations. Ignore scoping as it is mostly
452 : redundant with line number information and do not print anything
453 : when there is no location information available. */
454 184298 : if (INSN_HAS_LOCATION (in_insn))
455 : {
456 146225 : expanded_location xloc = insn_location (in_insn);
457 146225 : fprintf (m_outfile, " \"%s\":%i:%i", xloc.file, xloc.line,
458 : xloc.column);
459 146225 : if ((dump_flags & TDF_COMPARE_DEBUG) == 0)
460 86605 : if (int discriminator = insn_discriminator (in_insn))
461 34778 : fprintf (m_outfile, " discrim %d", discriminator);
462 : }
463 : #endif
464 : }
465 266 : else if (idx == 6 && GET_CODE (in_rtx) == ASM_OPERANDS)
466 : {
467 : #ifndef GENERATOR_FILE
468 129 : if (ASM_OPERANDS_SOURCE_LOCATION (in_rtx) != UNKNOWN_LOCATION)
469 101 : fprintf (m_outfile, " %s:%i",
470 101 : LOCATION_FILE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)),
471 202 : LOCATION_LINE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)));
472 : #endif
473 : }
474 137 : else if (idx == 1 && GET_CODE (in_rtx) == ASM_INPUT)
475 : {
476 : #ifndef GENERATOR_FILE
477 137 : if (ASM_INPUT_SOURCE_LOCATION (in_rtx) != UNKNOWN_LOCATION)
478 109 : fprintf (m_outfile, " %s:%i",
479 109 : LOCATION_FILE (ASM_INPUT_SOURCE_LOCATION (in_rtx)),
480 218 : LOCATION_LINE (ASM_INPUT_SOURCE_LOCATION (in_rtx)));
481 : #endif
482 : }
483 : else
484 0 : gcc_unreachable ();
485 184564 : }
486 :
487 : /* Subroutine of print_rtx_operand for handling code 'i'. */
488 :
489 : void
490 311462 : rtx_writer::print_rtx_operand_code_i (const_rtx in_rtx, int idx)
491 : {
492 311462 : if (idx == 5 && NOTE_P (in_rtx))
493 : {
494 : /* This field is only used for NOTE_INSN_DELETED_LABEL, and
495 : other times often contains garbage from INSN->NOTE death. */
496 85083 : if (NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_LABEL
497 85083 : || NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_DEBUG_LABEL)
498 38 : fprintf (m_outfile, " %d", XINT (in_rtx, idx));
499 : }
500 : #if !defined(GENERATOR_FILE) && NUM_UNSPECV_VALUES > 0
501 226379 : else if (idx == 1
502 4240 : && GET_CODE (in_rtx) == UNSPEC_VOLATILE
503 2896 : && XINT (in_rtx, 1) >= 0
504 2896 : && XINT (in_rtx, 1) < NUM_UNSPECV_VALUES)
505 2896 : fprintf (m_outfile, " %s", unspecv_strings[XINT (in_rtx, 1)]);
506 : #endif
507 : #if !defined(GENERATOR_FILE) && NUM_UNSPEC_VALUES > 0
508 1344 : else if (idx == 1
509 1344 : && (GET_CODE (in_rtx) == UNSPEC
510 : #if !(NUM_UNSPECV_VALUES > 0)
511 : // Only accept unspec_volatiles, if there's no unspecv enum.
512 : || GET_CODE (in_rtx) == UNSPEC_VOLATILE
513 : #endif
514 : || false)
515 1344 : && XINT (in_rtx, 1) >= 0
516 1344 : && XINT (in_rtx, 1) < NUM_UNSPEC_VALUES)
517 1344 : fprintf (m_outfile, " %s", unspec_strings[XINT (in_rtx, 1)]);
518 : #endif
519 : else
520 : {
521 222139 : int value = XINT (in_rtx, idx);
522 222139 : const char *name;
523 222139 : int is_insn = INSN_P (in_rtx);
524 :
525 : /* Don't print INSN_CODEs in compact mode. */
526 222139 : if (m_compact && is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, idx))
527 : {
528 24 : m_sawclose = false;
529 24 : return;
530 : }
531 :
532 222115 : if (flag_dump_unnumbered
533 82738 : && (is_insn || NOTE_P (in_rtx)))
534 73731 : fputc ('#', m_outfile);
535 : else
536 148384 : fprintf (m_outfile, " %d", value);
537 :
538 193937 : if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, idx)
539 184274 : && XINT (in_rtx, idx) >= 0
540 378711 : && (name = get_insn_name (XINT (in_rtx, idx))) != NULL)
541 156596 : fprintf (m_outfile, " {%s}", name);
542 222115 : m_sawclose = false;
543 : }
544 : }
545 :
546 : /* Subroutine of print_rtx_operand for handling code 'r'. */
547 :
548 : void
549 457047 : rtx_writer::print_rtx_operand_code_r (const_rtx in_rtx)
550 : {
551 457047 : int is_insn = INSN_P (in_rtx);
552 457047 : unsigned int regno = REGNO (in_rtx);
553 :
554 : #ifndef GENERATOR_FILE
555 : /* For hard registers and virtuals, always print the
556 : regno, except in compact mode. */
557 457047 : if (regno <= LAST_VIRTUAL_REGISTER && !m_compact)
558 351739 : fprintf (m_outfile, " %d", regno);
559 351783 : if (regno < FIRST_PSEUDO_REGISTER)
560 350919 : fprintf (m_outfile, " %s", reg_names[regno]);
561 106128 : else if (regno <= LAST_VIRTUAL_REGISTER)
562 : {
563 864 : if (regno == VIRTUAL_INCOMING_ARGS_REGNUM)
564 4 : fprintf (m_outfile, " virtual-incoming-args");
565 : else if (regno == VIRTUAL_STACK_VARS_REGNUM)
566 777 : fprintf (m_outfile, " virtual-stack-vars");
567 : else if (regno == VIRTUAL_STACK_DYNAMIC_REGNUM)
568 17 : fprintf (m_outfile, " virtual-stack-dynamic");
569 : else if (regno == VIRTUAL_OUTGOING_ARGS_REGNUM)
570 6 : fprintf (m_outfile, " virtual-outgoing-args");
571 : else if (regno == VIRTUAL_CFA_REGNUM)
572 4 : fprintf (m_outfile, " virtual-cfa");
573 56 : else if (regno == VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM)
574 56 : fprintf (m_outfile, " virtual-preferred-stack-boundary");
575 : else
576 : fprintf (m_outfile, " virtual-reg-%d", regno-FIRST_VIRTUAL_REGISTER);
577 : }
578 : else
579 : #endif
580 105264 : if (flag_dump_unnumbered && is_insn)
581 0 : fputc ('#', m_outfile);
582 105264 : else if (m_compact)
583 : {
584 : /* In compact mode, print pseudos with '< and '>' wrapping the regno,
585 : offsetting it by (LAST_VIRTUAL_REGISTER + 1), so that the
586 : first non-virtual pseudo is dumped as "<0>". */
587 24 : gcc_assert (regno > LAST_VIRTUAL_REGISTER);
588 24 : fprintf (m_outfile, " <%d>", regno - (LAST_VIRTUAL_REGISTER + 1));
589 : }
590 : else
591 105240 : fprintf (m_outfile, " %d", regno);
592 :
593 : #ifndef GENERATOR_FILE
594 457047 : if (REG_ATTRS (in_rtx))
595 : {
596 220198 : fputs (" [", m_outfile);
597 220198 : if (regno != ORIGINAL_REGNO (in_rtx))
598 113894 : fprintf (m_outfile, "orig:%i", ORIGINAL_REGNO (in_rtx));
599 220198 : if (REG_EXPR (in_rtx))
600 220024 : print_mem_expr (m_outfile, REG_EXPR (in_rtx));
601 :
602 220198 : if (maybe_ne (REG_OFFSET (in_rtx), 0))
603 : {
604 802 : fprintf (m_outfile, "+");
605 802 : print_poly_int (m_outfile, REG_OFFSET (in_rtx));
606 : }
607 220198 : fputs (" ]", m_outfile);
608 : }
609 457047 : if (regno != ORIGINAL_REGNO (in_rtx))
610 135359 : fprintf (m_outfile, " [%d]", ORIGINAL_REGNO (in_rtx));
611 : #endif
612 457047 : }
613 :
614 : /* Subroutine of print_rtx_operand for handling code 'u'. */
615 :
616 : void
617 610981 : rtx_writer::print_rtx_operand_code_u (const_rtx in_rtx, int idx)
618 : {
619 : /* Don't print insn UIDs for PREV/NEXT_INSN in compact mode. */
620 610981 : if (m_compact && INSN_CHAIN_CODE_P (GET_CODE (in_rtx)) && idx < 2)
621 : return;
622 :
623 610885 : if (XEXP (in_rtx, idx) != NULL)
624 : {
625 362366 : rtx sub = XEXP (in_rtx, idx);
626 362366 : enum rtx_code subc = GET_CODE (sub);
627 :
628 362366 : if (GET_CODE (in_rtx) == LABEL_REF)
629 : {
630 18234 : if (subc == NOTE
631 0 : && NOTE_KIND (sub) == NOTE_INSN_DELETED_LABEL)
632 : {
633 0 : if (flag_dump_unnumbered)
634 0 : fprintf (m_outfile, " [# deleted]");
635 : else
636 0 : fprintf (m_outfile, " [%d deleted]", INSN_UID (sub));
637 0 : m_sawclose = false;
638 0 : return;
639 : }
640 :
641 18234 : if (subc != CODE_LABEL)
642 : {
643 0 : print_rtx_operand_code_e (in_rtx, idx);
644 0 : return;
645 : }
646 : }
647 :
648 362366 : if (flag_dump_unnumbered
649 355961 : || (flag_dump_unnumbered_links && idx <= 1
650 0 : && (INSN_P (in_rtx) || NOTE_P (in_rtx)
651 0 : || LABEL_P (in_rtx) || BARRIER_P (in_rtx))))
652 6405 : fputs (" #", m_outfile);
653 : else
654 355961 : fprintf (m_outfile, " %d", INSN_UID (sub));
655 : }
656 : else
657 248519 : fputs (" 0", m_outfile);
658 610885 : m_sawclose = false;
659 : }
660 :
661 : /* Subroutine of print_rtx. Print operand IDX of IN_RTX. */
662 :
663 : void
664 3870336 : rtx_writer::print_rtx_operand (const_rtx in_rtx, int idx)
665 : {
666 3870336 : const char *format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
667 :
668 3870336 : switch (format_ptr[idx])
669 : {
670 0 : const char *str;
671 :
672 0 : case 'T':
673 0 : str = XTMPL (in_rtx, idx);
674 0 : goto string;
675 :
676 49639 : case 'S':
677 49639 : case 's':
678 49639 : str = XSTR (in_rtx, idx);
679 49639 : string:
680 :
681 49639 : if (str == 0)
682 15976 : fputs (" (nil)", m_outfile);
683 : else
684 33663 : fprintf (m_outfile, " (\"%s\")", str);
685 49639 : m_sawclose = true;
686 49639 : break;
687 :
688 301404 : case '0':
689 301404 : print_rtx_operand_code_0 (in_rtx, idx);
690 301404 : break;
691 :
692 1420972 : case 'e':
693 1420972 : print_rtx_operand_code_e (in_rtx, idx);
694 1420972 : break;
695 :
696 36371 : case 'E':
697 36371 : case 'V':
698 36371 : print_rtx_operand_codes_E_and_V (in_rtx, idx);
699 36371 : break;
700 :
701 124548 : case 'w':
702 124548 : if (! m_simple)
703 124548 : fprintf (m_outfile, " ");
704 124548 : fprintf (m_outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, idx));
705 124548 : if (! m_simple && !m_compact)
706 124528 : fprintf (m_outfile, " [" HOST_WIDE_INT_PRINT_HEX "]",
707 124528 : (unsigned HOST_WIDE_INT) XWINT (in_rtx, idx));
708 : break;
709 :
710 311462 : case 'i':
711 311462 : print_rtx_operand_code_i (in_rtx, idx);
712 311462 : break;
713 :
714 184564 : case 'L':
715 184564 : print_rtx_operand_code_L (in_rtx, idx);
716 184564 : break;
717 :
718 2621 : case 'p':
719 2621 : fprintf (m_outfile, " ");
720 2621 : print_poly_int (m_outfile, SUBREG_BYTE (in_rtx));
721 2621 : break;
722 :
723 457047 : case 'r':
724 457047 : print_rtx_operand_code_r (in_rtx);
725 457047 : break;
726 :
727 : /* Print NOTE_INSN names rather than integer codes. */
728 :
729 85083 : case 'n':
730 85083 : fprintf (m_outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, idx)));
731 85083 : m_sawclose = false;
732 85083 : break;
733 :
734 610981 : case 'u':
735 610981 : print_rtx_operand_code_u (in_rtx, idx);
736 610981 : break;
737 :
738 0 : case 't':
739 : #ifndef GENERATOR_FILE
740 0 : if (idx == 0 && GET_CODE (in_rtx) == DEBUG_IMPLICIT_PTR)
741 0 : print_mem_expr (m_outfile, DEBUG_IMPLICIT_PTR_DECL (in_rtx));
742 0 : else if (idx == 0 && GET_CODE (in_rtx) == DEBUG_PARAMETER_REF)
743 0 : print_mem_expr (m_outfile, DEBUG_PARAMETER_REF_DECL (in_rtx));
744 : else
745 0 : dump_addr (m_outfile, " ", XTREE (in_rtx, idx));
746 : #endif
747 : break;
748 :
749 0 : case '*':
750 0 : fputs (" Unknown", m_outfile);
751 0 : m_sawclose = false;
752 0 : break;
753 :
754 285644 : case 'B':
755 : /* Don't print basic block ids in compact mode. */
756 285644 : if (m_compact)
757 : break;
758 : #ifndef GENERATOR_FILE
759 285600 : if (XBBDEF (in_rtx, idx))
760 238313 : fprintf (m_outfile, " %i", XBBDEF (in_rtx, idx)->index);
761 : #endif
762 : break;
763 :
764 0 : default:
765 0 : gcc_unreachable ();
766 : }
767 3870336 : }
768 :
769 : /* Subroutine of rtx_writer::print_rtx.
770 : In compact mode, determine if operand IDX of IN_RTX is interesting
771 : to dump, or (if in a trailing position) it can be omitted. */
772 :
773 : bool
774 224 : rtx_writer::operand_has_default_value_p (const_rtx in_rtx, int idx)
775 : {
776 224 : const char *format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
777 :
778 224 : switch (format_ptr[idx])
779 : {
780 60 : case 'e':
781 60 : case 'u':
782 60 : return XEXP (in_rtx, idx) == NULL_RTX;
783 :
784 8 : case 's':
785 8 : return XSTR (in_rtx, idx) == NULL;
786 :
787 16 : case '0':
788 16 : switch (GET_CODE (in_rtx))
789 : {
790 4 : case JUMP_INSN:
791 : /* JUMP_LABELs are always omitted in compact mode, so treat
792 : any value here as omittable, so that earlier operands can
793 : potentially be omitted also. */
794 4 : return m_compact;
795 :
796 : default:
797 : return false;
798 :
799 : }
800 :
801 : default:
802 : return false;
803 : }
804 : }
805 :
806 : /* Print IN_RTX onto m_outfile. This is the recursive part of printing. */
807 :
808 : void
809 1807979 : rtx_writer::print_rtx (const_rtx in_rtx)
810 : {
811 1807979 : int idx = 0;
812 :
813 1807979 : if (m_sawclose)
814 : {
815 538431 : if (m_simple)
816 0 : fputc (' ', m_outfile);
817 : else
818 538431 : fprintf (m_outfile, "\n%s%*s", print_rtx_head, m_indent * 2, "");
819 538431 : m_sawclose = false;
820 : }
821 :
822 1807979 : if (in_rtx == 0)
823 : {
824 195480 : fputs ("(nil)", m_outfile);
825 195480 : m_sawclose = true;
826 195480 : return;
827 : }
828 1612499 : else if (GET_CODE (in_rtx) > NUM_RTX_CODE)
829 : {
830 0 : fprintf (m_outfile, "(??? bad code %d\n%s%*s)", GET_CODE (in_rtx),
831 0 : print_rtx_head, m_indent * 2, "");
832 0 : m_sawclose = true;
833 0 : return;
834 : }
835 :
836 1612499 : fputc ('(', m_outfile);
837 :
838 : /* Print name of expression code. */
839 :
840 : /* Handle reuse. */
841 : #ifndef GENERATOR_FILE
842 1612499 : if (m_rtx_reuse_manager)
843 : {
844 132 : int reuse_id;
845 132 : if (m_rtx_reuse_manager->has_reuse_id (in_rtx, &reuse_id))
846 : {
847 : /* Have we already seen the defn of this rtx? */
848 32 : if (m_rtx_reuse_manager->seen_def_p (reuse_id))
849 : {
850 20 : fprintf (m_outfile, "reuse_rtx %i)", reuse_id);
851 20 : m_sawclose = true;
852 20 : return;
853 : }
854 : else
855 : {
856 : /* First time we've seen this reused-rtx. */
857 12 : fprintf (m_outfile, "%i|", reuse_id);
858 12 : m_rtx_reuse_manager->set_seen_def (reuse_id);
859 : }
860 : }
861 : }
862 : #endif /* #ifndef GENERATOR_FILE */
863 :
864 : /* In compact mode, prefix the code of insns with "c",
865 : giving "cinsn", "cnote" etc. */
866 1612479 : if (m_compact && is_a <const rtx_insn *, const struct rtx_def> (in_rtx))
867 : {
868 : /* "ccode_label" is slightly awkward, so special-case it as
869 : just "clabel". */
870 48 : rtx_code code = GET_CODE (in_rtx);
871 48 : if (code == CODE_LABEL)
872 8 : fprintf (m_outfile, "clabel");
873 : else
874 40 : fprintf (m_outfile, "c%s", GET_RTX_NAME (code));
875 : }
876 1612431 : else if (m_simple && CONST_INT_P (in_rtx))
877 : ; /* no code. */
878 : else
879 1612431 : fprintf (m_outfile, "%s", GET_RTX_NAME (GET_CODE (in_rtx)));
880 :
881 1612479 : if (! m_simple)
882 : {
883 1611233 : if (RTX_FLAG (in_rtx, in_struct))
884 2234 : fputs ("/s", m_outfile);
885 :
886 1611233 : if (RTX_FLAG (in_rtx, volatil))
887 39431 : fputs ("/v", m_outfile);
888 :
889 1611233 : if (RTX_FLAG (in_rtx, unchanging))
890 3365 : fputs ("/u", m_outfile);
891 :
892 1611233 : if (RTX_FLAG (in_rtx, frame_related))
893 111381 : fputs ("/f", m_outfile);
894 :
895 1611233 : if (RTX_FLAG (in_rtx, jump))
896 923 : fputs ("/j", m_outfile);
897 :
898 1611233 : if (RTX_FLAG (in_rtx, call))
899 19933 : fputs ("/c", m_outfile);
900 :
901 1611233 : if (RTX_FLAG (in_rtx, return_val))
902 12602 : fputs ("/i", m_outfile);
903 :
904 : /* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */
905 1611233 : if ((GET_CODE (in_rtx) == EXPR_LIST
906 : || GET_CODE (in_rtx) == INSN_LIST
907 1611233 : || GET_CODE (in_rtx) == INT_LIST)
908 134629 : && (int)GET_MODE (in_rtx) < REG_NOTE_MAX
909 132412 : && !m_in_call_function_usage)
910 119861 : fprintf (m_outfile, ":%s",
911 119861 : GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
912 :
913 : /* For other rtl, print the mode if it's not VOID. */
914 1491372 : else if (GET_MODE (in_rtx) != VOIDmode)
915 764020 : fprintf (m_outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
916 :
917 : #ifndef GENERATOR_FILE
918 1611233 : if (GET_CODE (in_rtx) == VAR_LOCATION)
919 : {
920 6347 : if (TREE_CODE (PAT_VAR_LOCATION_DECL (in_rtx)) == STRING_CST)
921 0 : fputs (" <debug string placeholder>", m_outfile);
922 : else
923 6347 : print_mem_expr (m_outfile, PAT_VAR_LOCATION_DECL (in_rtx));
924 6347 : fputc (' ', m_outfile);
925 6347 : print_rtx (PAT_VAR_LOCATION_LOC (in_rtx));
926 6347 : if (PAT_VAR_LOCATION_STATUS (in_rtx)
927 : == VAR_INIT_STATUS_UNINITIALIZED)
928 0 : fprintf (m_outfile, " [uninit]");
929 6347 : m_sawclose = true;
930 6347 : idx = GET_RTX_LENGTH (VAR_LOCATION);
931 : }
932 : #endif
933 : }
934 :
935 : #ifndef GENERATOR_FILE
936 1612479 : if (CONST_DOUBLE_AS_FLOAT_P (in_rtx))
937 1612479 : idx = 5;
938 : #endif
939 :
940 : /* For insns, print the INSN_UID. */
941 1612479 : if (INSN_CHAIN_CODE_P (GET_CODE (in_rtx)))
942 : {
943 296343 : if (flag_dump_unnumbered)
944 119579 : fprintf (m_outfile, " #");
945 : else
946 176764 : fprintf (m_outfile, " %d", INSN_UID (in_rtx));
947 : }
948 :
949 : /* Determine which is the final operand to print.
950 : In compact mode, skip trailing operands that have the default values
951 : e.g. trailing "(nil)" values. */
952 1612479 : int limit = GET_RTX_LENGTH (GET_CODE (in_rtx));
953 1612479 : if (m_compact)
954 248 : while (limit > idx && operand_has_default_value_p (in_rtx, limit - 1))
955 : limit--;
956 :
957 : /* Get the format string and skip the first elements if we have handled
958 : them already. */
959 :
960 5482815 : for (; idx < limit; idx++)
961 3870336 : print_rtx_operand (in_rtx, idx);
962 :
963 1612479 : switch (GET_CODE (in_rtx))
964 : {
965 : #ifndef GENERATOR_FILE
966 70359 : case MEM:
967 70359 : if (UNLIKELY (final_insns_dump_p))
968 33947 : fprintf (m_outfile, " [");
969 : else
970 36412 : fprintf (m_outfile, " [" HOST_WIDE_INT_PRINT_DEC,
971 36412 : (HOST_WIDE_INT) MEM_ALIAS_SET (in_rtx));
972 :
973 81705 : if (MEM_EXPR (in_rtx))
974 50838 : print_mem_expr (m_outfile, MEM_EXPR (in_rtx));
975 : else
976 19521 : fputc (' ', m_outfile);
977 :
978 81705 : if (MEM_OFFSET_KNOWN_P (in_rtx))
979 : {
980 41250 : fprintf (m_outfile, "+");
981 41250 : print_poly_int (m_outfile, MEM_OFFSET (in_rtx));
982 : }
983 :
984 81705 : if (MEM_SIZE_KNOWN_P (in_rtx))
985 : {
986 65967 : fprintf (m_outfile, " S");
987 72923 : print_poly_int (m_outfile, MEM_SIZE (in_rtx));
988 : }
989 :
990 81705 : if (MEM_ALIGN (in_rtx) != 1)
991 70359 : fprintf (m_outfile, " A%u", MEM_ALIGN (in_rtx));
992 :
993 81705 : if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (in_rtx)))
994 68 : fprintf (m_outfile, " AS%u", MEM_ADDR_SPACE (in_rtx));
995 :
996 70359 : fputc (']', m_outfile);
997 70359 : break;
998 :
999 374 : case CONST_DOUBLE:
1000 374 : if (FLOAT_MODE_P (GET_MODE (in_rtx)))
1001 : {
1002 374 : char s[60];
1003 :
1004 374 : real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
1005 : sizeof (s), 0, 1);
1006 374 : fprintf (m_outfile, " %s", s);
1007 :
1008 374 : real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
1009 : sizeof (s), 0, 1);
1010 374 : fprintf (m_outfile, " [%s]", s);
1011 : }
1012 : break;
1013 :
1014 12 : case CONST_WIDE_INT:
1015 12 : fprintf (m_outfile, " ");
1016 12 : cwi_output_hex (m_outfile, in_rtx);
1017 12 : break;
1018 :
1019 0 : case CONST_POLY_INT:
1020 0 : fprintf (m_outfile, " [");
1021 0 : print_dec (CONST_POLY_INT_COEFFS (in_rtx)[0], m_outfile, SIGNED);
1022 0 : for (unsigned int i = 1; i < NUM_POLY_INT_COEFFS; ++i)
1023 : {
1024 : fprintf (m_outfile, ", ");
1025 : print_dec (CONST_POLY_INT_COEFFS (in_rtx)[i], m_outfile, SIGNED);
1026 : }
1027 0 : fprintf (m_outfile, "]");
1028 0 : break;
1029 : #endif
1030 :
1031 16131 : case CODE_LABEL:
1032 16131 : if (!m_compact)
1033 16123 : fprintf (m_outfile, " [%d uses]", LABEL_NUSES (in_rtx));
1034 16131 : switch (LABEL_KIND (in_rtx))
1035 : {
1036 : case LABEL_NORMAL: break;
1037 0 : case LABEL_STATIC_ENTRY: fputs (" [entry]", m_outfile); break;
1038 0 : case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", m_outfile); break;
1039 0 : case LABEL_WEAK_ENTRY: fputs (" [weak entry]", m_outfile); break;
1040 0 : default: gcc_unreachable ();
1041 : }
1042 : break;
1043 :
1044 : default:
1045 : break;
1046 : }
1047 :
1048 1612479 : fputc (')', m_outfile);
1049 1612479 : m_sawclose = true;
1050 : }
1051 :
1052 : /* Emit a closing parenthesis and newline. */
1053 :
1054 : void
1055 0 : rtx_writer::finish_directive ()
1056 : {
1057 0 : fprintf (m_outfile, ")\n");
1058 0 : m_sawclose = false;
1059 0 : }
1060 :
1061 : /* Print an rtx on the current line of FILE. Initially indent IND
1062 : characters. */
1063 :
1064 : void
1065 1627 : print_inline_rtx (FILE *outf, const_rtx x, int ind)
1066 : {
1067 1627 : rtx_writer w (outf, ind, false, false, NULL);
1068 1627 : w.print_rtx (x);
1069 1627 : }
1070 :
1071 : /* Call this function from the debugger to see what X looks like. */
1072 :
1073 : DEBUG_FUNCTION void
1074 0 : debug_rtx (const_rtx x)
1075 : {
1076 0 : rtx_writer w (stderr, 0, false, false, NULL);
1077 0 : w.print_rtx (x);
1078 0 : fprintf (stderr, "\n");
1079 0 : }
1080 :
1081 : /* Dump rtx REF. */
1082 :
1083 : DEBUG_FUNCTION void
1084 0 : debug (const rtx_def &ref)
1085 : {
1086 0 : debug_rtx (&ref);
1087 0 : }
1088 :
1089 : DEBUG_FUNCTION void
1090 0 : debug (const rtx_def *ptr)
1091 : {
1092 0 : if (ptr)
1093 0 : debug (*ptr);
1094 : else
1095 0 : fprintf (stderr, "<nil>\n");
1096 0 : }
1097 :
1098 : /* Like debug_rtx but with no newline, as debug_helper will add one.
1099 :
1100 : Note: No debug_slim(rtx_insn *) variant implemented, as this
1101 : function can serve for both rtx and rtx_insn. */
1102 :
1103 : static void
1104 0 : debug_slim (const_rtx x)
1105 : {
1106 0 : rtx_writer w (stderr, 0, false, false, NULL);
1107 0 : w.print_rtx (x);
1108 0 : }
1109 :
1110 0 : DEFINE_DEBUG_VEC (rtx_def *)
1111 0 : DEFINE_DEBUG_VEC (rtx_insn *)
1112 0 : DEFINE_DEBUG_HASH_SET (rtx_def *)
1113 0 : DEFINE_DEBUG_HASH_SET (rtx_insn *)
1114 :
1115 : /* Count of rtx's to print with debug_rtx_list.
1116 : This global exists because gdb user defined commands have no arguments. */
1117 :
1118 : DEBUG_VARIABLE int debug_rtx_count = 0; /* 0 is treated as equivalent to 1 */
1119 :
1120 : /* Call this function to print list from X on.
1121 :
1122 : N is a count of the rtx's to print. Positive values print from the specified
1123 : rtx_insn on. Negative values print a window around the rtx_insn.
1124 : EG: -5 prints 2 rtx_insn's on either side (in addition to the specified
1125 : rtx_insn). */
1126 :
1127 : DEBUG_FUNCTION void
1128 0 : debug_rtx_list (const rtx_insn *x, int n)
1129 : {
1130 0 : int i,count;
1131 0 : const rtx_insn *insn;
1132 :
1133 0 : count = n == 0 ? 1 : n < 0 ? -n : n;
1134 :
1135 : /* If we are printing a window, back up to the start. */
1136 :
1137 0 : if (n < 0)
1138 0 : for (i = count / 2; i > 0; i--)
1139 : {
1140 0 : if (PREV_INSN (x) == 0)
1141 : break;
1142 0 : x = PREV_INSN (x);
1143 : }
1144 :
1145 0 : for (i = count, insn = x; i > 0 && insn != 0; i--, insn = NEXT_INSN (insn))
1146 : {
1147 0 : debug_rtx (insn);
1148 0 : fprintf (stderr, "\n");
1149 : }
1150 0 : }
1151 :
1152 : /* Call this function to print an rtx_insn list from START to END
1153 : inclusive. */
1154 :
1155 : DEBUG_FUNCTION void
1156 0 : debug_rtx_range (const rtx_insn *start, const rtx_insn *end)
1157 : {
1158 0 : while (1)
1159 : {
1160 0 : debug_rtx (start);
1161 0 : fprintf (stderr, "\n");
1162 0 : if (!start || start == end)
1163 : break;
1164 0 : start = NEXT_INSN (start);
1165 : }
1166 0 : }
1167 :
1168 : /* Call this function to search an rtx_insn list to find one with insn uid UID,
1169 : and then call debug_rtx_list to print it, using DEBUG_RTX_COUNT.
1170 : The found insn is returned to enable further debugging analysis. */
1171 :
1172 : DEBUG_FUNCTION const rtx_insn *
1173 0 : debug_rtx_find (const rtx_insn *x, int uid)
1174 : {
1175 0 : while (x != 0 && INSN_UID (x) != uid)
1176 0 : x = NEXT_INSN (x);
1177 0 : if (x != 0)
1178 : {
1179 0 : debug_rtx_list (x, debug_rtx_count);
1180 0 : return x;
1181 : }
1182 : else
1183 : {
1184 0 : fprintf (stderr, "insn uid %d not found\n", uid);
1185 0 : return 0;
1186 : }
1187 : }
1188 :
1189 : /* External entry point for printing a chain of insns
1190 : starting with RTX_FIRST.
1191 : A blank line separates insns.
1192 :
1193 : If RTX_FIRST is not an insn, then it alone is printed, with no newline. */
1194 :
1195 : void
1196 4430 : rtx_writer::print_rtl (const_rtx rtx_first)
1197 : {
1198 4430 : const rtx_insn *tmp_rtx;
1199 :
1200 4430 : if (rtx_first == 0)
1201 : {
1202 8 : fputs (print_rtx_head, m_outfile);
1203 8 : fputs ("(nil)\n", m_outfile);
1204 : }
1205 : else
1206 4422 : switch (GET_CODE (rtx_first))
1207 : {
1208 426 : case INSN:
1209 426 : case JUMP_INSN:
1210 426 : case CALL_INSN:
1211 426 : case NOTE:
1212 426 : case CODE_LABEL:
1213 426 : case JUMP_TABLE_DATA:
1214 426 : case BARRIER:
1215 1945 : for (tmp_rtx = as_a <const rtx_insn *> (rtx_first);
1216 1945 : tmp_rtx != 0;
1217 1519 : tmp_rtx = NEXT_INSN (tmp_rtx))
1218 : {
1219 1519 : fputs (print_rtx_head, m_outfile);
1220 1519 : print_rtx (tmp_rtx);
1221 1519 : fprintf (m_outfile, "\n");
1222 : }
1223 : break;
1224 :
1225 3996 : default:
1226 3996 : fputs (print_rtx_head, m_outfile);
1227 3996 : print_rtx (rtx_first);
1228 : }
1229 4430 : }
1230 :
1231 : /* External entry point for printing a chain of insns
1232 : starting with RTX_FIRST onto file OUTF.
1233 : A blank line separates insns.
1234 :
1235 : If RTX_FIRST is not an insn, then it alone is printed, with no newline. */
1236 :
1237 : void
1238 3100 : print_rtl (FILE *outf, const_rtx rtx_first)
1239 : {
1240 3100 : rtx_writer w (outf, 0, false, false, NULL);
1241 3100 : w.print_rtl (rtx_first);
1242 3100 : }
1243 :
1244 : /* Like print_rtx, except specify a file. */
1245 :
1246 : void
1247 295207 : print_rtl_single (FILE *outf, const_rtx x)
1248 : {
1249 295207 : rtx_writer w (outf, 0, false, false, NULL);
1250 295207 : w.print_rtl_single_with_indent (x, 0);
1251 295207 : }
1252 :
1253 : /* Like print_rtl_single, except specify an indentation. */
1254 :
1255 : void
1256 295239 : rtx_writer::print_rtl_single_with_indent (const_rtx x, int ind)
1257 : {
1258 295239 : char *s_indent = (char *) alloca ((size_t) ind + 1);
1259 295239 : memset ((void *) s_indent, ' ', (size_t) ind);
1260 295239 : s_indent[ind] = '\0';
1261 295239 : fputs (s_indent, m_outfile);
1262 295239 : fputs (print_rtx_head, m_outfile);
1263 :
1264 295239 : int old_indent = m_indent;
1265 295239 : m_indent = ind;
1266 295239 : m_sawclose = false;
1267 295239 : print_rtx (x);
1268 295239 : putc ('\n', m_outfile);
1269 295239 : m_indent = old_indent;
1270 295239 : }
1271 :
1272 :
1273 : /* Like print_rtl except without all the detail; for example,
1274 : if RTX is a CONST_INT then print in decimal format. */
1275 :
1276 : void
1277 1230 : print_simple_rtl (FILE *outf, const_rtx x)
1278 : {
1279 1230 : rtx_writer w (outf, 0, true, false, NULL);
1280 1230 : w.print_rtl (x);
1281 1230 : }
1282 :
1283 : /* Print the elements of VEC to FILE. */
1284 :
1285 : void
1286 42 : print_rtx_insn_vec (FILE *file, const vec<rtx_insn *> &vec)
1287 : {
1288 42 : fputc('{', file);
1289 :
1290 42 : unsigned int len = vec.length ();
1291 44 : for (unsigned int i = 0; i < len; i++)
1292 : {
1293 2 : print_rtl_single (file, vec[i]);
1294 2 : if (i < len - 1)
1295 0 : fputs (", ", file);
1296 : }
1297 :
1298 42 : fputc ('}', file);
1299 42 : }
1300 :
1301 : #ifndef GENERATOR_FILE
1302 : /* The functions below try to print RTL in a form resembling assembler
1303 : mnemonics. Because this form is more concise than the "traditional" form
1304 : of RTL printing in Lisp-style, the form printed by this file is called
1305 : "slim". RTL dumps in slim format can be obtained by appending the "-slim"
1306 : option to -fdump-rtl-<pass>. Control flow graph output as a DOT file is
1307 : always printed in slim form.
1308 :
1309 : The normal interface to the functionality provided in this pretty-printer
1310 : is through the dump_*_slim functions to print to a stream, or via the
1311 : print_*_slim functions to print into a user's pretty-printer.
1312 :
1313 : It is also possible to obtain a string for a single pattern as a string
1314 : pointer, via str_pattern_slim, but this usage is discouraged. */
1315 :
1316 : /* This recognizes rtx'en classified as expressions. These are always
1317 : represent some action on values or results of other expression, that
1318 : may be stored in objects representing values. */
1319 :
1320 : static void
1321 5746 : print_exp (pretty_printer *pp, const_rtx x, int verbose)
1322 : {
1323 5746 : const char *st[4];
1324 5746 : const char *fun;
1325 5746 : rtx op[4];
1326 5746 : int i;
1327 :
1328 5746 : fun = (char *) 0;
1329 28730 : for (i = 0; i < 4; i++)
1330 : {
1331 22984 : st[i] = (char *) 0;
1332 22984 : op[i] = NULL_RTX;
1333 : }
1334 :
1335 5746 : switch (GET_CODE (x))
1336 : {
1337 2467 : case PLUS:
1338 2467 : op[0] = XEXP (x, 0);
1339 2467 : if (CONST_INT_P (XEXP (x, 1))
1340 1405 : && INTVAL (XEXP (x, 1)) < 0)
1341 : {
1342 694 : st[1] = "-";
1343 694 : op[1] = GEN_INT (-INTVAL (XEXP (x, 1)));
1344 : }
1345 : else
1346 : {
1347 1773 : st[1] = "+";
1348 1773 : op[1] = XEXP (x, 1);
1349 : }
1350 : break;
1351 0 : case LO_SUM:
1352 0 : op[0] = XEXP (x, 0);
1353 0 : st[1] = "+low(";
1354 0 : op[1] = XEXP (x, 1);
1355 0 : st[2] = ")";
1356 0 : break;
1357 175 : case MINUS:
1358 175 : op[0] = XEXP (x, 0);
1359 175 : st[1] = "-";
1360 175 : op[1] = XEXP (x, 1);
1361 175 : break;
1362 563 : case COMPARE:
1363 563 : fun = "cmp";
1364 563 : op[0] = XEXP (x, 0);
1365 563 : op[1] = XEXP (x, 1);
1366 563 : break;
1367 3 : case NEG:
1368 3 : st[0] = "-";
1369 3 : op[0] = XEXP (x, 0);
1370 3 : break;
1371 0 : case FMA:
1372 0 : st[0] = "{";
1373 0 : op[0] = XEXP (x, 0);
1374 0 : st[1] = "*";
1375 0 : op[1] = XEXP (x, 1);
1376 0 : st[2] = "+";
1377 0 : op[2] = XEXP (x, 2);
1378 0 : st[3] = "}";
1379 0 : break;
1380 528 : case MULT:
1381 528 : op[0] = XEXP (x, 0);
1382 528 : st[1] = "*";
1383 528 : op[1] = XEXP (x, 1);
1384 528 : break;
1385 2 : case DIV:
1386 2 : op[0] = XEXP (x, 0);
1387 2 : st[1] = "/";
1388 2 : op[1] = XEXP (x, 1);
1389 2 : break;
1390 4 : case UDIV:
1391 4 : fun = "udiv";
1392 4 : op[0] = XEXP (x, 0);
1393 4 : op[1] = XEXP (x, 1);
1394 4 : break;
1395 2 : case MOD:
1396 2 : op[0] = XEXP (x, 0);
1397 2 : st[1] = "%";
1398 2 : op[1] = XEXP (x, 1);
1399 2 : break;
1400 3 : case UMOD:
1401 3 : fun = "umod";
1402 3 : op[0] = XEXP (x, 0);
1403 3 : op[1] = XEXP (x, 1);
1404 3 : break;
1405 0 : case SMIN:
1406 0 : fun = "smin";
1407 0 : op[0] = XEXP (x, 0);
1408 0 : op[1] = XEXP (x, 1);
1409 0 : break;
1410 0 : case SMAX:
1411 0 : fun = "smax";
1412 0 : op[0] = XEXP (x, 0);
1413 0 : op[1] = XEXP (x, 1);
1414 0 : break;
1415 0 : case UMIN:
1416 0 : fun = "umin";
1417 0 : op[0] = XEXP (x, 0);
1418 0 : op[1] = XEXP (x, 1);
1419 0 : break;
1420 0 : case UMAX:
1421 0 : fun = "umax";
1422 0 : op[0] = XEXP (x, 0);
1423 0 : op[1] = XEXP (x, 1);
1424 0 : break;
1425 10 : case NOT:
1426 10 : st[0] = "~";
1427 10 : op[0] = XEXP (x, 0);
1428 10 : break;
1429 97 : case AND:
1430 97 : op[0] = XEXP (x, 0);
1431 97 : st[1] = "&";
1432 97 : op[1] = XEXP (x, 1);
1433 97 : break;
1434 11 : case IOR:
1435 11 : op[0] = XEXP (x, 0);
1436 11 : st[1] = "|";
1437 11 : op[1] = XEXP (x, 1);
1438 11 : break;
1439 10 : case XOR:
1440 10 : op[0] = XEXP (x, 0);
1441 10 : st[1] = "^";
1442 10 : op[1] = XEXP (x, 1);
1443 10 : break;
1444 86 : case ASHIFT:
1445 86 : op[0] = XEXP (x, 0);
1446 86 : st[1] = "<<";
1447 86 : op[1] = XEXP (x, 1);
1448 86 : break;
1449 87 : case LSHIFTRT:
1450 87 : op[0] = XEXP (x, 0);
1451 87 : st[1] = " 0>>";
1452 87 : op[1] = XEXP (x, 1);
1453 87 : break;
1454 44 : case ASHIFTRT:
1455 44 : op[0] = XEXP (x, 0);
1456 44 : st[1] = ">>";
1457 44 : op[1] = XEXP (x, 1);
1458 44 : break;
1459 0 : case ROTATE:
1460 0 : op[0] = XEXP (x, 0);
1461 0 : st[1] = "<-<";
1462 0 : op[1] = XEXP (x, 1);
1463 0 : break;
1464 0 : case ROTATERT:
1465 0 : op[0] = XEXP (x, 0);
1466 0 : st[1] = ">->";
1467 0 : op[1] = XEXP (x, 1);
1468 0 : break;
1469 50 : case NE:
1470 50 : op[0] = XEXP (x, 0);
1471 50 : st[1] = "!=";
1472 50 : op[1] = XEXP (x, 1);
1473 50 : break;
1474 154 : case EQ:
1475 154 : op[0] = XEXP (x, 0);
1476 154 : st[1] = "==";
1477 154 : op[1] = XEXP (x, 1);
1478 154 : break;
1479 24 : case GE:
1480 24 : op[0] = XEXP (x, 0);
1481 24 : st[1] = ">=";
1482 24 : op[1] = XEXP (x, 1);
1483 24 : break;
1484 18 : case GT:
1485 18 : op[0] = XEXP (x, 0);
1486 18 : st[1] = ">";
1487 18 : op[1] = XEXP (x, 1);
1488 18 : break;
1489 16 : case LE:
1490 16 : op[0] = XEXP (x, 0);
1491 16 : st[1] = "<=";
1492 16 : op[1] = XEXP (x, 1);
1493 16 : break;
1494 80 : case LT:
1495 80 : op[0] = XEXP (x, 0);
1496 80 : st[1] = "<";
1497 80 : op[1] = XEXP (x, 1);
1498 80 : break;
1499 0 : case SIGN_EXTRACT:
1500 0 : fun = (verbose) ? "sign_extract" : "sxt";
1501 0 : op[0] = XEXP (x, 0);
1502 0 : op[1] = XEXP (x, 1);
1503 0 : op[2] = XEXP (x, 2);
1504 0 : break;
1505 4 : case ZERO_EXTRACT:
1506 4 : fun = (verbose) ? "zero_extract" : "zxt";
1507 4 : op[0] = XEXP (x, 0);
1508 4 : op[1] = XEXP (x, 1);
1509 4 : op[2] = XEXP (x, 2);
1510 4 : break;
1511 71 : case SIGN_EXTEND:
1512 71 : fun = (verbose) ? "sign_extend" : "sxn";
1513 71 : op[0] = XEXP (x, 0);
1514 71 : break;
1515 140 : case ZERO_EXTEND:
1516 140 : fun = (verbose) ? "zero_extend" : "zxn";
1517 140 : op[0] = XEXP (x, 0);
1518 140 : break;
1519 0 : case FLOAT_EXTEND:
1520 0 : fun = (verbose) ? "float_extend" : "fxn";
1521 0 : op[0] = XEXP (x, 0);
1522 0 : break;
1523 0 : case TRUNCATE:
1524 0 : fun = (verbose) ? "trunc" : "trn";
1525 0 : op[0] = XEXP (x, 0);
1526 0 : break;
1527 0 : case FLOAT_TRUNCATE:
1528 0 : fun = (verbose) ? "float_trunc" : "ftr";
1529 0 : op[0] = XEXP (x, 0);
1530 0 : break;
1531 4 : case FLOAT:
1532 4 : fun = (verbose) ? "float" : "flt";
1533 4 : op[0] = XEXP (x, 0);
1534 4 : break;
1535 0 : case UNSIGNED_FLOAT:
1536 0 : fun = (verbose) ? "uns_float" : "ufl";
1537 0 : op[0] = XEXP (x, 0);
1538 0 : break;
1539 0 : case FIX:
1540 0 : fun = "fix";
1541 0 : op[0] = XEXP (x, 0);
1542 0 : break;
1543 0 : case UNSIGNED_FIX:
1544 0 : fun = (verbose) ? "uns_fix" : "ufx";
1545 0 : op[0] = XEXP (x, 0);
1546 0 : break;
1547 69 : case PRE_DEC:
1548 69 : st[0] = "--";
1549 69 : op[0] = XEXP (x, 0);
1550 69 : break;
1551 0 : case PRE_INC:
1552 0 : st[0] = "++";
1553 0 : op[0] = XEXP (x, 0);
1554 0 : break;
1555 0 : case POST_DEC:
1556 0 : op[0] = XEXP (x, 0);
1557 0 : st[1] = "--";
1558 0 : break;
1559 66 : case POST_INC:
1560 66 : op[0] = XEXP (x, 0);
1561 66 : st[1] = "++";
1562 66 : break;
1563 0 : case PRE_MODIFY:
1564 0 : st[0] = "pre ";
1565 0 : op[0] = XEXP (XEXP (x, 1), 0);
1566 0 : st[1] = "+=";
1567 0 : op[1] = XEXP (XEXP (x, 1), 1);
1568 0 : break;
1569 0 : case POST_MODIFY:
1570 0 : st[0] = "post ";
1571 0 : op[0] = XEXP (XEXP (x, 1), 0);
1572 0 : st[1] = "+=";
1573 0 : op[1] = XEXP (XEXP (x, 1), 1);
1574 0 : break;
1575 65 : case CALL:
1576 65 : st[0] = "call ";
1577 65 : op[0] = XEXP (x, 0);
1578 65 : if (verbose)
1579 : {
1580 52 : st[1] = " argc:";
1581 52 : op[1] = XEXP (x, 1);
1582 : }
1583 : break;
1584 390 : case IF_THEN_ELSE:
1585 390 : st[0] = "{(";
1586 390 : op[0] = XEXP (x, 0);
1587 390 : st[1] = ")?";
1588 390 : op[1] = XEXP (x, 1);
1589 390 : st[2] = ":";
1590 390 : op[2] = XEXP (x, 2);
1591 390 : st[3] = "}";
1592 390 : break;
1593 0 : case TRAP_IF:
1594 0 : fun = "trap_if";
1595 0 : op[0] = TRAP_CONDITION (x);
1596 0 : break;
1597 0 : case PREFETCH:
1598 0 : fun = "prefetch";
1599 0 : op[0] = XEXP (x, 0);
1600 0 : op[1] = XEXP (x, 1);
1601 0 : op[2] = XEXP (x, 2);
1602 0 : break;
1603 52 : case UNSPEC:
1604 52 : case UNSPEC_VOLATILE:
1605 52 : {
1606 52 : pp_string (pp, "unspec");
1607 52 : if (GET_CODE (x) == UNSPEC_VOLATILE)
1608 0 : pp_string (pp, "/v");
1609 52 : pp_left_bracket (pp);
1610 156 : for (i = 0; i < XVECLEN (x, 0); i++)
1611 : {
1612 52 : if (i != 0)
1613 0 : pp_comma (pp);
1614 52 : print_pattern (pp, XVECEXP (x, 0, i), verbose);
1615 : }
1616 52 : pp_string (pp, "]");
1617 52 : const char *str = nullptr;
1618 52 : auto unspec = XINT (x, 1);
1619 : #if !defined(GENERATOR_FILE)
1620 52 : if (unspec < 0)
1621 : {
1622 : }
1623 : #if NUM_UNSPECV_VALUES > 0
1624 52 : else if (GET_CODE (x) == UNSPEC_VOLATILE
1625 0 : && unspec < NUM_UNSPECV_VALUES)
1626 0 : str = unspecv_strings[unspec];
1627 : #endif
1628 : #if NUM_UNSPEC_VALUES > 0
1629 52 : else if (true
1630 : #if NUM_UNSPECV_VALUES > 0
1631 : // Only accept unspec_volatiles, if there's no unspecv enum.
1632 : && GET_CODE (x) == UNSPEC
1633 : #endif
1634 52 : && unspec < NUM_UNSPEC_VALUES)
1635 52 : str = unspec_strings[unspec];
1636 : #endif
1637 : #endif
1638 52 : if (str)
1639 : {
1640 : // Strip leading UNSPEC[_] leaving FOO or V_FOO by convention.
1641 52 : if (0 == strncmp (str, "UNSPEC", 6))
1642 52 : str += 6 + (str[6] == '_');
1643 52 : pp_string (pp, str);
1644 : }
1645 : else
1646 0 : pp_decimal_int (pp, unspec);
1647 : }
1648 : break;
1649 451 : default:
1650 451 : {
1651 : /* Most unhandled codes can be printed as pseudo-functions. */
1652 451 : if (GET_RTX_CLASS (GET_CODE (x)) == RTX_UNARY)
1653 : {
1654 25 : fun = GET_RTX_NAME (GET_CODE (x));
1655 25 : op[0] = XEXP (x, 0);
1656 : }
1657 426 : else if (GET_RTX_CLASS (GET_CODE (x)) == RTX_COMPARE
1658 : || GET_RTX_CLASS (GET_CODE (x)) == RTX_COMM_COMPARE
1659 : || GET_RTX_CLASS (GET_CODE (x)) == RTX_BIN_ARITH
1660 : || GET_RTX_CLASS (GET_CODE (x)) == RTX_COMM_ARITH)
1661 : {
1662 228 : fun = GET_RTX_NAME (GET_CODE (x));
1663 228 : op[0] = XEXP (x, 0);
1664 228 : op[1] = XEXP (x, 1);
1665 : }
1666 198 : else if (GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY)
1667 : {
1668 8 : fun = GET_RTX_NAME (GET_CODE (x));
1669 8 : op[0] = XEXP (x, 0);
1670 8 : op[1] = XEXP (x, 1);
1671 8 : op[2] = XEXP (x, 2);
1672 : }
1673 : else
1674 : /* Give up, just print the RTX name. */
1675 190 : st[0] = GET_RTX_NAME (GET_CODE (x));
1676 : }
1677 : break;
1678 : }
1679 :
1680 : /* Print this as a function? */
1681 5733 : if (fun)
1682 : {
1683 1050 : pp_string (pp, fun);
1684 1050 : pp_left_paren (pp);
1685 : }
1686 :
1687 28730 : for (i = 0; i < 4; i++)
1688 : {
1689 22984 : if (st[i])
1690 5866 : pp_string (pp, st[i]);
1691 :
1692 22984 : if (op[i])
1693 : {
1694 11009 : if (fun && i != 0)
1695 822 : pp_comma (pp);
1696 11009 : print_value (pp, op[i], verbose);
1697 : }
1698 : }
1699 :
1700 5746 : if (fun)
1701 1050 : pp_right_paren (pp);
1702 5746 : } /* print_exp */
1703 :
1704 : /* Prints rtxes, I customarily classified as values. They're constants,
1705 : registers, labels, symbols and memory accesses. */
1706 :
1707 : void
1708 28566 : print_value (pretty_printer *pp, const_rtx x, int verbose)
1709 : {
1710 28566 : char tmp[1024];
1711 :
1712 28566 : if (!x)
1713 : {
1714 1 : pp_string (pp, "(nil)");
1715 1 : return;
1716 : }
1717 28565 : switch (GET_CODE (x))
1718 : {
1719 3799 : case CONST_INT:
1720 3799 : pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
1721 : (unsigned HOST_WIDE_INT) INTVAL (x));
1722 3799 : break;
1723 :
1724 0 : case CONST_WIDE_INT:
1725 0 : {
1726 0 : const char *sep = "<";
1727 0 : int i;
1728 0 : for (i = CONST_WIDE_INT_NUNITS (x) - 1; i >= 0; i--)
1729 : {
1730 0 : pp_string (pp, sep);
1731 0 : sep = ",";
1732 0 : sprintf (tmp, HOST_WIDE_INT_PRINT_HEX,
1733 0 : (unsigned HOST_WIDE_INT) CONST_WIDE_INT_ELT (x, i));
1734 0 : pp_string (pp, tmp);
1735 : }
1736 0 : pp_greater (pp);
1737 : }
1738 0 : break;
1739 :
1740 0 : case CONST_POLY_INT:
1741 0 : pp_left_bracket (pp);
1742 0 : pp_wide_int (pp, CONST_POLY_INT_COEFFS (x)[0], SIGNED);
1743 0 : for (unsigned int i = 1; i < NUM_POLY_INT_COEFFS; ++i)
1744 : {
1745 : pp_string (pp, ", ");
1746 : pp_wide_int (pp, CONST_POLY_INT_COEFFS (x)[i], SIGNED);
1747 : }
1748 0 : pp_right_bracket (pp);
1749 0 : break;
1750 :
1751 1 : case CONST_DOUBLE:
1752 1 : if (FLOAT_MODE_P (GET_MODE (x)))
1753 : {
1754 1 : real_to_decimal (tmp, CONST_DOUBLE_REAL_VALUE (x),
1755 : sizeof (tmp), 0, 1);
1756 1 : pp_string (pp, tmp);
1757 : }
1758 : else
1759 0 : pp_printf (pp, "<%wx,%wx>",
1760 0 : (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x),
1761 0 : (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x));
1762 : break;
1763 0 : case CONST_FIXED:
1764 0 : fixed_to_decimal (tmp, CONST_FIXED_VALUE (x), sizeof (tmp));
1765 0 : pp_string (pp, tmp);
1766 0 : break;
1767 0 : case CONST_STRING:
1768 0 : pp_string (pp, "\"");
1769 0 : pretty_print_string (pp, XSTR (x, 0), strlen (XSTR (x, 0)));
1770 0 : pp_string (pp, "\"");
1771 0 : break;
1772 237 : case SYMBOL_REF:
1773 237 : pp_printf (pp, "`%s'", XSTR (x, 0));
1774 237 : break;
1775 413 : case LABEL_REF:
1776 413 : pp_printf (pp, "L%d", INSN_UID (label_ref_label (x)));
1777 413 : break;
1778 4 : case CONST:
1779 4 : case HIGH:
1780 4 : case STRICT_LOW_PART:
1781 4 : pp_printf (pp, "%s(", GET_RTX_NAME (GET_CODE (x)));
1782 4 : print_value (pp, XEXP (x, 0), verbose);
1783 4 : pp_right_paren (pp);
1784 4 : break;
1785 15633 : case REG:
1786 15633 : if (REGNO (x) < FIRST_PSEUDO_REGISTER)
1787 : {
1788 8427 : if (ISDIGIT (reg_names[REGNO (x)][0]))
1789 0 : pp_modulo (pp);
1790 8427 : pp_string (pp, reg_names[REGNO (x)]);
1791 : }
1792 : else
1793 7206 : pp_printf (pp, "r%d", REGNO (x));
1794 15633 : if (verbose)
1795 13092 : pp_printf (pp, ":%s", GET_MODE_NAME (GET_MODE (x)));
1796 : break;
1797 94 : case SUBREG:
1798 94 : print_value (pp, SUBREG_REG (x), verbose);
1799 94 : pp_printf (pp, "#");
1800 94 : pp_wide_integer (pp, SUBREG_BYTE (x));
1801 94 : break;
1802 848 : case SCRATCH:
1803 848 : case PC:
1804 848 : pp_string (pp, GET_RTX_NAME (GET_CODE (x)));
1805 848 : break;
1806 1739 : case MEM:
1807 1739 : pp_left_bracket (pp);
1808 1739 : print_value (pp, XEXP (x, 0), verbose);
1809 1739 : pp_right_bracket (pp);
1810 1739 : break;
1811 54 : case DEBUG_EXPR:
1812 54 : pp_printf (pp, "D#%i", DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x)));
1813 54 : break;
1814 5743 : default:
1815 5743 : print_exp (pp, x, verbose);
1816 5743 : break;
1817 : }
1818 : } /* print_value */
1819 :
1820 : /* The next step in insn detalization, its pattern recognition. */
1821 :
1822 : void
1823 11921 : print_pattern (pretty_printer *pp, const_rtx x, int verbose)
1824 : {
1825 11921 : if (! x)
1826 : {
1827 28 : pp_string (pp, "(nil)");
1828 28 : return;
1829 : }
1830 :
1831 11893 : switch (GET_CODE (x))
1832 : {
1833 5134 : case SET:
1834 5134 : print_value (pp, SET_DEST (x), verbose);
1835 5134 : pp_equal (pp);
1836 5134 : print_value (pp, SET_SRC (x), verbose);
1837 5134 : break;
1838 120 : case RETURN:
1839 120 : case SIMPLE_RETURN:
1840 120 : case EH_RETURN:
1841 120 : pp_string (pp, GET_RTX_NAME (GET_CODE (x)));
1842 120 : break;
1843 3 : case CALL:
1844 3 : print_exp (pp, x, verbose);
1845 3 : break;
1846 1565 : case CLOBBER:
1847 1565 : case USE:
1848 1565 : pp_printf (pp, "%s ", GET_RTX_NAME (GET_CODE (x)));
1849 1565 : print_value (pp, XEXP (x, 0), verbose);
1850 1565 : break;
1851 58 : case VAR_LOCATION:
1852 58 : pp_string (pp, "loc ");
1853 58 : print_value (pp, PAT_VAR_LOCATION_LOC (x), verbose);
1854 58 : break;
1855 0 : case COND_EXEC:
1856 0 : pp_left_paren (pp);
1857 0 : if (GET_CODE (COND_EXEC_TEST (x)) == NE
1858 0 : && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
1859 0 : print_value (pp, XEXP (COND_EXEC_TEST (x), 0), verbose);
1860 0 : else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
1861 0 : && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
1862 : {
1863 0 : pp_exclamation (pp);
1864 0 : print_value (pp, XEXP (COND_EXEC_TEST (x), 0), verbose);
1865 : }
1866 : else
1867 0 : print_value (pp, COND_EXEC_TEST (x), verbose);
1868 0 : pp_string (pp, ") ");
1869 0 : print_pattern (pp, COND_EXEC_CODE (x), verbose);
1870 0 : break;
1871 1187 : case PARALLEL:
1872 1187 : {
1873 1187 : int i;
1874 :
1875 1187 : pp_left_brace (pp);
1876 4781 : for (i = 0; i < XVECLEN (x, 0); i++)
1877 : {
1878 2407 : print_pattern (pp, XVECEXP (x, 0, i), verbose);
1879 2407 : pp_semicolon (pp);
1880 : }
1881 1187 : pp_right_brace (pp);
1882 : }
1883 1187 : break;
1884 0 : case SEQUENCE:
1885 0 : {
1886 0 : const rtx_sequence *seq = as_a <const rtx_sequence *> (x);
1887 0 : pp_string (pp, "sequence{");
1888 0 : if (INSN_P (seq->element (0)))
1889 : {
1890 : /* Print the sequence insns indented. */
1891 0 : const char * save_print_rtx_head = print_rtx_head;
1892 0 : char indented_print_rtx_head[32];
1893 :
1894 0 : pp_newline (pp);
1895 0 : gcc_assert (strlen (print_rtx_head) < sizeof (indented_print_rtx_head) - 4);
1896 0 : snprintf (indented_print_rtx_head,
1897 : sizeof (indented_print_rtx_head),
1898 : "%s ", print_rtx_head);
1899 0 : print_rtx_head = indented_print_rtx_head;
1900 0 : for (int i = 0; i < seq->len (); i++)
1901 0 : print_insn_with_notes (pp, seq->insn (i));
1902 0 : pp_printf (pp, "%s ", save_print_rtx_head);
1903 0 : print_rtx_head = save_print_rtx_head;
1904 : }
1905 : else
1906 : {
1907 0 : for (int i = 0; i < seq->len (); i++)
1908 : {
1909 0 : print_pattern (pp, seq->element (i), verbose);
1910 0 : pp_semicolon (pp);
1911 : }
1912 : }
1913 0 : pp_right_brace (pp);
1914 : }
1915 0 : break;
1916 0 : case ASM_INPUT:
1917 0 : pp_printf (pp, "asm {%s}", XSTR (x, 0));
1918 0 : break;
1919 : case ADDR_VEC:
1920 0 : for (int i = 0; i < XVECLEN (x, 0); i++)
1921 : {
1922 0 : print_value (pp, XVECEXP (x, 0, i), verbose);
1923 0 : pp_semicolon (pp);
1924 : }
1925 : break;
1926 : case ADDR_DIFF_VEC:
1927 0 : for (int i = 0; i < XVECLEN (x, 1); i++)
1928 : {
1929 0 : print_value (pp, XVECEXP (x, 1, i), verbose);
1930 0 : pp_semicolon (pp);
1931 : }
1932 : break;
1933 0 : case TRAP_IF:
1934 0 : pp_string (pp, "trap_if ");
1935 0 : print_value (pp, TRAP_CONDITION (x), verbose);
1936 0 : break;
1937 3826 : case UNSPEC:
1938 3826 : case UNSPEC_VOLATILE:
1939 : /* Fallthru -- leave UNSPECs to print_exp. */
1940 3826 : default:
1941 3826 : print_value (pp, x, verbose);
1942 : }
1943 : } /* print_pattern */
1944 :
1945 : /* This is the main function in slim rtl visualization mechanism.
1946 :
1947 : X is an insn, to be printed into PP.
1948 :
1949 : This function tries to print it properly in human-readable form,
1950 : resembling assembler mnemonics (instead of the older Lisp-style
1951 : form).
1952 :
1953 : If VERBOSE is TRUE, insns are printed with more complete (but
1954 : longer) pattern names and with extra information, and prefixed
1955 : with their INSN_UIDs. */
1956 :
1957 : void
1958 6033 : print_insn (pretty_printer *pp, const rtx_insn *x, int verbose)
1959 : {
1960 6033 : if (verbose)
1961 : {
1962 : /* Blech, pretty-print can't print integers with a specified width. */
1963 6033 : char uid_prefix[32];
1964 6033 : snprintf (uid_prefix, sizeof uid_prefix, " %4d: ", INSN_UID (x));
1965 6033 : pp_string (pp, uid_prefix);
1966 : }
1967 :
1968 6033 : switch (GET_CODE (x))
1969 : {
1970 4119 : case INSN:
1971 4119 : print_pattern (pp, PATTERN (x), verbose);
1972 4119 : break;
1973 :
1974 148 : case DEBUG_INSN:
1975 148 : {
1976 148 : if (DEBUG_MARKER_INSN_P (x))
1977 : {
1978 82 : switch (INSN_DEBUG_MARKER_KIND (x))
1979 : {
1980 82 : case NOTE_INSN_BEGIN_STMT:
1981 82 : pp_string (pp, "debug begin stmt marker");
1982 82 : break;
1983 :
1984 0 : case NOTE_INSN_INLINE_ENTRY:
1985 0 : pp_string (pp, "debug inline entry marker");
1986 0 : break;
1987 :
1988 0 : default:
1989 0 : gcc_unreachable ();
1990 : }
1991 82 : break;
1992 : }
1993 :
1994 66 : const char *name = "?";
1995 66 : char idbuf[32];
1996 :
1997 66 : if (DECL_P (INSN_VAR_LOCATION_DECL (x)))
1998 : {
1999 66 : tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (x));
2000 66 : if (id)
2001 58 : name = IDENTIFIER_POINTER (id);
2002 8 : else if (TREE_CODE (INSN_VAR_LOCATION_DECL (x))
2003 : == DEBUG_EXPR_DECL)
2004 : {
2005 16 : sprintf (idbuf, "D#%i",
2006 8 : DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (x)));
2007 8 : name = idbuf;
2008 : }
2009 : else
2010 : {
2011 0 : sprintf (idbuf, "D.%i",
2012 0 : DECL_UID (INSN_VAR_LOCATION_DECL (x)));
2013 0 : name = idbuf;
2014 : }
2015 : }
2016 66 : pp_printf (pp, "debug %s => ", name);
2017 66 : if (VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (x)))
2018 14 : pp_string (pp, "optimized away");
2019 : else
2020 52 : print_pattern (pp, INSN_VAR_LOCATION_LOC (x), verbose);
2021 : }
2022 66 : break;
2023 :
2024 396 : case JUMP_INSN:
2025 396 : print_pattern (pp, PATTERN (x), verbose);
2026 396 : break;
2027 52 : case CALL_INSN:
2028 52 : if (GET_CODE (PATTERN (x)) == PARALLEL)
2029 0 : print_pattern (pp, XVECEXP (PATTERN (x), 0, 0), verbose);
2030 : else
2031 52 : print_pattern (pp, PATTERN (x), verbose);
2032 : break;
2033 186 : case CODE_LABEL:
2034 186 : pp_printf (pp, "L%d:", INSN_UID (x));
2035 186 : break;
2036 0 : case JUMP_TABLE_DATA:
2037 0 : pp_string (pp, "jump_table_data{\n");
2038 0 : print_pattern (pp, PATTERN (x), verbose);
2039 0 : pp_right_brace (pp);
2040 0 : break;
2041 27 : case BARRIER:
2042 27 : pp_string (pp, "barrier");
2043 27 : break;
2044 1105 : case NOTE:
2045 1105 : {
2046 1105 : pp_string (pp, GET_NOTE_INSN_NAME (NOTE_KIND (x)));
2047 1105 : switch (NOTE_KIND (x))
2048 : {
2049 0 : case NOTE_INSN_EH_REGION_BEG:
2050 0 : case NOTE_INSN_EH_REGION_END:
2051 0 : pp_printf (pp, " %d", NOTE_EH_HANDLER (x));
2052 0 : break;
2053 :
2054 0 : case NOTE_INSN_BLOCK_BEG:
2055 0 : case NOTE_INSN_BLOCK_END:
2056 0 : pp_printf (pp, " %d", BLOCK_NUMBER (NOTE_BLOCK (x)));
2057 0 : break;
2058 :
2059 562 : case NOTE_INSN_BASIC_BLOCK:
2060 562 : pp_printf (pp, " %d", NOTE_BASIC_BLOCK (x)->index);
2061 562 : break;
2062 :
2063 0 : case NOTE_INSN_DELETED_LABEL:
2064 0 : case NOTE_INSN_DELETED_DEBUG_LABEL:
2065 0 : {
2066 0 : const char *label = NOTE_DELETED_LABEL_NAME (x);
2067 0 : if (label == NULL)
2068 0 : label = "";
2069 0 : pp_printf (pp, " (\"%s\")", label);
2070 : }
2071 0 : break;
2072 :
2073 2 : case NOTE_INSN_VAR_LOCATION:
2074 2 : pp_left_brace (pp);
2075 2 : print_pattern (pp, NOTE_VAR_LOCATION (x), verbose);
2076 2 : pp_right_brace (pp);
2077 2 : break;
2078 :
2079 : default:
2080 : break;
2081 : }
2082 : break;
2083 : }
2084 0 : default:
2085 0 : gcc_unreachable ();
2086 : }
2087 6033 : } /* print_insn */
2088 :
2089 : /* Pretty-print a slim dump of X (an insn) to PP, including any register
2090 : note attached to the instruction. */
2091 :
2092 : void
2093 6033 : print_insn_with_notes (pretty_printer *pp, const rtx_insn *x)
2094 : {
2095 6033 : pp_string (pp, print_rtx_head);
2096 6033 : print_insn (pp, x, 1);
2097 6033 : pp_newline (pp);
2098 6033 : if (INSN_P (x) && REG_NOTES (x))
2099 6010 : for (rtx note = REG_NOTES (x); note; note = XEXP (note, 1))
2100 : {
2101 3579 : pp_printf (pp, "%s %s ", print_rtx_head,
2102 3579 : GET_REG_NOTE_NAME (REG_NOTE_KIND (note)));
2103 3579 : if (GET_CODE (note) == INT_LIST)
2104 188 : pp_printf (pp, "%d", XINT (note, 0));
2105 : else
2106 3391 : print_pattern (pp, XEXP (note, 0), 1);
2107 3579 : pp_newline (pp);
2108 : }
2109 6033 : }
2110 :
2111 : /* Print X, an RTL value node, to file F in slim format. Include
2112 : additional information if VERBOSE is nonzero.
2113 :
2114 : Value nodes are constants, registers, labels, symbols and
2115 : memory. */
2116 :
2117 : void
2118 3 : dump_value_slim (FILE *f, const_rtx x, int verbose)
2119 : {
2120 3 : pretty_printer rtl_slim_pp;
2121 3 : rtl_slim_pp.set_output_stream (f);
2122 3 : print_value (&rtl_slim_pp, x, verbose);
2123 3 : pp_flush (&rtl_slim_pp);
2124 3 : }
2125 :
2126 : /* Emit a slim dump of X (an insn) to the file F, including any register
2127 : note attached to the instruction. */
2128 : void
2129 3168 : dump_insn_slim (FILE *f, const rtx_insn *x)
2130 : {
2131 3168 : pretty_printer rtl_slim_pp;
2132 3168 : rtl_slim_pp.set_output_stream (f);
2133 3168 : print_insn_with_notes (&rtl_slim_pp, x);
2134 3168 : pp_flush (&rtl_slim_pp);
2135 3168 : }
2136 :
2137 : /* Same as above, but stop at LAST or when COUNT == 0.
2138 : If COUNT < 0 it will stop only at LAST or NULL rtx. */
2139 :
2140 : void
2141 190 : dump_rtl_slim (FILE *f, const rtx_insn *first, const rtx_insn *last,
2142 : int count, int flags ATTRIBUTE_UNUSED)
2143 : {
2144 190 : const rtx_insn *insn, *tail;
2145 190 : pretty_printer rtl_slim_pp;
2146 190 : rtl_slim_pp.set_output_stream (f);
2147 :
2148 190 : tail = last ? NEXT_INSN (last) : NULL;
2149 384 : for (insn = first;
2150 384 : (insn != NULL) && (insn != tail) && (count != 0);
2151 194 : insn = NEXT_INSN (insn))
2152 : {
2153 194 : print_insn_with_notes (&rtl_slim_pp, insn);
2154 194 : if (count > 0)
2155 0 : count--;
2156 : }
2157 :
2158 190 : pp_flush (&rtl_slim_pp);
2159 190 : }
2160 :
2161 : /* Dumps basic block BB to pretty-printer PP in slim form and without and
2162 : no indentation, for use as a label of a DOT graph record-node. */
2163 :
2164 : void
2165 307 : rtl_dump_bb_for_graph (pretty_printer *pp, basic_block bb)
2166 : {
2167 307 : rtx_insn *insn;
2168 307 : bool first = true;
2169 :
2170 : /* TODO: inter-bb stuff. */
2171 1774 : FOR_BB_INSNS (bb, insn)
2172 : {
2173 1467 : if (! first)
2174 : {
2175 1160 : pp_bar (pp);
2176 1160 : pp_write_text_to_stream (pp);
2177 : }
2178 1467 : first = false;
2179 1467 : print_insn_with_notes (pp, insn);
2180 1467 : pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
2181 : }
2182 307 : }
2183 :
2184 :
2185 : void
2186 300 : rtl_dump_bb_as_sarif_properties (diagnostics::sarif_builder *,
2187 : json::object &output_bag,
2188 : basic_block bb)
2189 : {
2190 : /* TODO: inter-bb stuff. */
2191 300 : auto json_insn_arr = std::make_unique<json::array> ();
2192 300 : rtx_insn *insn;
2193 1504 : FOR_BB_INSNS (bb, insn)
2194 : {
2195 1204 : pretty_printer pp;
2196 1204 : print_insn_with_notes (&pp, insn);
2197 1204 : json_insn_arr->append_string (pp_formatted_text (&pp));
2198 1204 : }
2199 300 : output_bag.set_array_of_string
2200 300 : (custom_sarif_properties::cfg::basic_block::rtl::insns,
2201 : std::move (json_insn_arr));
2202 300 : }
2203 :
2204 : /* Pretty-print pattern X of some insn in non-verbose mode.
2205 : Return a string pointer to the pretty-printer buffer.
2206 :
2207 : This function is only exported exists only to accommodate some older users
2208 : of the slim RTL pretty printers. Please do not use it for new code. */
2209 :
2210 : const char *
2211 1446 : str_pattern_slim (const_rtx x)
2212 : {
2213 1446 : pretty_printer rtl_slim_pp;
2214 1446 : print_pattern (&rtl_slim_pp, x, 0);
2215 1446 : return ggc_strdup (pp_formatted_text (&rtl_slim_pp));
2216 1446 : }
2217 :
2218 : /* Emit a slim dump of X (an insn) to stderr. */
2219 : extern void debug_insn_slim (const rtx_insn *);
2220 : DEBUG_FUNCTION void
2221 0 : debug_insn_slim (const rtx_insn *x)
2222 : {
2223 0 : dump_insn_slim (stderr, x);
2224 0 : }
2225 :
2226 : /* Same as above, but using dump_rtl_slim. */
2227 : extern void debug_rtl_slim (FILE *, const rtx_insn *, const rtx_insn *,
2228 : int, int);
2229 : DEBUG_FUNCTION void
2230 0 : debug_rtl_slim (const rtx_insn *first, const rtx_insn *last, int count,
2231 : int flags)
2232 : {
2233 0 : dump_rtl_slim (stderr, first, last, count, flags);
2234 0 : }
2235 :
2236 : extern void debug_bb_slim (basic_block);
2237 : DEBUG_FUNCTION void
2238 0 : debug_bb_slim (basic_block bb)
2239 : {
2240 0 : debug_bb (bb, TDF_SLIM | TDF_BLOCKS);
2241 0 : }
2242 :
2243 : extern void debug_bb_n_slim (int);
2244 : DEBUG_FUNCTION void
2245 0 : debug_bb_n_slim (int n)
2246 : {
2247 0 : basic_block bb = BASIC_BLOCK_FOR_FN (cfun, n);
2248 0 : debug_bb_slim (bb);
2249 0 : }
2250 :
2251 : #endif
2252 :
2253 : #if __GNUC__ >= 10
2254 : # pragma GCC diagnostic pop
2255 : #endif
|