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