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