comparison gcc/print-rtl.c @ 111:04ced10e8804

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