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