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