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