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