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