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