Mercurial > hg > CbC > CbC_gcc
comparison gcc/print-rtl.c @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 77e2b8dfacca |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 /* Print RTL for GCC. | |
2 Copyright (C) 1987, 1988, 1992, 1997, 1998, 1999, 2000, 2002, 2003, | |
3 2004, 2005, 2007, 2008 | |
4 Free Software Foundation, Inc. | |
5 | |
6 This file is part of GCC. | |
7 | |
8 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 | |
10 Software Foundation; either version 3, or (at your option) any later | |
11 version. | |
12 | |
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with GCC; see the file COPYING3. If not see | |
20 <http://www.gnu.org/licenses/>. */ | |
21 | |
22 /* This file is compiled twice: once for the generator programs, | |
23 once for the compiler. */ | |
24 #ifdef GENERATOR_FILE | |
25 #include "bconfig.h" | |
26 #else | |
27 #include "config.h" | |
28 #endif | |
29 | |
30 #include "system.h" | |
31 #include "coretypes.h" | |
32 #include "tm.h" | |
33 #include "rtl.h" | |
34 | |
35 /* These headers all define things which are not available in | |
36 generator programs. */ | |
37 #ifndef GENERATOR_FILE | |
38 #include "tree.h" | |
39 #include "real.h" | |
40 #include "flags.h" | |
41 #include "hard-reg-set.h" | |
42 #include "basic-block.h" | |
43 #endif | |
44 | |
45 static FILE *outfile; | |
46 | |
47 static int sawclose = 0; | |
48 | |
49 static int indent; | |
50 | |
51 static void print_rtx (const_rtx); | |
52 | |
53 /* String printed at beginning of each RTL when it is dumped. | |
54 This string is set to ASM_COMMENT_START when the RTL is dumped in | |
55 the assembly output file. */ | |
56 const char *print_rtx_head = ""; | |
57 | |
58 /* Nonzero means suppress output of instruction numbers | |
59 in debugging dumps. | |
60 This must be defined here so that programs like gencodes can be linked. */ | |
61 int flag_dump_unnumbered = 0; | |
62 | |
63 /* Nonzero means use simplified format without flags, modes, etc. */ | |
64 int flag_simple = 0; | |
65 | |
66 /* Nonzero if we are dumping graphical description. */ | |
67 int dump_for_graph; | |
68 | |
69 #ifndef GENERATOR_FILE | |
70 static void | |
71 print_decl_name (FILE *outfile, const_tree node) | |
72 { | |
73 if (DECL_NAME (node)) | |
74 fputs (IDENTIFIER_POINTER (DECL_NAME (node)), outfile); | |
75 else | |
76 { | |
77 if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1) | |
78 fprintf (outfile, "L.%d", (int) LABEL_DECL_UID (node)); | |
79 else | |
80 { | |
81 char c = TREE_CODE (node) == CONST_DECL ? 'C' : 'D'; | |
82 fprintf (outfile, "%c.%u", c, DECL_UID (node)); | |
83 } | |
84 } | |
85 } | |
86 | |
87 void | |
88 print_mem_expr (FILE *outfile, const_tree expr) | |
89 { | |
90 if (TREE_CODE (expr) == COMPONENT_REF) | |
91 { | |
92 if (TREE_OPERAND (expr, 0)) | |
93 print_mem_expr (outfile, TREE_OPERAND (expr, 0)); | |
94 else | |
95 fputs (" <variable>", outfile); | |
96 fputc ('.', outfile); | |
97 print_decl_name (outfile, TREE_OPERAND (expr, 1)); | |
98 } | |
99 else if (TREE_CODE (expr) == INDIRECT_REF) | |
100 { | |
101 fputs (" (*", outfile); | |
102 print_mem_expr (outfile, TREE_OPERAND (expr, 0)); | |
103 fputs (")", outfile); | |
104 } | |
105 else if (TREE_CODE (expr) == ALIGN_INDIRECT_REF) | |
106 { | |
107 fputs (" (A*", outfile); | |
108 print_mem_expr (outfile, TREE_OPERAND (expr, 0)); | |
109 fputs (")", outfile); | |
110 } | |
111 else if (TREE_CODE (expr) == MISALIGNED_INDIRECT_REF) | |
112 { | |
113 fputs (" (M*", outfile); | |
114 print_mem_expr (outfile, TREE_OPERAND (expr, 0)); | |
115 fputs (")", outfile); | |
116 } | |
117 else if (TREE_CODE (expr) == RESULT_DECL) | |
118 fputs (" <result>", outfile); | |
119 else | |
120 { | |
121 fputc (' ', outfile); | |
122 print_decl_name (outfile, expr); | |
123 } | |
124 } | |
125 #endif | |
126 | |
127 /* Print IN_RTX onto OUTFILE. This is the recursive part of printing. */ | |
128 | |
129 static void | |
130 print_rtx (const_rtx in_rtx) | |
131 { | |
132 int i = 0; | |
133 int j; | |
134 const char *format_ptr; | |
135 int is_insn; | |
136 | |
137 if (sawclose) | |
138 { | |
139 if (flag_simple) | |
140 fputc (' ', outfile); | |
141 else | |
142 fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, ""); | |
143 sawclose = 0; | |
144 } | |
145 | |
146 if (in_rtx == 0) | |
147 { | |
148 fputs ("(nil)", outfile); | |
149 sawclose = 1; | |
150 return; | |
151 } | |
152 else if (GET_CODE (in_rtx) > NUM_RTX_CODE) | |
153 { | |
154 fprintf (outfile, "(??? bad code %d\n)", GET_CODE (in_rtx)); | |
155 sawclose = 1; | |
156 return; | |
157 } | |
158 | |
159 is_insn = INSN_P (in_rtx); | |
160 | |
161 /* When printing in VCG format we write INSNs, NOTE, LABEL, and BARRIER | |
162 in separate nodes and therefore have to handle them special here. */ | |
163 if (dump_for_graph | |
164 && (is_insn || NOTE_P (in_rtx) | |
165 || LABEL_P (in_rtx) || BARRIER_P (in_rtx))) | |
166 { | |
167 i = 3; | |
168 indent = 0; | |
169 } | |
170 else | |
171 { | |
172 /* Print name of expression code. */ | |
173 if (flag_simple && GET_CODE (in_rtx) == CONST_INT) | |
174 fputc ('(', outfile); | |
175 else | |
176 fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx))); | |
177 | |
178 if (! flag_simple) | |
179 { | |
180 if (RTX_FLAG (in_rtx, in_struct)) | |
181 fputs ("/s", outfile); | |
182 | |
183 if (RTX_FLAG (in_rtx, volatil)) | |
184 fputs ("/v", outfile); | |
185 | |
186 if (RTX_FLAG (in_rtx, unchanging)) | |
187 fputs ("/u", outfile); | |
188 | |
189 if (RTX_FLAG (in_rtx, frame_related)) | |
190 fputs ("/f", outfile); | |
191 | |
192 if (RTX_FLAG (in_rtx, jump)) | |
193 fputs ("/j", outfile); | |
194 | |
195 if (RTX_FLAG (in_rtx, call)) | |
196 fputs ("/c", outfile); | |
197 | |
198 if (RTX_FLAG (in_rtx, return_val)) | |
199 fputs ("/i", outfile); | |
200 | |
201 /* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */ | |
202 if (GET_CODE (in_rtx) == EXPR_LIST | |
203 || GET_CODE (in_rtx) == INSN_LIST) | |
204 fprintf (outfile, ":%s", | |
205 GET_REG_NOTE_NAME (GET_MODE (in_rtx))); | |
206 | |
207 /* For other rtl, print the mode if it's not VOID. */ | |
208 else if (GET_MODE (in_rtx) != VOIDmode) | |
209 fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx))); | |
210 } | |
211 } | |
212 | |
213 #ifndef GENERATOR_FILE | |
214 if (GET_CODE (in_rtx) == CONST_DOUBLE && FLOAT_MODE_P (GET_MODE (in_rtx))) | |
215 i = 5; | |
216 #endif | |
217 | |
218 /* Get the format string and skip the first elements if we have handled | |
219 them already. */ | |
220 format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i; | |
221 for (; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++) | |
222 switch (*format_ptr++) | |
223 { | |
224 const char *str; | |
225 | |
226 case 'T': | |
227 str = XTMPL (in_rtx, i); | |
228 goto string; | |
229 | |
230 case 'S': | |
231 case 's': | |
232 str = XSTR (in_rtx, i); | |
233 string: | |
234 | |
235 if (str == 0) | |
236 fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile); | |
237 else | |
238 { | |
239 if (dump_for_graph) | |
240 fprintf (outfile, " (\\\"%s\\\")", str); | |
241 else | |
242 fprintf (outfile, " (\"%s\")", str); | |
243 } | |
244 sawclose = 1; | |
245 break; | |
246 | |
247 /* 0 indicates a field for internal use that should not be printed. | |
248 An exception is the third field of a NOTE, where it indicates | |
249 that the field has several different valid contents. */ | |
250 case '0': | |
251 if (i == 1 && REG_P (in_rtx)) | |
252 { | |
253 if (REGNO (in_rtx) != ORIGINAL_REGNO (in_rtx)) | |
254 fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx)); | |
255 } | |
256 #ifndef GENERATOR_FILE | |
257 else if (i == 1 && GET_CODE (in_rtx) == SYMBOL_REF) | |
258 { | |
259 int flags = SYMBOL_REF_FLAGS (in_rtx); | |
260 if (flags) | |
261 fprintf (outfile, " [flags 0x%x]", flags); | |
262 } | |
263 else if (i == 2 && GET_CODE (in_rtx) == SYMBOL_REF) | |
264 { | |
265 tree decl = SYMBOL_REF_DECL (in_rtx); | |
266 if (decl) | |
267 print_node_brief (outfile, "", decl, 0); | |
268 } | |
269 #endif | |
270 else if (i == 4 && NOTE_P (in_rtx)) | |
271 { | |
272 switch (NOTE_KIND (in_rtx)) | |
273 { | |
274 case NOTE_INSN_EH_REGION_BEG: | |
275 case NOTE_INSN_EH_REGION_END: | |
276 if (flag_dump_unnumbered) | |
277 fprintf (outfile, " #"); | |
278 else | |
279 fprintf (outfile, " %d", NOTE_EH_HANDLER (in_rtx)); | |
280 sawclose = 1; | |
281 break; | |
282 | |
283 case NOTE_INSN_BLOCK_BEG: | |
284 case NOTE_INSN_BLOCK_END: | |
285 #ifndef GENERATOR_FILE | |
286 dump_addr (outfile, " ", NOTE_BLOCK (in_rtx)); | |
287 #endif | |
288 sawclose = 1; | |
289 break; | |
290 | |
291 case NOTE_INSN_BASIC_BLOCK: | |
292 { | |
293 #ifndef GENERATOR_FILE | |
294 basic_block bb = NOTE_BASIC_BLOCK (in_rtx); | |
295 if (bb != 0) | |
296 fprintf (outfile, " [bb %d]", bb->index); | |
297 #endif | |
298 break; | |
299 } | |
300 | |
301 case NOTE_INSN_DELETED_LABEL: | |
302 { | |
303 const char *label = NOTE_DELETED_LABEL_NAME (in_rtx); | |
304 if (label) | |
305 fprintf (outfile, " (\"%s\")", label); | |
306 else | |
307 fprintf (outfile, " \"\""); | |
308 } | |
309 break; | |
310 | |
311 case NOTE_INSN_SWITCH_TEXT_SECTIONS: | |
312 { | |
313 #ifndef GENERATOR_FILE | |
314 basic_block bb = NOTE_BASIC_BLOCK (in_rtx); | |
315 if (bb != 0) | |
316 fprintf (outfile, " [bb %d]", bb->index); | |
317 #endif | |
318 break; | |
319 } | |
320 | |
321 case NOTE_INSN_VAR_LOCATION: | |
322 #ifndef GENERATOR_FILE | |
323 fprintf (outfile, " ("); | |
324 print_mem_expr (outfile, NOTE_VAR_LOCATION_DECL (in_rtx)); | |
325 fprintf (outfile, " "); | |
326 print_rtx (NOTE_VAR_LOCATION_LOC (in_rtx)); | |
327 if (NOTE_VAR_LOCATION_STATUS (in_rtx) == | |
328 VAR_INIT_STATUS_UNINITIALIZED) | |
329 fprintf (outfile, " [uninit]"); | |
330 fprintf (outfile, ")"); | |
331 #endif | |
332 break; | |
333 | |
334 default: | |
335 break; | |
336 } | |
337 } | |
338 else if (i == 9 && JUMP_P (in_rtx) && XEXP (in_rtx, i) != NULL) | |
339 /* Output the JUMP_LABEL reference. */ | |
340 fprintf (outfile, "\n -> %d", INSN_UID (XEXP (in_rtx, i))); | |
341 break; | |
342 | |
343 case 'e': | |
344 do_e: | |
345 indent += 2; | |
346 if (!sawclose) | |
347 fprintf (outfile, " "); | |
348 print_rtx (XEXP (in_rtx, i)); | |
349 indent -= 2; | |
350 break; | |
351 | |
352 case 'E': | |
353 case 'V': | |
354 indent += 2; | |
355 if (sawclose) | |
356 { | |
357 fprintf (outfile, "\n%s%*s", | |
358 print_rtx_head, indent * 2, ""); | |
359 sawclose = 0; | |
360 } | |
361 fputs (" [", outfile); | |
362 if (NULL != XVEC (in_rtx, i)) | |
363 { | |
364 indent += 2; | |
365 if (XVECLEN (in_rtx, i)) | |
366 sawclose = 1; | |
367 | |
368 for (j = 0; j < XVECLEN (in_rtx, i); j++) | |
369 print_rtx (XVECEXP (in_rtx, i, j)); | |
370 | |
371 indent -= 2; | |
372 } | |
373 if (sawclose) | |
374 fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, ""); | |
375 | |
376 fputs ("]", outfile); | |
377 sawclose = 1; | |
378 indent -= 2; | |
379 break; | |
380 | |
381 case 'w': | |
382 if (! flag_simple) | |
383 fprintf (outfile, " "); | |
384 fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, i)); | |
385 if (! flag_simple) | |
386 fprintf (outfile, " [" HOST_WIDE_INT_PRINT_HEX "]", | |
387 (unsigned HOST_WIDE_INT) XWINT (in_rtx, i)); | |
388 break; | |
389 | |
390 case 'i': | |
391 if (i == 4 && INSN_P (in_rtx)) | |
392 { | |
393 #ifndef GENERATOR_FILE | |
394 /* Pretty-print insn locators. Ignore scoping as it is mostly | |
395 redundant with line number information and do not print anything | |
396 when there is no location information available. */ | |
397 if (INSN_LOCATOR (in_rtx) && insn_file (in_rtx)) | |
398 fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx)); | |
399 #endif | |
400 } | |
401 else if (i == 6 && NOTE_P (in_rtx)) | |
402 { | |
403 /* This field is only used for NOTE_INSN_DELETED_LABEL, and | |
404 other times often contains garbage from INSN->NOTE death. */ | |
405 if (NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_LABEL) | |
406 fprintf (outfile, " %d", XINT (in_rtx, i)); | |
407 } | |
408 else | |
409 { | |
410 int value = XINT (in_rtx, i); | |
411 const char *name; | |
412 | |
413 #ifndef GENERATOR_FILE | |
414 if (REG_P (in_rtx) && value < FIRST_PSEUDO_REGISTER) | |
415 fprintf (outfile, " %d %s", REGNO (in_rtx), | |
416 reg_names[REGNO (in_rtx)]); | |
417 else if (REG_P (in_rtx) | |
418 && value <= LAST_VIRTUAL_REGISTER) | |
419 { | |
420 if (value == VIRTUAL_INCOMING_ARGS_REGNUM) | |
421 fprintf (outfile, " %d virtual-incoming-args", value); | |
422 else if (value == VIRTUAL_STACK_VARS_REGNUM) | |
423 fprintf (outfile, " %d virtual-stack-vars", value); | |
424 else if (value == VIRTUAL_STACK_DYNAMIC_REGNUM) | |
425 fprintf (outfile, " %d virtual-stack-dynamic", value); | |
426 else if (value == VIRTUAL_OUTGOING_ARGS_REGNUM) | |
427 fprintf (outfile, " %d virtual-outgoing-args", value); | |
428 else if (value == VIRTUAL_CFA_REGNUM) | |
429 fprintf (outfile, " %d virtual-cfa", value); | |
430 else | |
431 fprintf (outfile, " %d virtual-reg-%d", value, | |
432 value-FIRST_VIRTUAL_REGISTER); | |
433 } | |
434 else | |
435 #endif | |
436 if (flag_dump_unnumbered | |
437 && (is_insn || NOTE_P (in_rtx))) | |
438 fputc ('#', outfile); | |
439 else | |
440 fprintf (outfile, " %d", value); | |
441 | |
442 #ifndef GENERATOR_FILE | |
443 if (REG_P (in_rtx) && REG_ATTRS (in_rtx)) | |
444 { | |
445 fputs (" [", outfile); | |
446 if (ORIGINAL_REGNO (in_rtx) != REGNO (in_rtx)) | |
447 fprintf (outfile, "orig:%i", ORIGINAL_REGNO (in_rtx)); | |
448 if (REG_EXPR (in_rtx)) | |
449 print_mem_expr (outfile, REG_EXPR (in_rtx)); | |
450 | |
451 if (REG_OFFSET (in_rtx)) | |
452 fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, | |
453 REG_OFFSET (in_rtx)); | |
454 fputs (" ]", outfile); | |
455 } | |
456 #endif | |
457 | |
458 if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i) | |
459 && XINT (in_rtx, i) >= 0 | |
460 && (name = get_insn_name (XINT (in_rtx, i))) != NULL) | |
461 fprintf (outfile, " {%s}", name); | |
462 sawclose = 0; | |
463 } | |
464 break; | |
465 | |
466 /* Print NOTE_INSN names rather than integer codes. */ | |
467 | |
468 case 'n': | |
469 fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i))); | |
470 sawclose = 0; | |
471 break; | |
472 | |
473 case 'u': | |
474 if (XEXP (in_rtx, i) != NULL) | |
475 { | |
476 rtx sub = XEXP (in_rtx, i); | |
477 enum rtx_code subc = GET_CODE (sub); | |
478 | |
479 if (GET_CODE (in_rtx) == LABEL_REF) | |
480 { | |
481 if (subc == NOTE | |
482 && NOTE_KIND (sub) == NOTE_INSN_DELETED_LABEL) | |
483 { | |
484 if (flag_dump_unnumbered) | |
485 fprintf (outfile, " [# deleted]"); | |
486 else | |
487 fprintf (outfile, " [%d deleted]", INSN_UID (sub)); | |
488 sawclose = 0; | |
489 break; | |
490 } | |
491 | |
492 if (subc != CODE_LABEL) | |
493 goto do_e; | |
494 } | |
495 | |
496 if (flag_dump_unnumbered) | |
497 fputs (" #", outfile); | |
498 else | |
499 fprintf (outfile, " %d", INSN_UID (sub)); | |
500 } | |
501 else | |
502 fputs (" 0", outfile); | |
503 sawclose = 0; | |
504 break; | |
505 | |
506 case 'b': | |
507 #ifndef GENERATOR_FILE | |
508 if (XBITMAP (in_rtx, i) == NULL) | |
509 fputs (" {null}", outfile); | |
510 else | |
511 bitmap_print (outfile, XBITMAP (in_rtx, i), " {", "}"); | |
512 #endif | |
513 sawclose = 0; | |
514 break; | |
515 | |
516 case 't': | |
517 #ifndef GENERATOR_FILE | |
518 dump_addr (outfile, " ", XTREE (in_rtx, i)); | |
519 #endif | |
520 break; | |
521 | |
522 case '*': | |
523 fputs (" Unknown", outfile); | |
524 sawclose = 0; | |
525 break; | |
526 | |
527 case 'B': | |
528 #ifndef GENERATOR_FILE | |
529 if (XBBDEF (in_rtx, i)) | |
530 fprintf (outfile, " %i", XBBDEF (in_rtx, i)->index); | |
531 #endif | |
532 break; | |
533 | |
534 default: | |
535 gcc_unreachable (); | |
536 } | |
537 | |
538 switch (GET_CODE (in_rtx)) | |
539 { | |
540 #ifndef GENERATOR_FILE | |
541 case MEM: | |
542 fprintf (outfile, " [" HOST_WIDE_INT_PRINT_DEC, | |
543 (HOST_WIDE_INT) MEM_ALIAS_SET (in_rtx)); | |
544 | |
545 if (MEM_EXPR (in_rtx)) | |
546 print_mem_expr (outfile, MEM_EXPR (in_rtx)); | |
547 | |
548 if (MEM_OFFSET (in_rtx)) | |
549 fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, | |
550 INTVAL (MEM_OFFSET (in_rtx))); | |
551 | |
552 if (MEM_SIZE (in_rtx)) | |
553 fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC, | |
554 INTVAL (MEM_SIZE (in_rtx))); | |
555 | |
556 if (MEM_ALIGN (in_rtx) != 1) | |
557 fprintf (outfile, " A%u", MEM_ALIGN (in_rtx)); | |
558 | |
559 fputc (']', outfile); | |
560 break; | |
561 | |
562 case CONST_DOUBLE: | |
563 if (FLOAT_MODE_P (GET_MODE (in_rtx))) | |
564 { | |
565 char s[60]; | |
566 | |
567 real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx), | |
568 sizeof (s), 0, 1); | |
569 fprintf (outfile, " %s", s); | |
570 | |
571 real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx), | |
572 sizeof (s), 0, 1); | |
573 fprintf (outfile, " [%s]", s); | |
574 } | |
575 break; | |
576 #endif | |
577 | |
578 case CODE_LABEL: | |
579 fprintf (outfile, " [%d uses]", LABEL_NUSES (in_rtx)); | |
580 switch (LABEL_KIND (in_rtx)) | |
581 { | |
582 case LABEL_NORMAL: break; | |
583 case LABEL_STATIC_ENTRY: fputs (" [entry]", outfile); break; | |
584 case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", outfile); break; | |
585 case LABEL_WEAK_ENTRY: fputs (" [weak entry]", outfile); break; | |
586 default: gcc_unreachable (); | |
587 } | |
588 break; | |
589 | |
590 default: | |
591 break; | |
592 } | |
593 | |
594 if (dump_for_graph | |
595 && (is_insn || NOTE_P (in_rtx) | |
596 || LABEL_P (in_rtx) || BARRIER_P (in_rtx))) | |
597 sawclose = 0; | |
598 else | |
599 { | |
600 fputc (')', outfile); | |
601 sawclose = 1; | |
602 } | |
603 } | |
604 | |
605 /* Print an rtx on the current line of FILE. Initially indent IND | |
606 characters. */ | |
607 | |
608 void | |
609 print_inline_rtx (FILE *outf, const_rtx x, int ind) | |
610 { | |
611 int oldsaw = sawclose; | |
612 int oldindent = indent; | |
613 | |
614 sawclose = 0; | |
615 indent = ind; | |
616 outfile = outf; | |
617 print_rtx (x); | |
618 sawclose = oldsaw; | |
619 indent = oldindent; | |
620 } | |
621 | |
622 /* Call this function from the debugger to see what X looks like. */ | |
623 | |
624 void | |
625 debug_rtx (const_rtx x) | |
626 { | |
627 outfile = stderr; | |
628 sawclose = 0; | |
629 print_rtx (x); | |
630 fprintf (stderr, "\n"); | |
631 } | |
632 | |
633 /* Count of rtx's to print with debug_rtx_list. | |
634 This global exists because gdb user defined commands have no arguments. */ | |
635 | |
636 int debug_rtx_count = 0; /* 0 is treated as equivalent to 1 */ | |
637 | |
638 /* Call this function to print list from X on. | |
639 | |
640 N is a count of the rtx's to print. Positive values print from the specified | |
641 rtx on. Negative values print a window around the rtx. | |
642 EG: -5 prints 2 rtx's on either side (in addition to the specified rtx). */ | |
643 | |
644 void | |
645 debug_rtx_list (const_rtx x, int n) | |
646 { | |
647 int i,count; | |
648 const_rtx insn; | |
649 | |
650 count = n == 0 ? 1 : n < 0 ? -n : n; | |
651 | |
652 /* If we are printing a window, back up to the start. */ | |
653 | |
654 if (n < 0) | |
655 for (i = count / 2; i > 0; i--) | |
656 { | |
657 if (PREV_INSN (x) == 0) | |
658 break; | |
659 x = PREV_INSN (x); | |
660 } | |
661 | |
662 for (i = count, insn = x; i > 0 && insn != 0; i--, insn = NEXT_INSN (insn)) | |
663 { | |
664 debug_rtx (insn); | |
665 fprintf (stderr, "\n"); | |
666 } | |
667 } | |
668 | |
669 /* Call this function to print an rtx list from START to END inclusive. */ | |
670 | |
671 void | |
672 debug_rtx_range (const_rtx start, const_rtx end) | |
673 { | |
674 while (1) | |
675 { | |
676 debug_rtx (start); | |
677 fprintf (stderr, "\n"); | |
678 if (!start || start == end) | |
679 break; | |
680 start = NEXT_INSN (start); | |
681 } | |
682 } | |
683 | |
684 /* Call this function to search an rtx list to find one with insn uid UID, | |
685 and then call debug_rtx_list to print it, using DEBUG_RTX_COUNT. | |
686 The found insn is returned to enable further debugging analysis. */ | |
687 | |
688 const_rtx | |
689 debug_rtx_find (const_rtx x, int uid) | |
690 { | |
691 while (x != 0 && INSN_UID (x) != uid) | |
692 x = NEXT_INSN (x); | |
693 if (x != 0) | |
694 { | |
695 debug_rtx_list (x, debug_rtx_count); | |
696 return x; | |
697 } | |
698 else | |
699 { | |
700 fprintf (stderr, "insn uid %d not found\n", uid); | |
701 return 0; | |
702 } | |
703 } | |
704 | |
705 /* External entry point for printing a chain of insns | |
706 starting with RTX_FIRST onto file OUTF. | |
707 A blank line separates insns. | |
708 | |
709 If RTX_FIRST is not an insn, then it alone is printed, with no newline. */ | |
710 | |
711 void | |
712 print_rtl (FILE *outf, const_rtx rtx_first) | |
713 { | |
714 const_rtx tmp_rtx; | |
715 | |
716 outfile = outf; | |
717 sawclose = 0; | |
718 | |
719 if (rtx_first == 0) | |
720 { | |
721 fputs (print_rtx_head, outf); | |
722 fputs ("(nil)\n", outf); | |
723 } | |
724 else | |
725 switch (GET_CODE (rtx_first)) | |
726 { | |
727 case INSN: | |
728 case JUMP_INSN: | |
729 case CALL_INSN: | |
730 case NOTE: | |
731 case CODE_LABEL: | |
732 case BARRIER: | |
733 for (tmp_rtx = rtx_first; tmp_rtx != 0; tmp_rtx = NEXT_INSN (tmp_rtx)) | |
734 { | |
735 fputs (print_rtx_head, outfile); | |
736 print_rtx (tmp_rtx); | |
737 fprintf (outfile, "\n"); | |
738 } | |
739 break; | |
740 | |
741 default: | |
742 fputs (print_rtx_head, outfile); | |
743 print_rtx (rtx_first); | |
744 } | |
745 } | |
746 | |
747 /* Like print_rtx, except specify a file. */ | |
748 /* Return nonzero if we actually printed anything. */ | |
749 | |
750 int | |
751 print_rtl_single (FILE *outf, const_rtx x) | |
752 { | |
753 outfile = outf; | |
754 sawclose = 0; | |
755 fputs (print_rtx_head, outfile); | |
756 print_rtx (x); | |
757 putc ('\n', outf); | |
758 return 1; | |
759 } | |
760 | |
761 | |
762 /* Like print_rtl except without all the detail; for example, | |
763 if RTX is a CONST_INT then print in decimal format. */ | |
764 | |
765 void | |
766 print_simple_rtl (FILE *outf, const_rtx x) | |
767 { | |
768 flag_simple = 1; | |
769 print_rtl (outf, x); | |
770 flag_simple = 0; | |
771 } |