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