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