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