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