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