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