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