00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "hconfig.h"
00024 #include "system.h"
00025 #include "rtl.h"
00026
00027
00028
00029 #undef ENABLE_TREE_CHECKING
00030 #include "tree.h"
00031 #include "real.h"
00032 #include "flags.h"
00033 #include "hard-reg-set.h"
00034 #include "basic-block.h"
00035
00036
00037
00038
00039 #ifndef DEBUG_PRINT_REG
00040 #define DEBUG_PRINT_REG(RTX, CODE, FILE) \
00041 fprintf ((FILE), "%d %s", REGNO (RTX), reg_names[REGNO (RTX)])
00042 #endif
00043
00044
00045
00046 #ifdef DEBUG_REGISTER_NAMES
00047 static const char * const debug_reg_names[] = DEBUG_REGISTER_NAMES;
00048 #define reg_names debug_reg_names
00049 #else
00050 const char * reg_names[] = REGISTER_NAMES;
00051 #endif
00052
00053 static FILE *outfile;
00054
00055 static int sawclose = 0;
00056
00057 static int indent;
00058
00059 static void print_rtx PARAMS ((rtx));
00060
00061
00062
00063
00064 const char *print_rtx_head = "";
00065
00066
00067
00068
00069 int flag_dump_unnumbered = 0;
00070
00071
00072 int flag_simple = 0;
00073
00074
00075 int dump_for_graph;
00076
00077
00078 static int debug_call_placeholder_verbose;
00079
00080 void
00081 print_mem_expr (outfile, expr)
00082 FILE *outfile;
00083 tree expr;
00084 {
00085 if (TREE_CODE (expr) == COMPONENT_REF)
00086 {
00087 if (TREE_OPERAND (expr, 0))
00088 print_mem_expr (outfile, TREE_OPERAND (expr, 0));
00089 else
00090 fputs (" <variable>", outfile);
00091 if (DECL_NAME (TREE_OPERAND (expr, 1)))
00092 fprintf (outfile, ".%s",
00093 IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (expr, 1))));
00094 }
00095 else if (TREE_CODE (expr) == INDIRECT_REF)
00096 {
00097 fputs (" (*", outfile);
00098 print_mem_expr (outfile, TREE_OPERAND (expr, 0));
00099 fputs (")", outfile);
00100 }
00101 else if (DECL_NAME (expr))
00102 fprintf (outfile, " %s", IDENTIFIER_POINTER (DECL_NAME (expr)));
00103 else if (TREE_CODE (expr) == RESULT_DECL)
00104 fputs (" <result>", outfile);
00105 else
00106 fputs (" <anonymous>", outfile);
00107 }
00108
00109
00110
00111 static void
00112 print_rtx (in_rtx)
00113 rtx in_rtx;
00114 {
00115 int i = 0;
00116 int j;
00117 const char *format_ptr;
00118 int is_insn;
00119 rtx tem;
00120
00121 if (sawclose)
00122 {
00123 if (flag_simple)
00124 fputc (' ', outfile);
00125 else
00126 fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, "");
00127 sawclose = 0;
00128 }
00129
00130 if (in_rtx == 0)
00131 {
00132 fputs ("(nil)", outfile);
00133 sawclose = 1;
00134 return;
00135 }
00136 else if (GET_CODE (in_rtx) > NUM_RTX_CODE)
00137 {
00138 fprintf (outfile, "(??? bad code %d\n)", GET_CODE (in_rtx));
00139 sawclose = 1;
00140 return;
00141 }
00142
00143 is_insn = INSN_P (in_rtx);
00144
00145
00146
00147 if (dump_for_graph
00148 && (is_insn || GET_CODE (in_rtx) == NOTE
00149 || GET_CODE (in_rtx) == CODE_LABEL || GET_CODE (in_rtx) == BARRIER))
00150 {
00151 i = 3;
00152 indent = 0;
00153 }
00154 else
00155 {
00156
00157 if (flag_simple && GET_CODE (in_rtx) == CONST_INT)
00158 fputc ('(', outfile);
00159 else
00160 fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
00161
00162 if (! flag_simple)
00163 {
00164 if (RTX_FLAG (in_rtx, in_struct))
00165 fputs ("/s", outfile);
00166
00167 if (RTX_FLAG (in_rtx, volatil))
00168 fputs ("/v", outfile);
00169
00170 if (RTX_FLAG (in_rtx, unchanging))
00171 fputs ("/u", outfile);
00172
00173 if (RTX_FLAG (in_rtx, integrated))
00174 fputs ("/i", outfile);
00175
00176 if (RTX_FLAG (in_rtx, frame_related))
00177 fputs ("/f", outfile);
00178
00179 if (RTX_FLAG (in_rtx, jump))
00180 fputs ("/j", outfile);
00181
00182 if (RTX_FLAG (in_rtx, call))
00183 fputs ("/c", outfile);
00184
00185 if (GET_MODE (in_rtx) != VOIDmode)
00186 {
00187
00188 if (GET_CODE (in_rtx) == EXPR_LIST
00189 || GET_CODE (in_rtx) == INSN_LIST)
00190 fprintf (outfile, ":%s",
00191 GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
00192 else
00193 fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
00194 }
00195 }
00196 }
00197
00198 #ifndef GENERATOR_FILE
00199 if (GET_CODE (in_rtx) == CONST_DOUBLE && FLOAT_MODE_P (GET_MODE (in_rtx)))
00200 i = 5;
00201 #endif
00202
00203
00204
00205 format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i;
00206 for (; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
00207 switch (*format_ptr++)
00208 {
00209 const char *str;
00210
00211 case 'T':
00212 str = XTMPL (in_rtx, i);
00213 goto string;
00214
00215 case 'S':
00216 case 's':
00217 str = XSTR (in_rtx, i);
00218 string:
00219
00220 if (str == 0)
00221 fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile);
00222 else
00223 {
00224 if (dump_for_graph)
00225 fprintf (outfile, " (\\\"%s\\\")", str);
00226 else
00227 fprintf (outfile, " (\"%s\")", str);
00228 }
00229 sawclose = 1;
00230 break;
00231
00232
00233
00234
00235 case '0':
00236 if (i == 1 && GET_CODE (in_rtx) == REG)
00237 {
00238 if (REGNO (in_rtx) != ORIGINAL_REGNO (in_rtx))
00239 fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx));
00240 break;
00241 }
00242 if (i == 4 && GET_CODE (in_rtx) == NOTE)
00243 {
00244 switch (NOTE_LINE_NUMBER (in_rtx))
00245 {
00246 case NOTE_INSN_EH_REGION_BEG:
00247 case NOTE_INSN_EH_REGION_END:
00248 if (flag_dump_unnumbered)
00249 fprintf (outfile, " #");
00250 else
00251 fprintf (outfile, " %d", NOTE_EH_HANDLER (in_rtx));
00252 sawclose = 1;
00253 break;
00254
00255 case NOTE_INSN_BLOCK_BEG:
00256 case NOTE_INSN_BLOCK_END:
00257 fprintf (outfile, " ");
00258 if (flag_dump_unnumbered)
00259 fprintf (outfile, "#");
00260 else
00261 fprintf (outfile, HOST_PTR_PRINTF,
00262 (char *) NOTE_BLOCK (in_rtx));
00263 sawclose = 1;
00264 break;
00265
00266 case NOTE_INSN_BASIC_BLOCK:
00267 {
00268 basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
00269 if (bb != 0)
00270 fprintf (outfile, " [bb %d]", bb->index);
00271 break;
00272 }
00273
00274 case NOTE_INSN_EXPECTED_VALUE:
00275 indent += 2;
00276 if (!sawclose)
00277 fprintf (outfile, " ");
00278 print_rtx (NOTE_EXPECTED_VALUE (in_rtx));
00279 indent -= 2;
00280 break;
00281
00282 case NOTE_INSN_DELETED_LABEL:
00283 if (NOTE_SOURCE_FILE (in_rtx))
00284 fprintf (outfile, " (\"%s\")", NOTE_SOURCE_FILE (in_rtx));
00285 else
00286 fprintf (outfile, " \"\"");
00287 break;
00288
00289 case NOTE_INSN_PREDICTION:
00290 if (NOTE_PREDICTION (in_rtx))
00291 fprintf (outfile, " [ %d %d ] ",
00292 (int)NOTE_PREDICTION_ALG (in_rtx),
00293 (int) NOTE_PREDICTION_FLAGS (in_rtx));
00294 else
00295 fprintf (outfile, " [ ERROR ]");
00296 break;
00297
00298 default:
00299 {
00300 const char * const str = X0STR (in_rtx, i);
00301
00302 if (NOTE_LINE_NUMBER (in_rtx) < 0)
00303 ;
00304 else if (str == 0)
00305 fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile);
00306 else
00307 {
00308 if (dump_for_graph)
00309 fprintf (outfile, " (\\\"%s\\\")", str);
00310 else
00311 fprintf (outfile, " (\"%s\")", str);
00312 }
00313 break;
00314 }
00315 }
00316 }
00317 break;
00318
00319 case 'e':
00320 do_e:
00321 indent += 2;
00322 if (!sawclose)
00323 fprintf (outfile, " ");
00324 print_rtx (XEXP (in_rtx, i));
00325 indent -= 2;
00326 break;
00327
00328 case 'E':
00329 case 'V':
00330 indent += 2;
00331 if (sawclose)
00332 {
00333 fprintf (outfile, "\n%s%*s",
00334 print_rtx_head, indent * 2, "");
00335 sawclose = 0;
00336 }
00337 fputs (" [", outfile);
00338 if (NULL != XVEC (in_rtx, i))
00339 {
00340 indent += 2;
00341 if (XVECLEN (in_rtx, i))
00342 sawclose = 1;
00343
00344 for (j = 0; j < XVECLEN (in_rtx, i); j++)
00345 print_rtx (XVECEXP (in_rtx, i, j));
00346
00347 indent -= 2;
00348 }
00349 if (sawclose)
00350 fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, "");
00351
00352 fputs ("]", outfile);
00353 sawclose = 1;
00354 indent -= 2;
00355 break;
00356
00357 case 'w':
00358 if (! flag_simple)
00359 fprintf (outfile, " ");
00360 fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, i));
00361 if (! flag_simple)
00362 {
00363 fprintf (outfile, " [");
00364 fprintf (outfile, HOST_WIDE_INT_PRINT_HEX, XWINT (in_rtx, i));
00365 fprintf (outfile, "]");
00366 }
00367 break;
00368
00369 case 'i':
00370 if (i == 6 && GET_CODE (in_rtx) == NOTE)
00371 {
00372
00373
00374 if (NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_DELETED_LABEL)
00375 fprintf (outfile, " %d", XINT (in_rtx, i));
00376 }
00377 else
00378 {
00379 int value = XINT (in_rtx, i);
00380 const char *name;
00381
00382 if (GET_CODE (in_rtx) == REG && value < FIRST_PSEUDO_REGISTER)
00383 {
00384 fputc (' ', outfile);
00385 DEBUG_PRINT_REG (in_rtx, 0, outfile);
00386 }
00387 else if (GET_CODE (in_rtx) == REG
00388 && value <= LAST_VIRTUAL_REGISTER)
00389 {
00390 if (value == VIRTUAL_INCOMING_ARGS_REGNUM)
00391 fprintf (outfile, " %d virtual-incoming-args", value);
00392 else if (value == VIRTUAL_STACK_VARS_REGNUM)
00393 fprintf (outfile, " %d virtual-stack-vars", value);
00394 else if (value == VIRTUAL_STACK_DYNAMIC_REGNUM)
00395 fprintf (outfile, " %d virtual-stack-dynamic", value);
00396 else if (value == VIRTUAL_OUTGOING_ARGS_REGNUM)
00397 fprintf (outfile, " %d virtual-outgoing-args", value);
00398 else if (value == VIRTUAL_CFA_REGNUM)
00399 fprintf (outfile, " %d virtual-cfa", value);
00400 else
00401 fprintf (outfile, " %d virtual-reg-%d", value,
00402 value-FIRST_VIRTUAL_REGISTER);
00403 }
00404 else if (flag_dump_unnumbered
00405 && (is_insn || GET_CODE (in_rtx) == NOTE))
00406 fputc ('#', outfile);
00407 else
00408 fprintf (outfile, " %d", value);
00409
00410 if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i)
00411 && XINT (in_rtx, i) >= 0
00412 && (name = get_insn_name (XINT (in_rtx, i))) != NULL)
00413 fprintf (outfile, " {%s}", name);
00414 sawclose = 0;
00415 }
00416 break;
00417
00418
00419
00420 case 'n':
00421 if (XINT (in_rtx, i) >= (int) NOTE_INSN_BIAS
00422 && XINT (in_rtx, i) < (int) NOTE_INSN_MAX)
00423 fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i)));
00424 else
00425 fprintf (outfile, " %d", XINT (in_rtx, i));
00426 sawclose = 0;
00427 break;
00428
00429 case 'u':
00430 if (XEXP (in_rtx, i) != NULL)
00431 {
00432 rtx sub = XEXP (in_rtx, i);
00433 enum rtx_code subc = GET_CODE (sub);
00434
00435 if (GET_CODE (in_rtx) == LABEL_REF)
00436 {
00437 if (subc == NOTE
00438 && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
00439 {
00440 if (flag_dump_unnumbered)
00441 fprintf (outfile, " [# deleted]");
00442 else
00443 fprintf (outfile, " [%d deleted]", INSN_UID (sub));
00444 sawclose = 0;
00445 break;
00446 }
00447
00448 if (subc != CODE_LABEL)
00449 goto do_e;
00450 }
00451
00452 if (flag_dump_unnumbered)
00453 fputs (" #", outfile);
00454 else
00455 fprintf (outfile, " %d", INSN_UID (sub));
00456 }
00457 else
00458 fputs (" 0", outfile);
00459 sawclose = 0;
00460 break;
00461
00462 case 'b':
00463 if (XBITMAP (in_rtx, i) == NULL)
00464 fputs (" {null}", outfile);
00465 else
00466 bitmap_print (outfile, XBITMAP (in_rtx, i), " {", "}");
00467 sawclose = 0;
00468 break;
00469
00470 case 't':
00471 putc (' ', outfile);
00472 fprintf (outfile, HOST_PTR_PRINTF, (char *) XTREE (in_rtx, i));
00473 break;
00474
00475 case '*':
00476 fputs (" Unknown", outfile);
00477 sawclose = 0;
00478 break;
00479
00480 case 'B':
00481 if (XBBDEF (in_rtx, i))
00482 fprintf (outfile, " %i", XBBDEF (in_rtx, i)->index);
00483 break;
00484
00485 default:
00486 fprintf (stderr,
00487 "switch format wrong in rtl.print_rtx(). format was: %c.\n",
00488 format_ptr[-1]);
00489 abort ();
00490 }
00491
00492 switch (GET_CODE (in_rtx))
00493 {
00494 #ifndef GENERATOR_FILE
00495 case MEM:
00496 fputs (" [", outfile);
00497 fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, MEM_ALIAS_SET (in_rtx));
00498
00499 if (MEM_EXPR (in_rtx))
00500 print_mem_expr (outfile, MEM_EXPR (in_rtx));
00501
00502 if (MEM_OFFSET (in_rtx))
00503 {
00504 fputc ('+', outfile);
00505 fprintf (outfile, HOST_WIDE_INT_PRINT_DEC,
00506 INTVAL (MEM_OFFSET (in_rtx)));
00507 }
00508
00509 if (MEM_SIZE (in_rtx))
00510 {
00511 fputs (" S", outfile);
00512 fprintf (outfile, HOST_WIDE_INT_PRINT_DEC,
00513 INTVAL (MEM_SIZE (in_rtx)));
00514 }
00515
00516 if (MEM_ALIGN (in_rtx) != 1)
00517 fprintf (outfile, " A%u", MEM_ALIGN (in_rtx));
00518
00519 fputc (']', outfile);
00520 break;
00521
00522 case CONST_DOUBLE:
00523 if (FLOAT_MODE_P (GET_MODE (in_rtx)))
00524 {
00525 char s[60];
00526
00527 real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
00528 sizeof (s), 0, 1);
00529 fprintf (outfile, " %s", s);
00530
00531 real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
00532 sizeof (s), 0, 1);
00533 fprintf (outfile, " [%s]", s);
00534 }
00535 break;
00536 #endif
00537
00538 case CODE_LABEL:
00539 fprintf (outfile, " [%d uses]", LABEL_NUSES (in_rtx));
00540 switch (LABEL_KIND (in_rtx))
00541 {
00542 case LABEL_NORMAL: break;
00543 case LABEL_STATIC_ENTRY: fputs (" [entry]", outfile); break;
00544 case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", outfile); break;
00545 case LABEL_WEAK_ENTRY: fputs (" [weak entry]", outfile); break;
00546 default: abort();
00547 }
00548 break;
00549
00550 case CALL_PLACEHOLDER:
00551 if (debug_call_placeholder_verbose)
00552 {
00553 fputs (" (cond [\n (const_string \"normal\") (sequence [", outfile);
00554 for (tem = XEXP (in_rtx, 0); tem != 0; tem = NEXT_INSN (tem))
00555 {
00556 fputs ("\n ", outfile);
00557 print_inline_rtx (outfile, tem, 4);
00558 }
00559
00560 tem = XEXP (in_rtx, 1);
00561 if (tem)
00562 fputs ("\n ])\n (const_string \"tail_call\") (sequence [",
00563 outfile);
00564 for (; tem != 0; tem = NEXT_INSN (tem))
00565 {
00566 fputs ("\n ", outfile);
00567 print_inline_rtx (outfile, tem, 4);
00568 }
00569
00570 tem = XEXP (in_rtx, 2);
00571 if (tem)
00572 fputs ("\n ])\n (const_string \"tail_recursion\") (sequence [",
00573 outfile);
00574 for (; tem != 0; tem = NEXT_INSN (tem))
00575 {
00576 fputs ("\n ", outfile);
00577 print_inline_rtx (outfile, tem, 4);
00578 }
00579
00580 fputs ("\n ])\n ])", outfile);
00581 break;
00582 }
00583
00584 for (tem = XEXP (in_rtx, 0); tem != 0; tem = NEXT_INSN (tem))
00585 if (GET_CODE (tem) == CALL_INSN)
00586 {
00587 fprintf (outfile, " ");
00588 print_rtx (tem);
00589 break;
00590 }
00591 break;
00592
00593 default:
00594 break;
00595 }
00596
00597 if (dump_for_graph
00598 && (is_insn || GET_CODE (in_rtx) == NOTE
00599 || GET_CODE (in_rtx) == CODE_LABEL || GET_CODE (in_rtx) == BARRIER))
00600 sawclose = 0;
00601 else
00602 {
00603 fputc (')', outfile);
00604 sawclose = 1;
00605 }
00606 }
00607
00608
00609
00610
00611 void
00612 print_inline_rtx (outf, x, ind)
00613 FILE *outf;
00614 rtx x;
00615 int ind;
00616 {
00617 int oldsaw = sawclose;
00618 int oldindent = indent;
00619
00620 sawclose = 0;
00621 indent = ind;
00622 outfile = outf;
00623 print_rtx (x);
00624 sawclose = oldsaw;
00625 indent = oldindent;
00626 }
00627
00628
00629
00630 void
00631 debug_rtx (x)
00632 rtx x;
00633 {
00634 outfile = stderr;
00635 sawclose = 0;
00636 print_rtx (x);
00637 fprintf (stderr, "\n");
00638 }
00639
00640
00641
00642
00643 int debug_rtx_count = 0;
00644
00645
00646
00647
00648
00649
00650
00651 void
00652 debug_rtx_list (x, n)
00653 rtx x;
00654 int n;
00655 {
00656 int i,count;
00657 rtx insn;
00658
00659 count = n == 0 ? 1 : n < 0 ? -n : n;
00660
00661
00662
00663 if (n < 0)
00664 for (i = count / 2; i > 0; i--)
00665 {
00666 if (PREV_INSN (x) == 0)
00667 break;
00668 x = PREV_INSN (x);
00669 }
00670
00671 for (i = count, insn = x; i > 0 && insn != 0; i--, insn = NEXT_INSN (insn))
00672 {
00673 debug_rtx (insn);
00674 fprintf (stderr, "\n");
00675 }
00676 }
00677
00678
00679
00680 void
00681 debug_rtx_range (start, end)
00682 rtx start, end;
00683 {
00684 while (1)
00685 {
00686 debug_rtx (start);
00687 fprintf (stderr, "\n");
00688 if (!start || start == end)
00689 break;
00690 start = NEXT_INSN (start);
00691 }
00692 }
00693
00694
00695
00696
00697
00698 rtx
00699 debug_rtx_find (x, uid)
00700 rtx x;
00701 int uid;
00702 {
00703 while (x != 0 && INSN_UID (x) != uid)
00704 x = NEXT_INSN (x);
00705 if (x != 0)
00706 {
00707 debug_rtx_list (x, debug_rtx_count);
00708 return x;
00709 }
00710 else
00711 {
00712 fprintf (stderr, "insn uid %d not found\n", uid);
00713 return 0;
00714 }
00715 }
00716
00717
00718
00719
00720
00721
00722
00723 void
00724 print_rtl (outf, rtx_first)
00725 FILE *outf;
00726 rtx rtx_first;
00727 {
00728 rtx tmp_rtx;
00729
00730 outfile = outf;
00731 sawclose = 0;
00732
00733 if (rtx_first == 0)
00734 {
00735 fputs (print_rtx_head, outf);
00736 fputs ("(nil)\n", outf);
00737 }
00738 else
00739 switch (GET_CODE (rtx_first))
00740 {
00741 case INSN:
00742 case JUMP_INSN:
00743 case CALL_INSN:
00744 case NOTE:
00745 case CODE_LABEL:
00746 case BARRIER:
00747 for (tmp_rtx = rtx_first; tmp_rtx != 0; tmp_rtx = NEXT_INSN (tmp_rtx))
00748 if (! flag_dump_unnumbered
00749 || GET_CODE (tmp_rtx) != NOTE || NOTE_LINE_NUMBER (tmp_rtx) < 0)
00750 {
00751 fputs (print_rtx_head, outfile);
00752 print_rtx (tmp_rtx);
00753 fprintf (outfile, "\n");
00754 }
00755 break;
00756
00757 default:
00758 fputs (print_rtx_head, outfile);
00759 print_rtx (rtx_first);
00760 }
00761 }
00762
00763
00764
00765
00766 int
00767 print_rtl_single (outf, x)
00768 FILE *outf;
00769 rtx x;
00770 {
00771 outfile = outf;
00772 sawclose = 0;
00773 if (! flag_dump_unnumbered
00774 || GET_CODE (x) != NOTE || NOTE_LINE_NUMBER (x) < 0)
00775 {
00776 fputs (print_rtx_head, outfile);
00777 print_rtx (x);
00778 putc ('\n', outf);
00779 return 1;
00780 }
00781 return 0;
00782 }
00783
00784
00785
00786
00787
00788 void
00789 print_simple_rtl (outf, x)
00790 FILE *outf;
00791 rtx x;
00792 {
00793 flag_simple = 1;
00794 print_rtl (outf, x);
00795 flag_simple = 0;
00796 }