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