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

source code of gcc/print-rtl.cc