1 /* Print RTL for GCC.
2    Copyright (C) 1987-2016 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 "cfg.h"
39 #include "print-tree.h"
40 #include "flags.h"
41 #include "predict.h"
42 #include "function.h"
43 #include "basic-block.h"
44 #include "diagnostic.h"
45 #include "tree-pretty-print.h"
46 #include "alloc-pool.h"
47 #include "cselib.h"
48 #include "dumpfile.h"	/* for dump_flags */
49 #include "dwarf2out.h"
50 #include "pretty-print.h"
51 #endif
52 
53 #include "print-rtl.h"
54 
55 static FILE *outfile;
56 
57 static int sawclose = 0;
58 
59 static int indent;
60 
61 static bool in_call_function_usage;
62 
63 static void print_rtx (const_rtx);
64 
65 /* String printed at beginning of each RTL when it is dumped.
66    This string is set to ASM_COMMENT_START when the RTL is dumped in
67    the assembly output file.  */
68 const char *print_rtx_head = "";
69 
70 #ifdef GENERATOR_FILE
71 /* These are defined from the .opt file when not used in generator
72    programs.  */
73 
74 /* Nonzero means suppress output of instruction numbers
75    in debugging dumps.
76    This must be defined here so that programs like gencodes can be linked.  */
77 int flag_dump_unnumbered = 0;
78 
79 /* Nonzero means suppress output of instruction numbers for previous
80    and next insns in debugging dumps.
81    This must be defined here so that programs like gencodes can be linked.  */
82 int flag_dump_unnumbered_links = 0;
83 #endif
84 
85 /* Nonzero means use simplified format without flags, modes, etc.  */
86 int flag_simple = 0;
87 
88 #ifndef GENERATOR_FILE
89 void
print_mem_expr(FILE * outfile,const_tree expr)90 print_mem_expr (FILE *outfile, const_tree expr)
91 {
92   fputc (' ', outfile);
93   print_generic_expr (outfile, CONST_CAST_TREE (expr), dump_flags);
94 }
95 #endif
96 
97 /* Print IN_RTX onto OUTFILE.  This is the recursive part of printing.  */
98 
99 static void
print_rtx(const_rtx in_rtx)100 print_rtx (const_rtx in_rtx)
101 {
102   int i = 0;
103   int j;
104   const char *format_ptr;
105   int is_insn;
106 
107   if (sawclose)
108     {
109       if (flag_simple)
110 	fputc (' ', outfile);
111       else
112 	fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, "");
113       sawclose = 0;
114     }
115 
116   if (in_rtx == 0)
117     {
118       fputs ("(nil)", outfile);
119       sawclose = 1;
120       return;
121     }
122   else if (GET_CODE (in_rtx) > NUM_RTX_CODE)
123     {
124        fprintf (outfile, "(??? bad code %d\n%s%*s)", GET_CODE (in_rtx),
125 		print_rtx_head, indent * 2, "");
126        sawclose = 1;
127        return;
128     }
129 
130   is_insn = INSN_P (in_rtx);
131 
132   /* Print name of expression code.  */
133   if (flag_simple && CONST_INT_P (in_rtx))
134     fputc ('(', outfile);
135   else
136     fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
137 
138   if (! flag_simple)
139     {
140       if (RTX_FLAG (in_rtx, in_struct))
141 	fputs ("/s", outfile);
142 
143       if (RTX_FLAG (in_rtx, volatil))
144 	fputs ("/v", outfile);
145 
146       if (RTX_FLAG (in_rtx, unchanging))
147 	fputs ("/u", outfile);
148 
149       if (RTX_FLAG (in_rtx, frame_related))
150 	fputs ("/f", outfile);
151 
152       if (RTX_FLAG (in_rtx, jump))
153 	fputs ("/j", outfile);
154 
155       if (RTX_FLAG (in_rtx, call))
156 	fputs ("/c", outfile);
157 
158       if (RTX_FLAG (in_rtx, return_val))
159 	fputs ("/i", outfile);
160 
161       /* Print REG_NOTE names for EXPR_LIST and INSN_LIST.  */
162       if ((GET_CODE (in_rtx) == EXPR_LIST
163 	   || GET_CODE (in_rtx) == INSN_LIST
164 	   || GET_CODE (in_rtx) == INT_LIST)
165 	  && (int)GET_MODE (in_rtx) < REG_NOTE_MAX
166 	  && !in_call_function_usage)
167 	fprintf (outfile, ":%s",
168 		 GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
169 
170       /* For other rtl, print the mode if it's not VOID.  */
171       else if (GET_MODE (in_rtx) != VOIDmode)
172 	fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
173 
174 #ifndef GENERATOR_FILE
175       if (GET_CODE (in_rtx) == VAR_LOCATION)
176 	{
177 	  if (TREE_CODE (PAT_VAR_LOCATION_DECL (in_rtx)) == STRING_CST)
178 	    fputs (" <debug string placeholder>", outfile);
179 	  else
180 	    print_mem_expr (outfile, PAT_VAR_LOCATION_DECL (in_rtx));
181 	  fputc (' ', outfile);
182 	  print_rtx (PAT_VAR_LOCATION_LOC (in_rtx));
183 	  if (PAT_VAR_LOCATION_STATUS (in_rtx)
184 	      == VAR_INIT_STATUS_UNINITIALIZED)
185 	    fprintf (outfile, " [uninit]");
186 	  sawclose = 1;
187 	  i = GET_RTX_LENGTH (VAR_LOCATION);
188 	}
189 #endif
190     }
191 
192 #ifndef GENERATOR_FILE
193   if (CONST_DOUBLE_AS_FLOAT_P (in_rtx))
194     i = 5;
195 #endif
196 
197   if (INSN_CHAIN_CODE_P (GET_CODE (in_rtx)))
198     {
199       if (flag_dump_unnumbered)
200 	fprintf (outfile, " #");
201       else
202 	fprintf (outfile, " %d", INSN_UID (in_rtx));
203     }
204 
205   /* Get the format string and skip the first elements if we have handled
206      them already.  */
207   format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i;
208   for (; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
209     switch (*format_ptr++)
210       {
211 	const char *str;
212 
213       case 'T':
214 	str = XTMPL (in_rtx, i);
215 	goto string;
216 
217       case 'S':
218       case 's':
219 	str = XSTR (in_rtx, i);
220       string:
221 
222 	if (str == 0)
223 	  fputs (" \"\"", outfile);
224 	else
225 	  fprintf (outfile, " (\"%s\")", str);
226 	sawclose = 1;
227 	break;
228 
229 	/* 0 indicates a field for internal use that should not be printed.
230 	   An exception is the third field of a NOTE, where it indicates
231 	   that the field has several different valid contents.  */
232       case '0':
233 #ifndef GENERATOR_FILE
234 	if (i == 1 && GET_CODE (in_rtx) == SYMBOL_REF)
235 	  {
236 	    int flags = SYMBOL_REF_FLAGS (in_rtx);
237 	    if (flags)
238 	      fprintf (outfile, " [flags %#x]", flags);
239 	    tree decl = SYMBOL_REF_DECL (in_rtx);
240 	    if (decl)
241 	      print_node_brief (outfile, "", decl, dump_flags);
242 	  }
243 	else if (i == 3 && NOTE_P (in_rtx))
244 	  {
245 	    switch (NOTE_KIND (in_rtx))
246 	      {
247 	      case NOTE_INSN_EH_REGION_BEG:
248 	      case NOTE_INSN_EH_REGION_END:
249 		if (flag_dump_unnumbered)
250 		  fprintf (outfile, " #");
251 		else
252 		  fprintf (outfile, " %d", NOTE_EH_HANDLER (in_rtx));
253 		sawclose = 1;
254 		break;
255 
256 	      case NOTE_INSN_BLOCK_BEG:
257 	      case NOTE_INSN_BLOCK_END:
258 		dump_addr (outfile, " ", NOTE_BLOCK (in_rtx));
259 		sawclose = 1;
260 		break;
261 
262 	      case NOTE_INSN_BASIC_BLOCK:
263 		{
264 		  basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
265 		  if (bb != 0)
266 		    fprintf (outfile, " [bb %d]", bb->index);
267 		  break;
268 	        }
269 
270 	      case NOTE_INSN_DELETED_LABEL:
271 	      case NOTE_INSN_DELETED_DEBUG_LABEL:
272 		{
273 		  const char *label = NOTE_DELETED_LABEL_NAME (in_rtx);
274 		  if (label)
275 		    fprintf (outfile, " (\"%s\")", label);
276 		  else
277 		    fprintf (outfile, " \"\"");
278 		}
279 		break;
280 
281 	      case NOTE_INSN_SWITCH_TEXT_SECTIONS:
282 		{
283 		  basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
284 		  if (bb != 0)
285 		    fprintf (outfile, " [bb %d]", bb->index);
286 		  break;
287 		}
288 
289 	      case NOTE_INSN_VAR_LOCATION:
290 	      case NOTE_INSN_CALL_ARG_LOCATION:
291 		fputc (' ', outfile);
292 		print_rtx (NOTE_VAR_LOCATION (in_rtx));
293 		break;
294 
295 	      case NOTE_INSN_CFI:
296 		fputc ('\n', outfile);
297 		output_cfi_directive (outfile, NOTE_CFI (in_rtx));
298 		fputc ('\t', outfile);
299 		break;
300 
301 	      default:
302 		break;
303 	      }
304 	  }
305 	else if (i == 7 && JUMP_P (in_rtx) && JUMP_LABEL (in_rtx) != NULL)
306 	  {
307 	    /* Output the JUMP_LABEL reference.  */
308 	    fprintf (outfile, "\n%s%*s -> ", print_rtx_head, indent * 2, "");
309 	    if (GET_CODE (JUMP_LABEL (in_rtx)) == RETURN)
310 	      fprintf (outfile, "return");
311 	    else if (GET_CODE (JUMP_LABEL (in_rtx)) == SIMPLE_RETURN)
312 	      fprintf (outfile, "simple_return");
313 	    else
314 	      fprintf (outfile, "%d", INSN_UID (JUMP_LABEL (in_rtx)));
315 	  }
316 	else if (i == 0 && GET_CODE (in_rtx) == VALUE)
317 	  {
318 	    cselib_val *val = CSELIB_VAL_PTR (in_rtx);
319 
320 	    fprintf (outfile, " %u:%u", val->uid, val->hash);
321 	    dump_addr (outfile, " @", in_rtx);
322 	    dump_addr (outfile, "/", (void*)val);
323 	  }
324 	else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
325 	  {
326 	    fprintf (outfile, " D#%i",
327 		     DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (in_rtx)));
328 	  }
329 	else if (i == 0 && GET_CODE (in_rtx) == ENTRY_VALUE)
330 	  {
331 	    indent += 2;
332 	    if (!sawclose)
333 	      fprintf (outfile, " ");
334 	    print_rtx (ENTRY_VALUE_EXP (in_rtx));
335 	    indent -= 2;
336 	  }
337 #endif
338 	break;
339 
340       case 'e':
341       do_e:
342 	indent += 2;
343 	if (i == 6 && INSN_P (in_rtx))
344 	  /* Put REG_NOTES on their own line.  */
345 	  fprintf (outfile, "\n%s%*s",
346 		   print_rtx_head, indent * 2, "");
347 	if (!sawclose)
348 	  fprintf (outfile, " ");
349 	if (i == 7 && CALL_P (in_rtx))
350 	  {
351 	    in_call_function_usage = true;
352 	    print_rtx (XEXP (in_rtx, i));
353 	    in_call_function_usage = false;
354 	  }
355 	else
356 	  print_rtx (XEXP (in_rtx, i));
357 	indent -= 2;
358 	break;
359 
360       case 'E':
361       case 'V':
362 	indent += 2;
363 	if (sawclose)
364 	  {
365 	    fprintf (outfile, "\n%s%*s",
366 		     print_rtx_head, indent * 2, "");
367 	    sawclose = 0;
368 	  }
369 	fputs (" [", outfile);
370 	if (NULL != XVEC (in_rtx, i))
371 	  {
372 	    indent += 2;
373 	    if (XVECLEN (in_rtx, i))
374 	      sawclose = 1;
375 
376 	    for (j = 0; j < XVECLEN (in_rtx, i); j++)
377 	      print_rtx (XVECEXP (in_rtx, i, j));
378 
379 	    indent -= 2;
380 	  }
381 	if (sawclose)
382 	  fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, "");
383 
384 	fputs ("]", outfile);
385 	sawclose = 1;
386 	indent -= 2;
387 	break;
388 
389       case 'w':
390 	if (! flag_simple)
391 	  fprintf (outfile, " ");
392 	fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, i));
393 	if (! flag_simple)
394 	  fprintf (outfile, " [" HOST_WIDE_INT_PRINT_HEX "]",
395 		   (unsigned HOST_WIDE_INT) XWINT (in_rtx, i));
396 	break;
397 
398       case 'i':
399 	if (i == 4 && INSN_P (in_rtx))
400 	  {
401 #ifndef GENERATOR_FILE
402 	    const rtx_insn *in_insn = as_a <const rtx_insn *> (in_rtx);
403 
404 	    /*  Pretty-print insn locations.  Ignore scoping as it is mostly
405 		redundant with line number information and do not print anything
406 		when there is no location information available.  */
407 	    if (INSN_HAS_LOCATION (in_insn))
408 	      {
409 		expanded_location xloc = insn_location (in_insn);
410 		fprintf (outfile, " %s:%i", xloc.file, xloc.line);
411 	      }
412 #endif
413 	  }
414 	else if (i == 6 && GET_CODE (in_rtx) == ASM_OPERANDS)
415 	  {
416 #ifndef GENERATOR_FILE
417 	    if (ASM_OPERANDS_SOURCE_LOCATION (in_rtx) != UNKNOWN_LOCATION)
418 	      fprintf (outfile, " %s:%i",
419 		       LOCATION_FILE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)),
420 		       LOCATION_LINE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)));
421 #endif
422 	  }
423 	else if (i == 1 && GET_CODE (in_rtx) == ASM_INPUT)
424 	  {
425 #ifndef GENERATOR_FILE
426 	    if (ASM_INPUT_SOURCE_LOCATION (in_rtx) != UNKNOWN_LOCATION)
427 	      fprintf (outfile, " %s:%i",
428 		       LOCATION_FILE (ASM_INPUT_SOURCE_LOCATION (in_rtx)),
429 		       LOCATION_LINE (ASM_INPUT_SOURCE_LOCATION (in_rtx)));
430 #endif
431 	  }
432 	else if (i == 5 && NOTE_P (in_rtx))
433 	  {
434 	    /* This field is only used for NOTE_INSN_DELETED_LABEL, and
435 	       other times often contains garbage from INSN->NOTE death.  */
436 	    if (NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_LABEL
437 		|| NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_DEBUG_LABEL)
438 	      fprintf (outfile, " %d",  XINT (in_rtx, i));
439 	  }
440 #if !defined(GENERATOR_FILE) && NUM_UNSPECV_VALUES > 0
441 	else if (i == 1
442 		 && GET_CODE (in_rtx) == UNSPEC_VOLATILE
443 		 && XINT (in_rtx, 1) >= 0
444 		 && XINT (in_rtx, 1) < NUM_UNSPECV_VALUES)
445 	  fprintf (outfile, " %s", unspecv_strings[XINT (in_rtx, 1)]);
446 #endif
447 #if !defined(GENERATOR_FILE) && NUM_UNSPEC_VALUES > 0
448 	else if (i == 1
449 		 && (GET_CODE (in_rtx) == UNSPEC
450 		     || GET_CODE (in_rtx) == UNSPEC_VOLATILE)
451 		 && XINT (in_rtx, 1) >= 0
452 		 && XINT (in_rtx, 1) < NUM_UNSPEC_VALUES)
453 	  fprintf (outfile, " %s", unspec_strings[XINT (in_rtx, 1)]);
454 #endif
455 	else
456 	  {
457 	    int value = XINT (in_rtx, i);
458 	    const char *name;
459 
460 	    if (flag_dump_unnumbered
461 		&& (is_insn || NOTE_P (in_rtx)))
462 	      fputc ('#', outfile);
463 	    else
464 	      fprintf (outfile, " %d", value);
465 
466 	    if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i)
467 		&& XINT (in_rtx, i) >= 0
468 		&& (name = get_insn_name (XINT (in_rtx, i))) != NULL)
469 	      fprintf (outfile, " {%s}", name);
470 	    sawclose = 0;
471 	  }
472 	break;
473 
474       case 'r':
475 	{
476 	  unsigned int regno = REGNO (in_rtx);
477 #ifndef GENERATOR_FILE
478 	  if (regno < FIRST_PSEUDO_REGISTER)
479 	    fprintf (outfile, " %d %s", regno, reg_names[regno]);
480 	  else if (regno <= LAST_VIRTUAL_REGISTER)
481 	    {
482 	      if (regno == VIRTUAL_INCOMING_ARGS_REGNUM)
483 		fprintf (outfile, " %d virtual-incoming-args", regno);
484 	      else if (regno == VIRTUAL_STACK_VARS_REGNUM)
485 		fprintf (outfile, " %d virtual-stack-vars", regno);
486 	      else if (regno == VIRTUAL_STACK_DYNAMIC_REGNUM)
487 		fprintf (outfile, " %d virtual-stack-dynamic", regno);
488 	      else if (regno == VIRTUAL_OUTGOING_ARGS_REGNUM)
489 		fprintf (outfile, " %d virtual-outgoing-args", regno);
490 	      else if (regno == VIRTUAL_CFA_REGNUM)
491 		fprintf (outfile, " %d virtual-cfa", regno);
492 	      else if (regno == VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM)
493 		fprintf (outfile, " %d virtual-preferred-stack-boundary",
494 			 regno);
495 	      else
496 		fprintf (outfile, " %d virtual-reg-%d", regno,
497 			 regno-FIRST_VIRTUAL_REGISTER);
498 	    }
499 	  else
500 #endif
501 	    if (flag_dump_unnumbered && is_insn)
502 	      fputc ('#', outfile);
503 	    else
504 	      fprintf (outfile, " %d", regno);
505 
506 #ifndef GENERATOR_FILE
507 	  if (REG_ATTRS (in_rtx))
508 	    {
509 	      fputs (" [", outfile);
510 	      if (regno != ORIGINAL_REGNO (in_rtx))
511 		fprintf (outfile, "orig:%i", ORIGINAL_REGNO (in_rtx));
512 	      if (REG_EXPR (in_rtx))
513 		print_mem_expr (outfile, REG_EXPR (in_rtx));
514 
515 	      if (REG_OFFSET (in_rtx))
516 		fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
517 			 REG_OFFSET (in_rtx));
518 	      fputs (" ]", outfile);
519 	    }
520 	  if (regno != ORIGINAL_REGNO (in_rtx))
521 	    fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx));
522 #endif
523 	  break;
524 	}
525 
526       /* Print NOTE_INSN names rather than integer codes.  */
527 
528       case 'n':
529 	fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i)));
530 	sawclose = 0;
531 	break;
532 
533       case 'u':
534 	if (XEXP (in_rtx, i) != NULL)
535 	  {
536 	    rtx sub = XEXP (in_rtx, i);
537 	    enum rtx_code subc = GET_CODE (sub);
538 
539 	    if (GET_CODE (in_rtx) == LABEL_REF)
540 	      {
541 		if (subc == NOTE
542 		    && NOTE_KIND (sub) == NOTE_INSN_DELETED_LABEL)
543 		  {
544 		    if (flag_dump_unnumbered)
545 		      fprintf (outfile, " [# deleted]");
546 		    else
547 		      fprintf (outfile, " [%d deleted]", INSN_UID (sub));
548 		    sawclose = 0;
549 		    break;
550 		  }
551 
552 		if (subc != CODE_LABEL)
553 		  goto do_e;
554 	      }
555 
556 	    if (flag_dump_unnumbered
557 		|| (flag_dump_unnumbered_links && i <= 1
558 		    && (INSN_P (in_rtx) || NOTE_P (in_rtx)
559 			|| LABEL_P (in_rtx) || BARRIER_P (in_rtx))))
560 	      fputs (" #", outfile);
561 	    else
562 	      fprintf (outfile, " %d", INSN_UID (sub));
563 	  }
564 	else
565 	  fputs (" 0", outfile);
566 	sawclose = 0;
567 	break;
568 
569       case 't':
570 #ifndef GENERATOR_FILE
571 	if (i == 0 && GET_CODE (in_rtx) == DEBUG_IMPLICIT_PTR)
572 	  print_mem_expr (outfile, DEBUG_IMPLICIT_PTR_DECL (in_rtx));
573 	else if (i == 0 && GET_CODE (in_rtx) == DEBUG_PARAMETER_REF)
574 	  print_mem_expr (outfile, DEBUG_PARAMETER_REF_DECL (in_rtx));
575 	else
576 	  dump_addr (outfile, " ", XTREE (in_rtx, i));
577 #endif
578 	break;
579 
580       case '*':
581 	fputs (" Unknown", outfile);
582 	sawclose = 0;
583 	break;
584 
585       case 'B':
586 #ifndef GENERATOR_FILE
587 	if (XBBDEF (in_rtx, i))
588 	  fprintf (outfile, " %i", XBBDEF (in_rtx, i)->index);
589 #endif
590 	break;
591 
592       default:
593 	gcc_unreachable ();
594       }
595 
596   switch (GET_CODE (in_rtx))
597     {
598 #ifndef GENERATOR_FILE
599     case MEM:
600       if (__builtin_expect (final_insns_dump_p, false))
601 	fprintf (outfile, " [");
602       else
603 	fprintf (outfile, " [" HOST_WIDE_INT_PRINT_DEC,
604 		 (HOST_WIDE_INT) MEM_ALIAS_SET (in_rtx));
605 
606       if (MEM_EXPR (in_rtx))
607 	print_mem_expr (outfile, MEM_EXPR (in_rtx));
608       else
609 	fputc (' ', outfile);
610 
611       if (MEM_OFFSET_KNOWN_P (in_rtx))
612 	fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, MEM_OFFSET (in_rtx));
613 
614       if (MEM_SIZE_KNOWN_P (in_rtx))
615 	fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC, MEM_SIZE (in_rtx));
616 
617       if (MEM_ALIGN (in_rtx) != 1)
618 	fprintf (outfile, " A%u", MEM_ALIGN (in_rtx));
619 
620       if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (in_rtx)))
621 	fprintf (outfile, " AS%u", MEM_ADDR_SPACE (in_rtx));
622 
623       fputc (']', outfile);
624       break;
625 
626     case CONST_DOUBLE:
627       if (FLOAT_MODE_P (GET_MODE (in_rtx)))
628 	{
629 	  char s[60];
630 
631 	  real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
632 			   sizeof (s), 0, 1);
633 	  fprintf (outfile, " %s", s);
634 
635 	  real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
636 			       sizeof (s), 0, 1);
637 	  fprintf (outfile, " [%s]", s);
638 	}
639       break;
640 
641     case CONST_WIDE_INT:
642       fprintf (outfile, " ");
643       cwi_output_hex (outfile, in_rtx);
644       break;
645 #endif
646 
647     case CODE_LABEL:
648       fprintf (outfile, " [%d uses]", LABEL_NUSES (in_rtx));
649       switch (LABEL_KIND (in_rtx))
650 	{
651 	  case LABEL_NORMAL: break;
652 	  case LABEL_STATIC_ENTRY: fputs (" [entry]", outfile); break;
653 	  case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", outfile); break;
654 	  case LABEL_WEAK_ENTRY: fputs (" [weak entry]", outfile); break;
655 	  default: gcc_unreachable ();
656 	}
657       break;
658 
659     default:
660       break;
661     }
662 
663   fputc (')', outfile);
664   sawclose = 1;
665 }
666 
667 /* Print an rtx on the current line of FILE.  Initially indent IND
668    characters.  */
669 
670 void
print_inline_rtx(FILE * outf,const_rtx x,int ind)671 print_inline_rtx (FILE *outf, const_rtx x, int ind)
672 {
673   int oldsaw = sawclose;
674   int oldindent = indent;
675 
676   sawclose = 0;
677   indent = ind;
678   outfile = outf;
679   print_rtx (x);
680   sawclose = oldsaw;
681   indent = oldindent;
682 }
683 
684 /* Call this function from the debugger to see what X looks like.  */
685 
686 DEBUG_FUNCTION void
debug_rtx(const_rtx x)687 debug_rtx (const_rtx x)
688 {
689   outfile = stderr;
690   sawclose = 0;
691   print_rtx (x);
692   fprintf (stderr, "\n");
693 }
694 
695 /* Dump rtx REF.  */
696 
697 DEBUG_FUNCTION void
debug(const rtx_def & ref)698 debug (const rtx_def &ref)
699 {
700   debug_rtx (&ref);
701 }
702 
703 DEBUG_FUNCTION void
debug(const rtx_def * ptr)704 debug (const rtx_def *ptr)
705 {
706   if (ptr)
707     debug (*ptr);
708   else
709     fprintf (stderr, "<nil>\n");
710 }
711 
712 /* Count of rtx's to print with debug_rtx_list.
713    This global exists because gdb user defined commands have no arguments.  */
714 
715 DEBUG_VARIABLE int debug_rtx_count = 0;	/* 0 is treated as equivalent to 1 */
716 
717 /* Call this function to print list from X on.
718 
719    N is a count of the rtx's to print. Positive values print from the specified
720    rtx_insn on.  Negative values print a window around the rtx_insn.
721    EG: -5 prints 2 rtx_insn's on either side (in addition to the specified
722    rtx_insn).  */
723 
724 DEBUG_FUNCTION void
debug_rtx_list(const rtx_insn * x,int n)725 debug_rtx_list (const rtx_insn *x, int n)
726 {
727   int i,count;
728   const rtx_insn *insn;
729 
730   count = n == 0 ? 1 : n < 0 ? -n : n;
731 
732   /* If we are printing a window, back up to the start.  */
733 
734   if (n < 0)
735     for (i = count / 2; i > 0; i--)
736       {
737 	if (PREV_INSN (x) == 0)
738 	  break;
739 	x = PREV_INSN (x);
740       }
741 
742   for (i = count, insn = x; i > 0 && insn != 0; i--, insn = NEXT_INSN (insn))
743     {
744       debug_rtx (insn);
745       fprintf (stderr, "\n");
746     }
747 }
748 
749 /* Call this function to print an rtx_insn list from START to END
750    inclusive.  */
751 
752 DEBUG_FUNCTION void
debug_rtx_range(const rtx_insn * start,const rtx_insn * end)753 debug_rtx_range (const rtx_insn *start, const rtx_insn *end)
754 {
755   while (1)
756     {
757       debug_rtx (start);
758       fprintf (stderr, "\n");
759       if (!start || start == end)
760 	break;
761       start = NEXT_INSN (start);
762     }
763 }
764 
765 /* Call this function to search an rtx_insn list to find one with insn uid UID,
766    and then call debug_rtx_list to print it, using DEBUG_RTX_COUNT.
767    The found insn is returned to enable further debugging analysis.  */
768 
769 DEBUG_FUNCTION const rtx_insn *
debug_rtx_find(const rtx_insn * x,int uid)770 debug_rtx_find (const rtx_insn *x, int uid)
771 {
772   while (x != 0 && INSN_UID (x) != uid)
773     x = NEXT_INSN (x);
774   if (x != 0)
775     {
776       debug_rtx_list (x, debug_rtx_count);
777       return x;
778     }
779   else
780     {
781       fprintf (stderr, "insn uid %d not found\n", uid);
782       return 0;
783     }
784 }
785 
786 /* External entry point for printing a chain of insns
787    starting with RTX_FIRST onto file OUTF.
788    A blank line separates insns.
789 
790    If RTX_FIRST is not an insn, then it alone is printed, with no newline.  */
791 
792 void
print_rtl(FILE * outf,const_rtx rtx_first)793 print_rtl (FILE *outf, const_rtx rtx_first)
794 {
795   const rtx_insn *tmp_rtx;
796 
797   outfile = outf;
798   sawclose = 0;
799 
800   if (rtx_first == 0)
801     {
802       fputs (print_rtx_head, outf);
803       fputs ("(nil)\n", outf);
804     }
805   else
806     switch (GET_CODE (rtx_first))
807       {
808       case INSN:
809       case JUMP_INSN:
810       case CALL_INSN:
811       case NOTE:
812       case CODE_LABEL:
813       case JUMP_TABLE_DATA:
814       case BARRIER:
815 	for (tmp_rtx = as_a <const rtx_insn *> (rtx_first);
816 	     tmp_rtx != 0;
817 	     tmp_rtx = NEXT_INSN (tmp_rtx))
818 	  {
819 	    fputs (print_rtx_head, outfile);
820 	    print_rtx (tmp_rtx);
821 	    fprintf (outfile, "\n");
822 	  }
823 	break;
824 
825       default:
826 	fputs (print_rtx_head, outfile);
827 	print_rtx (rtx_first);
828       }
829 }
830 
831 /* Like print_rtx, except specify a file.  */
832 /* Return nonzero if we actually printed anything.  */
833 
834 int
print_rtl_single(FILE * outf,const_rtx x)835 print_rtl_single (FILE *outf, const_rtx x)
836 {
837   return print_rtl_single_with_indent (outf, x, 0);
838 }
839 
840 /* Like print_rtl_single, except specify a file and indentation.  */
841 
842 int
print_rtl_single_with_indent(FILE * outf,const_rtx x,int ind)843 print_rtl_single_with_indent (FILE *outf, const_rtx x, int ind)
844 {
845   int old_indent = indent;
846   char *s_indent = (char *) alloca ((size_t) ind + 1);
847   memset ((void *) s_indent, ' ', (size_t) ind);
848   s_indent[ind] = '\0';
849 
850   indent = ind;
851   outfile = outf;
852   sawclose = 0;
853   fputs (s_indent, outfile);
854   fputs (print_rtx_head, outfile);
855   print_rtx (x);
856   putc ('\n', outf);
857   indent = old_indent;
858   return 1;
859 }
860 
861 
862 /* Like print_rtl except without all the detail; for example,
863    if RTX is a CONST_INT then print in decimal format.  */
864 
865 void
print_simple_rtl(FILE * outf,const_rtx x)866 print_simple_rtl (FILE *outf, const_rtx x)
867 {
868   flag_simple = 1;
869   print_rtl (outf, x);
870   flag_simple = 0;
871 }
872 
873 #ifndef GENERATOR_FILE
874 /* The functions below  try to print RTL in a form resembling assembler
875    mnemonics.  Because this form is more concise than the "traditional" form
876    of RTL printing in Lisp-style, the form printed by this file is called
877    "slim".  RTL dumps in slim format can be obtained by appending the "-slim"
878    option to -fdump-rtl-<pass>.  Control flow graph output as a DOT file is
879    always printed in slim form.
880 
881    The normal interface to the functionality provided in this pretty-printer
882    is through the dump_*_slim functions to print to a stream, or via the
883    print_*_slim functions to print into a user's pretty-printer.
884 
885    It is also possible to obtain a string for a single pattern as a string
886    pointer, via str_pattern_slim, but this usage is discouraged.  */
887 
888 /* For insns we print patterns, and for some patterns we print insns...  */
889 static void print_insn_with_notes (pretty_printer *, const rtx_insn *);
890 
891 /* This recognizes rtx'en classified as expressions.  These are always
892    represent some action on values or results of other expression, that
893    may be stored in objects representing values.  */
894 
895 static void
print_exp(pretty_printer * pp,const_rtx x,int verbose)896 print_exp (pretty_printer *pp, const_rtx x, int verbose)
897 {
898   const char *st[4];
899   const char *fun;
900   rtx op[4];
901   int i;
902 
903   fun = (char *) 0;
904   for (i = 0; i < 4; i++)
905     {
906       st[i] = (char *) 0;
907       op[i] = NULL_RTX;
908     }
909 
910   switch (GET_CODE (x))
911     {
912     case PLUS:
913       op[0] = XEXP (x, 0);
914       if (CONST_INT_P (XEXP (x, 1))
915 	  && INTVAL (XEXP (x, 1)) < 0)
916 	{
917 	  st[1] = "-";
918 	  op[1] = GEN_INT (-INTVAL (XEXP (x, 1)));
919 	}
920       else
921 	{
922 	  st[1] = "+";
923 	  op[1] = XEXP (x, 1);
924 	}
925       break;
926     case LO_SUM:
927       op[0] = XEXP (x, 0);
928       st[1] = "+low(";
929       op[1] = XEXP (x, 1);
930       st[2] = ")";
931       break;
932     case MINUS:
933       op[0] = XEXP (x, 0);
934       st[1] = "-";
935       op[1] = XEXP (x, 1);
936       break;
937     case COMPARE:
938       fun = "cmp";
939       op[0] = XEXP (x, 0);
940       op[1] = XEXP (x, 1);
941       break;
942     case NEG:
943       st[0] = "-";
944       op[0] = XEXP (x, 0);
945       break;
946     case FMA:
947       st[0] = "{";
948       op[0] = XEXP (x, 0);
949       st[1] = "*";
950       op[1] = XEXP (x, 1);
951       st[2] = "+";
952       op[2] = XEXP (x, 2);
953       st[3] = "}";
954       break;
955     case MULT:
956       op[0] = XEXP (x, 0);
957       st[1] = "*";
958       op[1] = XEXP (x, 1);
959       break;
960     case DIV:
961       op[0] = XEXP (x, 0);
962       st[1] = "/";
963       op[1] = XEXP (x, 1);
964       break;
965     case UDIV:
966       fun = "udiv";
967       op[0] = XEXP (x, 0);
968       op[1] = XEXP (x, 1);
969       break;
970     case MOD:
971       op[0] = XEXP (x, 0);
972       st[1] = "%";
973       op[1] = XEXP (x, 1);
974       break;
975     case UMOD:
976       fun = "umod";
977       op[0] = XEXP (x, 0);
978       op[1] = XEXP (x, 1);
979       break;
980     case SMIN:
981       fun = "smin";
982       op[0] = XEXP (x, 0);
983       op[1] = XEXP (x, 1);
984       break;
985     case SMAX:
986       fun = "smax";
987       op[0] = XEXP (x, 0);
988       op[1] = XEXP (x, 1);
989       break;
990     case UMIN:
991       fun = "umin";
992       op[0] = XEXP (x, 0);
993       op[1] = XEXP (x, 1);
994       break;
995     case UMAX:
996       fun = "umax";
997       op[0] = XEXP (x, 0);
998       op[1] = XEXP (x, 1);
999       break;
1000     case NOT:
1001       st[0] = "!";
1002       op[0] = XEXP (x, 0);
1003       break;
1004     case AND:
1005       op[0] = XEXP (x, 0);
1006       st[1] = "&";
1007       op[1] = XEXP (x, 1);
1008       break;
1009     case IOR:
1010       op[0] = XEXP (x, 0);
1011       st[1] = "|";
1012       op[1] = XEXP (x, 1);
1013       break;
1014     case XOR:
1015       op[0] = XEXP (x, 0);
1016       st[1] = "^";
1017       op[1] = XEXP (x, 1);
1018       break;
1019     case ASHIFT:
1020       op[0] = XEXP (x, 0);
1021       st[1] = "<<";
1022       op[1] = XEXP (x, 1);
1023       break;
1024     case LSHIFTRT:
1025       op[0] = XEXP (x, 0);
1026       st[1] = " 0>>";
1027       op[1] = XEXP (x, 1);
1028       break;
1029     case ASHIFTRT:
1030       op[0] = XEXP (x, 0);
1031       st[1] = ">>";
1032       op[1] = XEXP (x, 1);
1033       break;
1034     case ROTATE:
1035       op[0] = XEXP (x, 0);
1036       st[1] = "<-<";
1037       op[1] = XEXP (x, 1);
1038       break;
1039     case ROTATERT:
1040       op[0] = XEXP (x, 0);
1041       st[1] = ">->";
1042       op[1] = XEXP (x, 1);
1043       break;
1044     case NE:
1045       op[0] = XEXP (x, 0);
1046       st[1] = "!=";
1047       op[1] = XEXP (x, 1);
1048       break;
1049     case EQ:
1050       op[0] = XEXP (x, 0);
1051       st[1] = "==";
1052       op[1] = XEXP (x, 1);
1053       break;
1054     case GE:
1055       op[0] = XEXP (x, 0);
1056       st[1] = ">=";
1057       op[1] = XEXP (x, 1);
1058       break;
1059     case GT:
1060       op[0] = XEXP (x, 0);
1061       st[1] = ">";
1062       op[1] = XEXP (x, 1);
1063       break;
1064     case LE:
1065       op[0] = XEXP (x, 0);
1066       st[1] = "<=";
1067       op[1] = XEXP (x, 1);
1068       break;
1069     case LT:
1070       op[0] = XEXP (x, 0);
1071       st[1] = "<";
1072       op[1] = XEXP (x, 1);
1073       break;
1074     case SIGN_EXTRACT:
1075       fun = (verbose) ? "sign_extract" : "sxt";
1076       op[0] = XEXP (x, 0);
1077       op[1] = XEXP (x, 1);
1078       op[2] = XEXP (x, 2);
1079       break;
1080     case ZERO_EXTRACT:
1081       fun = (verbose) ? "zero_extract" : "zxt";
1082       op[0] = XEXP (x, 0);
1083       op[1] = XEXP (x, 1);
1084       op[2] = XEXP (x, 2);
1085       break;
1086     case SIGN_EXTEND:
1087       fun = (verbose) ? "sign_extend" : "sxn";
1088       op[0] = XEXP (x, 0);
1089       break;
1090     case ZERO_EXTEND:
1091       fun = (verbose) ? "zero_extend" : "zxn";
1092       op[0] = XEXP (x, 0);
1093       break;
1094     case FLOAT_EXTEND:
1095       fun = (verbose) ? "float_extend" : "fxn";
1096       op[0] = XEXP (x, 0);
1097       break;
1098     case TRUNCATE:
1099       fun = (verbose) ? "trunc" : "trn";
1100       op[0] = XEXP (x, 0);
1101       break;
1102     case FLOAT_TRUNCATE:
1103       fun = (verbose) ? "float_trunc" : "ftr";
1104       op[0] = XEXP (x, 0);
1105       break;
1106     case FLOAT:
1107       fun = (verbose) ? "float" : "flt";
1108       op[0] = XEXP (x, 0);
1109       break;
1110     case UNSIGNED_FLOAT:
1111       fun = (verbose) ? "uns_float" : "ufl";
1112       op[0] = XEXP (x, 0);
1113       break;
1114     case FIX:
1115       fun = "fix";
1116       op[0] = XEXP (x, 0);
1117       break;
1118     case UNSIGNED_FIX:
1119       fun = (verbose) ? "uns_fix" : "ufx";
1120       op[0] = XEXP (x, 0);
1121       break;
1122     case PRE_DEC:
1123       st[0] = "--";
1124       op[0] = XEXP (x, 0);
1125       break;
1126     case PRE_INC:
1127       st[0] = "++";
1128       op[0] = XEXP (x, 0);
1129       break;
1130     case POST_DEC:
1131       op[0] = XEXP (x, 0);
1132       st[1] = "--";
1133       break;
1134     case POST_INC:
1135       op[0] = XEXP (x, 0);
1136       st[1] = "++";
1137       break;
1138     case PRE_MODIFY:
1139       st[0] = "pre ";
1140       op[0] = XEXP (XEXP (x, 1), 0);
1141       st[1] = "+=";
1142       op[1] = XEXP (XEXP (x, 1), 1);
1143       break;
1144     case POST_MODIFY:
1145       st[0] = "post ";
1146       op[0] = XEXP (XEXP (x, 1), 0);
1147       st[1] = "+=";
1148       op[1] = XEXP (XEXP (x, 1), 1);
1149       break;
1150     case CALL:
1151       st[0] = "call ";
1152       op[0] = XEXP (x, 0);
1153       if (verbose)
1154 	{
1155 	  st[1] = " argc:";
1156 	  op[1] = XEXP (x, 1);
1157 	}
1158       break;
1159     case IF_THEN_ELSE:
1160       st[0] = "{(";
1161       op[0] = XEXP (x, 0);
1162       st[1] = ")?";
1163       op[1] = XEXP (x, 1);
1164       st[2] = ":";
1165       op[2] = XEXP (x, 2);
1166       st[3] = "}";
1167       break;
1168     case TRAP_IF:
1169       fun = "trap_if";
1170       op[0] = TRAP_CONDITION (x);
1171       break;
1172     case PREFETCH:
1173       fun = "prefetch";
1174       op[0] = XEXP (x, 0);
1175       op[1] = XEXP (x, 1);
1176       op[2] = XEXP (x, 2);
1177       break;
1178     case UNSPEC:
1179     case UNSPEC_VOLATILE:
1180       {
1181 	pp_string (pp, "unspec");
1182 	if (GET_CODE (x) == UNSPEC_VOLATILE)
1183 	  pp_string (pp, "/v");
1184 	pp_left_bracket (pp);
1185 	for (i = 0; i < XVECLEN (x, 0); i++)
1186 	  {
1187 	    if (i != 0)
1188 	      pp_comma (pp);
1189 	    print_pattern (pp, XVECEXP (x, 0, i), verbose);
1190 	  }
1191 	pp_string (pp, "] ");
1192 	pp_decimal_int (pp, XINT (x, 1));
1193       }
1194       break;
1195     default:
1196       {
1197 	/* Most unhandled codes can be printed as pseudo-functions.  */
1198         if (GET_RTX_CLASS (GET_CODE (x)) == RTX_UNARY)
1199 	  {
1200 	    fun = GET_RTX_NAME (GET_CODE (x));
1201 	    op[0] = XEXP (x, 0);
1202 	  }
1203         else if (GET_RTX_CLASS (GET_CODE (x)) == RTX_COMPARE
1204 		 || GET_RTX_CLASS (GET_CODE (x)) == RTX_COMM_COMPARE
1205 		 || GET_RTX_CLASS (GET_CODE (x)) == RTX_BIN_ARITH
1206 		 || GET_RTX_CLASS (GET_CODE (x)) == RTX_COMM_ARITH)
1207 	  {
1208 	    fun = GET_RTX_NAME (GET_CODE (x));
1209 	    op[0] = XEXP (x, 0);
1210 	    op[1] = XEXP (x, 1);
1211 	  }
1212         else if (GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY)
1213 	  {
1214 	    fun = GET_RTX_NAME (GET_CODE (x));
1215 	    op[0] = XEXP (x, 0);
1216 	    op[1] = XEXP (x, 1);
1217 	    op[2] = XEXP (x, 2);
1218 	  }
1219 	else
1220 	  /* Give up, just print the RTX name.  */
1221 	  st[0] = GET_RTX_NAME (GET_CODE (x));
1222       }
1223       break;
1224     }
1225 
1226   /* Print this as a function?  */
1227   if (fun)
1228     {
1229       pp_string (pp, fun);
1230       pp_left_paren (pp);
1231     }
1232 
1233   for (i = 0; i < 4; i++)
1234     {
1235       if (st[i])
1236         pp_string (pp, st[i]);
1237 
1238       if (op[i])
1239 	{
1240 	  if (fun && i != 0)
1241 	    pp_comma (pp);
1242 	  print_value (pp, op[i], verbose);
1243 	}
1244     }
1245 
1246   if (fun)
1247     pp_right_paren (pp);
1248 }		/* print_exp */
1249 
1250 /* Prints rtxes, I customarily classified as values.  They're constants,
1251    registers, labels, symbols and memory accesses.  */
1252 
1253 void
print_value(pretty_printer * pp,const_rtx x,int verbose)1254 print_value (pretty_printer *pp, const_rtx x, int verbose)
1255 {
1256   char tmp[1024];
1257 
1258   if (!x)
1259     {
1260       pp_string (pp, "(nil)");
1261       return;
1262     }
1263   switch (GET_CODE (x))
1264     {
1265     case CONST_INT:
1266       pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
1267 		 (unsigned HOST_WIDE_INT) INTVAL (x));
1268       break;
1269 
1270     case CONST_WIDE_INT:
1271       {
1272 	const char *sep = "<";
1273 	int i;
1274 	for (i = CONST_WIDE_INT_NUNITS (x) - 1; i >= 0; i--)
1275 	  {
1276 	    pp_string (pp, sep);
1277 	    sep = ",";
1278 	    sprintf (tmp, HOST_WIDE_INT_PRINT_HEX,
1279 		     (unsigned HOST_WIDE_INT) CONST_WIDE_INT_ELT (x, i));
1280 	    pp_string (pp, tmp);
1281 	  }
1282         pp_greater (pp);
1283       }
1284       break;
1285 
1286     case CONST_DOUBLE:
1287       if (FLOAT_MODE_P (GET_MODE (x)))
1288 	{
1289 	  real_to_decimal (tmp, CONST_DOUBLE_REAL_VALUE (x),
1290 			   sizeof (tmp), 0, 1);
1291 	  pp_string (pp, tmp);
1292 	}
1293       else
1294 	pp_printf (pp, "<%wx,%wx>",
1295 		   (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x),
1296 		   (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x));
1297       break;
1298     case CONST_FIXED:
1299       fixed_to_decimal (tmp, CONST_FIXED_VALUE (x), sizeof (tmp));
1300       pp_string (pp, tmp);
1301       break;
1302     case CONST_STRING:
1303       pp_printf (pp, "\"%s\"", XSTR (x, 0));
1304       break;
1305     case SYMBOL_REF:
1306       pp_printf (pp, "`%s'", XSTR (x, 0));
1307       break;
1308     case LABEL_REF:
1309       pp_printf (pp, "L%d", INSN_UID (LABEL_REF_LABEL (x)));
1310       break;
1311     case CONST:
1312     case HIGH:
1313     case STRICT_LOW_PART:
1314       pp_printf (pp, "%s(", GET_RTX_NAME (GET_CODE (x)));
1315       print_value (pp, XEXP (x, 0), verbose);
1316       pp_right_paren (pp);
1317       break;
1318     case REG:
1319       if (REGNO (x) < FIRST_PSEUDO_REGISTER)
1320 	{
1321 	  if (ISDIGIT (reg_names[REGNO (x)][0]))
1322 	    pp_modulo (pp);
1323 	  pp_string (pp, reg_names[REGNO (x)]);
1324 	}
1325       else
1326 	pp_printf (pp, "r%d", REGNO (x));
1327       if (verbose)
1328 	pp_printf (pp, ":%s", GET_MODE_NAME (GET_MODE (x)));
1329       break;
1330     case SUBREG:
1331       print_value (pp, SUBREG_REG (x), verbose);
1332       pp_printf (pp, "#%d", SUBREG_BYTE (x));
1333       break;
1334     case SCRATCH:
1335     case CC0:
1336     case PC:
1337       pp_string (pp, GET_RTX_NAME (GET_CODE (x)));
1338       break;
1339     case MEM:
1340       pp_left_bracket (pp);
1341       print_value (pp, XEXP (x, 0), verbose);
1342       pp_right_bracket (pp);
1343       break;
1344     case DEBUG_EXPR:
1345       pp_printf (pp, "D#%i", DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x)));
1346       break;
1347     default:
1348       print_exp (pp, x, verbose);
1349       break;
1350     }
1351 }				/* print_value */
1352 
1353 /* The next step in insn detalization, its pattern recognition.  */
1354 
1355 void
print_pattern(pretty_printer * pp,const_rtx x,int verbose)1356 print_pattern (pretty_printer *pp, const_rtx x, int verbose)
1357 {
1358   if (! x)
1359     {
1360       pp_string (pp, "(nil)");
1361       return;
1362     }
1363 
1364   switch (GET_CODE (x))
1365     {
1366     case SET:
1367       print_value (pp, SET_DEST (x), verbose);
1368       pp_equal (pp);
1369       print_value (pp, SET_SRC (x), verbose);
1370       break;
1371     case RETURN:
1372     case SIMPLE_RETURN:
1373     case EH_RETURN:
1374       pp_string (pp, GET_RTX_NAME (GET_CODE (x)));
1375       break;
1376     case CALL:
1377       print_exp (pp, x, verbose);
1378       break;
1379     case CLOBBER:
1380     case USE:
1381       pp_printf (pp, "%s ", GET_RTX_NAME (GET_CODE (x)));
1382       print_value (pp, XEXP (x, 0), verbose);
1383       break;
1384     case VAR_LOCATION:
1385       pp_string (pp, "loc ");
1386       print_value (pp, PAT_VAR_LOCATION_LOC (x), verbose);
1387       break;
1388     case COND_EXEC:
1389       pp_left_paren (pp);
1390       if (GET_CODE (COND_EXEC_TEST (x)) == NE
1391 	  && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
1392 	print_value (pp, XEXP (COND_EXEC_TEST (x), 0), verbose);
1393       else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
1394 	       && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
1395 	{
1396 	  pp_exclamation (pp);
1397 	  print_value (pp, XEXP (COND_EXEC_TEST (x), 0), verbose);
1398 	}
1399       else
1400 	print_value (pp, COND_EXEC_TEST (x), verbose);
1401       pp_string (pp, ") ");
1402       print_pattern (pp, COND_EXEC_CODE (x), verbose);
1403       break;
1404     case PARALLEL:
1405       {
1406 	int i;
1407 
1408 	pp_left_brace (pp);
1409 	for (i = 0; i < XVECLEN (x, 0); i++)
1410 	  {
1411 	    print_pattern (pp, XVECEXP (x, 0, i), verbose);
1412 	    pp_semicolon (pp);
1413 	  }
1414 	pp_right_brace (pp);
1415       }
1416       break;
1417     case SEQUENCE:
1418       {
1419 	const rtx_sequence *seq = as_a <const rtx_sequence *> (x);
1420 	pp_string (pp, "sequence{");
1421 	if (INSN_P (seq->element (0)))
1422 	  {
1423 	    /* Print the sequence insns indented.  */
1424 	    const char * save_print_rtx_head = print_rtx_head;
1425 	    char indented_print_rtx_head[32];
1426 
1427 	    pp_newline (pp);
1428 	    gcc_assert (strlen (print_rtx_head) < sizeof (indented_print_rtx_head) - 4);
1429 	    snprintf (indented_print_rtx_head,
1430 		      sizeof (indented_print_rtx_head),
1431 		      "%s     ", print_rtx_head);
1432 	    print_rtx_head = indented_print_rtx_head;
1433 	    for (int i = 0; i < seq->len (); i++)
1434 	      print_insn_with_notes (pp, seq->insn (i));
1435 	    pp_printf (pp, "%s      ", save_print_rtx_head);
1436 	    print_rtx_head = save_print_rtx_head;
1437 	  }
1438 	else
1439 	  {
1440 	    for (int i = 0; i < seq->len (); i++)
1441 	      {
1442 		print_pattern (pp, seq->element (i), verbose);
1443 		pp_semicolon (pp);
1444 	      }
1445 	  }
1446 	pp_right_brace (pp);
1447       }
1448       break;
1449     case ASM_INPUT:
1450       pp_printf (pp, "asm {%s}", XSTR (x, 0));
1451       break;
1452     case ADDR_VEC:
1453       for (int i = 0; i < XVECLEN (x, 0); i++)
1454 	{
1455 	  print_value (pp, XVECEXP (x, 0, i), verbose);
1456 	  pp_semicolon (pp);
1457 	}
1458       break;
1459     case ADDR_DIFF_VEC:
1460       for (int i = 0; i < XVECLEN (x, 1); i++)
1461 	{
1462 	  print_value (pp, XVECEXP (x, 1, i), verbose);
1463 	  pp_semicolon (pp);
1464 	}
1465       break;
1466     case TRAP_IF:
1467       pp_string (pp, "trap_if ");
1468       print_value (pp, TRAP_CONDITION (x), verbose);
1469       break;
1470     case UNSPEC:
1471     case UNSPEC_VOLATILE:
1472       /* Fallthru -- leave UNSPECs to print_exp.  */
1473     default:
1474       print_value (pp, x, verbose);
1475     }
1476 }				/* print_pattern */
1477 
1478 /* This is the main function in slim rtl visualization mechanism.
1479 
1480    X is an insn, to be printed into PP.
1481 
1482    This function tries to print it properly in human-readable form,
1483    resembling assembler mnemonics (instead of the older Lisp-style
1484    form).
1485 
1486    If VERBOSE is TRUE, insns are printed with more complete (but
1487    longer) pattern names and with extra information, and prefixed
1488    with their INSN_UIDs.  */
1489 
1490 void
print_insn(pretty_printer * pp,const rtx_insn * x,int verbose)1491 print_insn (pretty_printer *pp, const rtx_insn *x, int verbose)
1492 {
1493   if (verbose)
1494     {
1495       /* Blech, pretty-print can't print integers with a specified width.  */
1496       char uid_prefix[32];
1497       snprintf (uid_prefix, sizeof uid_prefix, " %4d: ", INSN_UID (x));
1498       pp_string (pp, uid_prefix);
1499     }
1500 
1501   switch (GET_CODE (x))
1502     {
1503     case INSN:
1504       print_pattern (pp, PATTERN (x), verbose);
1505       break;
1506 
1507     case DEBUG_INSN:
1508       {
1509 	const char *name = "?";
1510 
1511 	if (DECL_P (INSN_VAR_LOCATION_DECL (x)))
1512 	  {
1513 	    tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (x));
1514 	    char idbuf[32];
1515 	    if (id)
1516 	      name = IDENTIFIER_POINTER (id);
1517 	    else if (TREE_CODE (INSN_VAR_LOCATION_DECL (x))
1518 		     == DEBUG_EXPR_DECL)
1519 	      {
1520 		sprintf (idbuf, "D#%i",
1521 			 DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (x)));
1522 		name = idbuf;
1523 	      }
1524 	    else
1525 	      {
1526 		sprintf (idbuf, "D.%i",
1527 			 DECL_UID (INSN_VAR_LOCATION_DECL (x)));
1528 		name = idbuf;
1529 	      }
1530 	  }
1531 	pp_printf (pp, "debug %s => ", name);
1532 	if (VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (x)))
1533 	  pp_string (pp, "optimized away");
1534 	else
1535 	  print_pattern (pp, INSN_VAR_LOCATION_LOC (x), verbose);
1536       }
1537       break;
1538 
1539     case JUMP_INSN:
1540       print_pattern (pp, PATTERN (x), verbose);
1541       break;
1542     case CALL_INSN:
1543       if (GET_CODE (PATTERN (x)) == PARALLEL)
1544         print_pattern (pp, XVECEXP (PATTERN (x), 0, 0), verbose);
1545       else
1546 	print_pattern (pp, PATTERN (x), verbose);
1547       break;
1548     case CODE_LABEL:
1549       pp_printf (pp, "L%d:", INSN_UID (x));
1550       break;
1551     case JUMP_TABLE_DATA:
1552       pp_string (pp, "jump_table_data{\n");
1553       print_pattern (pp, PATTERN (x), verbose);
1554       pp_right_brace (pp);
1555       break;
1556     case BARRIER:
1557       pp_string (pp, "barrier");
1558       break;
1559     case NOTE:
1560       {
1561 	pp_string (pp, GET_NOTE_INSN_NAME (NOTE_KIND (x)));
1562 	switch (NOTE_KIND (x))
1563 	  {
1564 	  case NOTE_INSN_EH_REGION_BEG:
1565 	  case NOTE_INSN_EH_REGION_END:
1566 	    pp_printf (pp, " %d", NOTE_EH_HANDLER (x));
1567 	    break;
1568 
1569 	  case NOTE_INSN_BLOCK_BEG:
1570 	  case NOTE_INSN_BLOCK_END:
1571 	    pp_printf (pp, " %d", BLOCK_NUMBER (NOTE_BLOCK (x)));
1572 	    break;
1573 
1574 	  case NOTE_INSN_BASIC_BLOCK:
1575 	    pp_printf (pp, " %d", NOTE_BASIC_BLOCK (x)->index);
1576 	    break;
1577 
1578 	  case NOTE_INSN_DELETED_LABEL:
1579 	  case NOTE_INSN_DELETED_DEBUG_LABEL:
1580 	    {
1581 	      const char *label = NOTE_DELETED_LABEL_NAME (x);
1582 	      if (label == NULL)
1583 		label = "";
1584 	      pp_printf (pp, " (\"%s\")", label);
1585 	    }
1586 	    break;
1587 
1588 	  case NOTE_INSN_VAR_LOCATION:
1589 	  case NOTE_INSN_CALL_ARG_LOCATION:
1590 	    pp_left_brace (pp);
1591 	    print_pattern (pp, NOTE_VAR_LOCATION (x), verbose);
1592 	    pp_right_brace (pp);
1593 	    break;
1594 
1595 	  default:
1596 	    break;
1597 	  }
1598 	break;
1599       }
1600     default:
1601       gcc_unreachable ();
1602     }
1603 }				/* print_insn */
1604 
1605 /* Pretty-print a slim dump of X (an insn) to PP, including any register
1606    note attached to the instruction.  */
1607 
1608 static void
print_insn_with_notes(pretty_printer * pp,const rtx_insn * x)1609 print_insn_with_notes (pretty_printer *pp, const rtx_insn *x)
1610 {
1611   pp_string (pp, print_rtx_head);
1612   print_insn (pp, x, 1);
1613   pp_newline (pp);
1614   if (INSN_P (x) && REG_NOTES (x))
1615     for (rtx note = REG_NOTES (x); note; note = XEXP (note, 1))
1616       {
1617 	pp_printf (pp, "%s      %s ", print_rtx_head,
1618 		   GET_REG_NOTE_NAME (REG_NOTE_KIND (note)));
1619 	if (GET_CODE (note) == INT_LIST)
1620 	  pp_printf (pp, "%d", XINT (note, 0));
1621 	else
1622 	  print_pattern (pp, XEXP (note, 0), 1);
1623 	pp_newline (pp);
1624       }
1625 }
1626 
1627 /* Print X, an RTL value node, to file F in slim format.  Include
1628    additional information if VERBOSE is nonzero.
1629 
1630    Value nodes are constants, registers, labels, symbols and
1631    memory.  */
1632 
1633 void
dump_value_slim(FILE * f,const_rtx x,int verbose)1634 dump_value_slim (FILE *f, const_rtx x, int verbose)
1635 {
1636   pretty_printer rtl_slim_pp;
1637   rtl_slim_pp.buffer->stream = f;
1638   print_value (&rtl_slim_pp, x, verbose);
1639   pp_flush (&rtl_slim_pp);
1640 }
1641 
1642 /* Emit a slim dump of X (an insn) to the file F, including any register
1643    note attached to the instruction.  */
1644 void
dump_insn_slim(FILE * f,const rtx_insn * x)1645 dump_insn_slim (FILE *f, const rtx_insn *x)
1646 {
1647   pretty_printer rtl_slim_pp;
1648   rtl_slim_pp.buffer->stream = f;
1649   print_insn_with_notes (&rtl_slim_pp, x);
1650   pp_flush (&rtl_slim_pp);
1651 }
1652 
1653 /* Same as above, but stop at LAST or when COUNT == 0.
1654    If COUNT < 0 it will stop only at LAST or NULL rtx.  */
1655 
1656 void
dump_rtl_slim(FILE * f,const rtx_insn * first,const rtx_insn * last,int count,int flags ATTRIBUTE_UNUSED)1657 dump_rtl_slim (FILE *f, const rtx_insn *first, const rtx_insn *last,
1658 	       int count, int flags ATTRIBUTE_UNUSED)
1659 {
1660   const rtx_insn *insn, *tail;
1661   pretty_printer rtl_slim_pp;
1662   rtl_slim_pp.buffer->stream = f;
1663 
1664   tail = last ? NEXT_INSN (last) : NULL;
1665   for (insn = first;
1666        (insn != NULL) && (insn != tail) && (count != 0);
1667        insn = NEXT_INSN (insn))
1668     {
1669       print_insn_with_notes (&rtl_slim_pp, insn);
1670       if (count > 0)
1671         count--;
1672     }
1673 
1674   pp_flush (&rtl_slim_pp);
1675 }
1676 
1677 /* Dumps basic block BB to pretty-printer PP in slim form and without and
1678    no indentation, for use as a label of a DOT graph record-node.  */
1679 
1680 void
rtl_dump_bb_for_graph(pretty_printer * pp,basic_block bb)1681 rtl_dump_bb_for_graph (pretty_printer *pp, basic_block bb)
1682 {
1683   rtx_insn *insn;
1684   bool first = true;
1685 
1686   /* TODO: inter-bb stuff.  */
1687   FOR_BB_INSNS (bb, insn)
1688     {
1689       if (! first)
1690 	{
1691 	  pp_bar (pp);
1692 	  pp_write_text_to_stream (pp);
1693 	}
1694       first = false;
1695       print_insn_with_notes (pp, insn);
1696       pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
1697     }
1698 }
1699 
1700 /* Pretty-print pattern X of some insn in non-verbose mode.
1701    Return a string pointer to the pretty-printer buffer.
1702 
1703    This function is only exported exists only to accommodate some older users
1704    of the slim RTL pretty printers.  Please do not use it for new code.  */
1705 
1706 const char *
str_pattern_slim(const_rtx x)1707 str_pattern_slim (const_rtx x)
1708 {
1709   pretty_printer rtl_slim_pp;
1710   print_pattern (&rtl_slim_pp, x, 0);
1711   return ggc_strdup (pp_formatted_text (&rtl_slim_pp));
1712 }
1713 
1714 /* Emit a slim dump of X (an insn) to stderr.  */
1715 extern void debug_insn_slim (const rtx_insn *);
1716 DEBUG_FUNCTION void
debug_insn_slim(const rtx_insn * x)1717 debug_insn_slim (const rtx_insn *x)
1718 {
1719   dump_insn_slim (stderr, x);
1720 }
1721 
1722 /* Same as above, but using dump_rtl_slim.  */
1723 extern void debug_rtl_slim (FILE *, const rtx_insn *, const rtx_insn *,
1724 			    int, int);
1725 DEBUG_FUNCTION void
debug_rtl_slim(const rtx_insn * first,const rtx_insn * last,int count,int flags)1726 debug_rtl_slim (const rtx_insn *first, const rtx_insn *last, int count,
1727 		int flags)
1728 {
1729   dump_rtl_slim (stderr, first, last, count, flags);
1730 }
1731 
1732 extern void debug_bb_slim (basic_block);
1733 DEBUG_FUNCTION void
debug_bb_slim(basic_block bb)1734 debug_bb_slim (basic_block bb)
1735 {
1736   dump_bb (stderr, bb, 0, TDF_SLIM | TDF_BLOCKS);
1737 }
1738 
1739 extern void debug_bb_n_slim (int);
1740 DEBUG_FUNCTION void
debug_bb_n_slim(int n)1741 debug_bb_n_slim (int n)
1742 {
1743   basic_block bb = BASIC_BLOCK_FOR_FN (cfun, n);
1744   debug_bb_slim (bb);
1745 }
1746 
1747 #endif
1748