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