1/* Print RTL for GNU C Compiler. 2 Copyright (C) 1987, 1988, 1992, 1997, 1998 Free Software Foundation, Inc. 3 4This file is part of GNU CC. 5 6GNU CC is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 2, or (at your option) 9any later version. 10 11GNU CC is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License 17along with GNU CC; see the file COPYING. If not, write to 18the Free Software Foundation, 59 Temple Place - Suite 330, 19Boston, MA 02111-1307, USA. */ 20 21 22#include "config.h" 23#include "system.h" 24#include "rtl.h" 25#include "real.h" 26#include "flags.h" 27#include "basic-block.h" 28 29 30/* How to print out a register name. 31 We don't use PRINT_REG because some definitions of PRINT_REG 32 don't work here. */ 33#ifndef DEBUG_PRINT_REG 34#define DEBUG_PRINT_REG(RTX, CODE, FILE) \ 35 fprintf ((FILE), "%d %s", REGNO (RTX), reg_names[REGNO (RTX)]) 36#endif 37 38/* Array containing all of the register names */ 39 40#ifdef DEBUG_REGISTER_NAMES 41static char *reg_names[] = DEBUG_REGISTER_NAMES; 42#else 43static char *reg_names[] = REGISTER_NAMES; 44#endif 45 46static FILE *outfile; 47 48static const char xspaces[] = " "; 49 50static int sawclose = 0; 51 52static int indent; 53 54/* Names for patterns. Non-zero only when linked with insn-output.c. */ 55 56extern char **insn_name_ptr; 57 58static void print_rtx PROTO ((rtx)); 59 60/* Nonzero means suppress output of instruction numbers and line number 61 notes in debugging dumps. 62 This must be defined here so that programs like gencodes can be linked. */ 63int flag_dump_unnumbered = 0; 64 65/* Nonzero if we are dumping graphical description. */ 66int dump_for_graph; 67 68/* Print IN_RTX onto OUTFILE. This is the recursive part of printing. */ 69 70static void 71print_rtx (in_rtx) 72 register rtx in_rtx; 73{ 74 register int i = 0; 75 register int j; 76 register char *format_ptr; 77 register int is_insn; 78 79 if (sawclose) 80 { 81 fprintf (outfile, "\n%s", 82 (xspaces + (sizeof xspaces - 1 - indent * 2))); 83 sawclose = 0; 84 } 85 86 if (in_rtx == 0) 87 { 88 fputs ("(nil)", outfile); 89 sawclose = 1; 90 return; 91 } 92 93 is_insn = (GET_RTX_CLASS (GET_CODE (in_rtx)) == 'i'); 94 95 /* When printing in VCG format we write INSNs, NOTE, LABEL, and BARRIER 96 in separate nodes and therefore have to handle them special here. */ 97 if (dump_for_graph && 98 (is_insn || GET_CODE (in_rtx) == NOTE || GET_CODE (in_rtx) == CODE_LABEL 99 || GET_CODE (in_rtx) == BARRIER)) 100 { 101 i = 3; 102 indent = 0; 103 } 104 else 105 { 106 /* print name of expression code */ 107 fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx))); 108 109 if (in_rtx->in_struct) 110 fputs ("/s", outfile); 111 112 if (in_rtx->volatil) 113 fputs ("/v", outfile); 114 115 if (in_rtx->unchanging) 116 fputs ("/u", outfile); 117 118 if (in_rtx->integrated) 119 fputs ("/i", outfile); 120 121 if (in_rtx->frame_related) 122 fputs ("/f", outfile); 123 124 if (in_rtx->jump) 125 fputs ("/j", outfile); 126 127 if (in_rtx->call) 128 fputs ("/c", outfile); 129 130 if (GET_MODE (in_rtx) != VOIDmode) 131 { 132 /* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */ 133 if (GET_CODE (in_rtx) == EXPR_LIST || GET_CODE (in_rtx) == INSN_LIST) 134 fprintf (outfile, ":%s", GET_REG_NOTE_NAME (GET_MODE (in_rtx))); 135 else 136 fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx))); 137 } 138 } 139 140 /* Get the format string and skip the first elements if we have handled 141 them already. */ 142 format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i; 143 144 for (; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++) 145 switch (*format_ptr++) 146 { 147 case 'S': 148 case 's': 149 if (i == 3 && GET_CODE (in_rtx) == NOTE 150 && (NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_EH_REGION_BEG 151 || NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_EH_REGION_END 152 || NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_BLOCK_BEG 153 || NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_BLOCK_END)) 154 { 155 fprintf (outfile, " %d", NOTE_BLOCK_NUMBER (in_rtx)); 156 sawclose = 1; 157 break; 158 } 159 160 if (i == 3 && GET_CODE (in_rtx) == NOTE 161 && (NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_RANGE_START 162 || NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_RANGE_END 163 || NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_LIVE)) 164 { 165 indent += 2; 166 if (!sawclose) 167 fprintf (outfile, " "); 168 print_rtx (NOTE_RANGE_INFO (in_rtx)); 169 indent -= 2; 170 break; 171 } 172 173 if (i == 3 && GET_CODE (in_rtx) == NOTE 174 && NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_BASIC_BLOCK) 175 { 176 basic_block bb = NOTE_BASIC_BLOCK (in_rtx); 177 fprintf (outfile, " [bb %d]", bb->index); 178 break; 179 } 180 181 if (XSTR (in_rtx, i) == 0) 182 fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile); 183 else 184 fprintf (outfile, dump_for_graph ? " (\\\"%s\\\")" : " (\"%s\")", 185 XSTR (in_rtx, i)); 186 sawclose = 1; 187 break; 188 189 /* 0 indicates a field for internal use that should not be printed. */ 190 case '0': 191 break; 192 193 case 'e': 194 indent += 2; 195 if (!sawclose) 196 fprintf (outfile, " "); 197 print_rtx (XEXP (in_rtx, i)); 198 indent -= 2; 199 break; 200 201 case 'E': 202 case 'V': 203 indent += 2; 204 if (sawclose) 205 { 206 fprintf (outfile, "\n%s", 207 (xspaces + (sizeof xspaces - 1 - indent * 2))); 208 sawclose = 0; 209 } 210 fputs ("[ ", outfile); 211 if (NULL != XVEC (in_rtx, i)) 212 { 213 indent += 2; 214 if (XVECLEN (in_rtx, i)) 215 sawclose = 1; 216 217 for (j = 0; j < XVECLEN (in_rtx, i); j++) 218 print_rtx (XVECEXP (in_rtx, i, j)); 219 220 indent -= 2; 221 } 222 if (sawclose) 223 fprintf (outfile, "\n%s", 224 (xspaces + (sizeof xspaces - 1 - indent * 2))); 225 226 fputs ("] ", outfile); 227 sawclose = 1; 228 indent -= 2; 229 break; 230 231 case 'w': 232 fprintf (outfile, " "); 233 fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, i)); 234 fprintf (outfile, " ["); 235 fprintf (outfile, HOST_WIDE_INT_PRINT_HEX, XWINT (in_rtx, i)); 236 fprintf (outfile, "]"); 237 break; 238 239 case 'i': 240 { 241 register int value = XINT (in_rtx, i); 242 243 if (GET_CODE (in_rtx) == REG && value < FIRST_PSEUDO_REGISTER) 244 { 245 fputc (' ', outfile); 246 DEBUG_PRINT_REG (in_rtx, 0, outfile); 247 } 248 else if (flag_dump_unnumbered 249 && (is_insn || GET_CODE (in_rtx) == NOTE)) 250 fputc ('#', outfile); 251 else 252 fprintf (outfile, " %d", value); 253 } 254 if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i) 255 && insn_name_ptr 256 && XINT (in_rtx, i) >= 0) 257 fprintf (outfile, " {%s}", insn_name_ptr[XINT (in_rtx, i)]); 258 sawclose = 0; 259 break; 260 261 /* Print NOTE_INSN names rather than integer codes. */ 262 263 case 'n': 264 if (XINT (in_rtx, i) <= 0) 265 fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i))); 266 else 267 fprintf (outfile, " %d", XINT (in_rtx, i)); 268 sawclose = 0; 269 break; 270 271 case 'u': 272 if (XEXP (in_rtx, i) != NULL) 273 { 274 if (flag_dump_unnumbered) 275 fputc ('#', outfile); 276 else 277 fprintf (outfile, " %d", INSN_UID (XEXP (in_rtx, i))); 278 } 279 else 280 fputs (" 0", outfile); 281 sawclose = 0; 282 break; 283 284 case 'b': 285 if (XBITMAP (in_rtx, i) == NULL) 286 fputs (" {null}", outfile); 287 else 288 bitmap_print (outfile, XBITMAP (in_rtx, i), " {", "}"); 289 sawclose = 0; 290 break; 291 292 case 't': 293 putc (' ', outfile); 294 fprintf (outfile, HOST_PTR_PRINTF, (char *) XTREE (in_rtx, i)); 295 break; 296 297 case '*': 298 fputs (" Unknown", outfile); 299 sawclose = 0; 300 break; 301 302 default: 303 fprintf (stderr, 304 "switch format wrong in rtl.print_rtx(). format was: %c.\n", 305 format_ptr[-1]); 306 abort (); 307 } 308 309 if (GET_CODE (in_rtx) == MEM) 310 fprintf (outfile, " %d", MEM_ALIAS_SET (in_rtx)); 311 312#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT && LONG_DOUBLE_TYPE_SIZE == 64 313 if (GET_CODE (in_rtx) == CONST_DOUBLE && FLOAT_MODE_P (GET_MODE (in_rtx))) 314 { 315 double val; 316 REAL_VALUE_FROM_CONST_DOUBLE (val, in_rtx); 317 fprintf (outfile, " [%.16g]", val); 318 } 319#endif 320 321 if (GET_CODE (in_rtx) == CODE_LABEL) 322 fprintf (outfile, " [num uses: %d]", LABEL_NUSES (in_rtx)); 323 324 if (dump_for_graph 325 && (is_insn || GET_CODE (in_rtx) == NOTE 326 || GET_CODE (in_rtx) == CODE_LABEL || GET_CODE (in_rtx) == BARRIER)) 327 sawclose = 0; 328 else 329 { 330 fputc (')', outfile); 331 sawclose = 1; 332 } 333} 334 335/* Print an rtx on the current line of FILE. Initially indent IND 336 characters. */ 337 338void 339print_inline_rtx (outf, x, ind) 340 FILE *outf; 341 rtx x; 342 int ind; 343{ 344 int oldsaw = sawclose; 345 int oldindent = indent; 346 347 sawclose = 0; 348 indent = ind; 349 outfile = outf; 350 print_rtx (x); 351 sawclose = oldsaw; 352 indent = oldindent; 353} 354 355/* Call this function from the debugger to see what X looks like. */ 356 357void 358debug_rtx (x) 359 rtx x; 360{ 361 outfile = stderr; 362 print_rtx (x); 363 fprintf (stderr, "\n"); 364} 365 366/* Count of rtx's to print with debug_rtx_list. 367 This global exists because gdb user defined commands have no arguments. */ 368 369int debug_rtx_count = 0; /* 0 is treated as equivalent to 1 */ 370 371/* Call this function to print list from X on. 372 373 N is a count of the rtx's to print. Positive values print from the specified 374 rtx on. Negative values print a window around the rtx. 375 EG: -5 prints 2 rtx's on either side (in addition to the specified rtx). */ 376 377void 378debug_rtx_list (x, n) 379 rtx x; 380 int n; 381{ 382 int i,count; 383 rtx insn; 384 385 count = n == 0 ? 1 : n < 0 ? -n : n; 386 387 /* If we are printing a window, back up to the start. */ 388 389 if (n < 0) 390 for (i = count / 2; i > 0; i--) 391 { 392 if (PREV_INSN (x) == 0) 393 break; 394 x = PREV_INSN (x); 395 } 396 397 for (i = count, insn = x; i > 0 && insn != 0; i--, insn = NEXT_INSN (insn)) 398 debug_rtx (insn); 399} 400 401/* Call this function to search an rtx list to find one with insn uid UID, 402 and then call debug_rtx_list to print it, using DEBUG_RTX_COUNT. 403 The found insn is returned to enable further debugging analysis. */ 404 405rtx 406debug_rtx_find (x, uid) 407 rtx x; 408 int uid; 409{ 410 while (x != 0 && INSN_UID (x) != uid) 411 x = NEXT_INSN (x); 412 if (x != 0) 413 { 414 debug_rtx_list (x, debug_rtx_count); 415 return x; 416 } 417 else 418 { 419 fprintf (stderr, "insn uid %d not found\n", uid); 420 return 0; 421 } 422} 423 424/* External entry point for printing a chain of insns 425 starting with RTX_FIRST onto file OUTF. 426 A blank line separates insns. 427 428 If RTX_FIRST is not an insn, then it alone is printed, with no newline. */ 429 430void 431print_rtl (outf, rtx_first) 432 FILE *outf; 433 rtx rtx_first; 434{ 435 register rtx tmp_rtx; 436 437 outfile = outf; 438 sawclose = 0; 439 440 if (rtx_first == 0) 441 fputs ("(nil)\n", outf); 442 else 443 switch (GET_CODE (rtx_first)) 444 { 445 case INSN: 446 case JUMP_INSN: 447 case CALL_INSN: 448 case NOTE: 449 case CODE_LABEL: 450 case BARRIER: 451 for (tmp_rtx = rtx_first; NULL != tmp_rtx; tmp_rtx = NEXT_INSN (tmp_rtx)) 452 { 453 if (! flag_dump_unnumbered 454 || GET_CODE (tmp_rtx) != NOTE 455 || NOTE_LINE_NUMBER (tmp_rtx) < 0) 456 { 457 print_rtx (tmp_rtx); 458 fprintf (outfile, "\n"); 459 } 460 } 461 break; 462 463 default: 464 print_rtx (rtx_first); 465 } 466} 467 468/* Like print_rtx, except specify a file. */ 469/* Return nonzero if we actually printed anything. */ 470 471int 472print_rtl_single (outf, x) 473 FILE *outf; 474 rtx x; 475{ 476 outfile = outf; 477 sawclose = 0; 478 if (! flag_dump_unnumbered 479 || GET_CODE (x) != NOTE || NOTE_LINE_NUMBER (x) < 0) 480 { 481 print_rtx (x); 482 putc ('\n', outf); 483 return 1; 484 } 485 return 0; 486} 487