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