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