1132718Skan/* Print RTL for GCC. 2169689Skan Copyright (C) 1987, 1988, 1992, 1997, 1998, 1999, 2000, 2002, 2003, 3169689Skan 2004, 2005 490075Sobrien Free Software Foundation, Inc. 518334Speter 690075SobrienThis file is part of GCC. 718334Speter 890075SobrienGCC is free software; you can redistribute it and/or modify it under 990075Sobrienthe terms of the GNU General Public License as published by the Free 1090075SobrienSoftware Foundation; either version 2, or (at your option) any later 1190075Sobrienversion. 1218334Speter 1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1590075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1690075Sobrienfor more details. 1718334Speter 1818334SpeterYou should have received a copy of the GNU General Public License 1990075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169689Skan02110-1301, USA. */ 2218334Speter 23169689Skan/* This file is compiled twice: once for the generator programs, 24169689Skan once for the compiler. */ 25169689Skan#ifdef GENERATOR_FILE 26169689Skan#include "bconfig.h" 27169689Skan#else 28169689Skan#include "config.h" 29169689Skan#endif 3018334Speter 3150397Sobrien#include "system.h" 32132718Skan#include "coretypes.h" 33132718Skan#include "tm.h" 3418334Speter#include "rtl.h" 3590075Sobrien 36169689Skan/* These headers all define things which are not available in 37169689Skan generator programs. */ 38169689Skan#ifndef GENERATOR_FILE 3990075Sobrien#include "tree.h" 4050397Sobrien#include "real.h" 4152284Sobrien#include "flags.h" 4290075Sobrien#include "hard-reg-set.h" 4352284Sobrien#include "basic-block.h" 44169689Skan#endif 4518334Speter 4618334Speterstatic FILE *outfile; 4718334Speter 4818334Speterstatic int sawclose = 0; 4918334Speter 5050397Sobrienstatic int indent; 5150397Sobrien 52132718Skanstatic void print_rtx (rtx); 5318334Speter 5490075Sobrien/* String printed at beginning of each RTL when it is dumped. 5590075Sobrien This string is set to ASM_COMMENT_START when the RTL is dumped in 5690075Sobrien the assembly output file. */ 5790075Sobrienconst char *print_rtx_head = ""; 5818334Speter 5952284Sobrien/* Nonzero means suppress output of instruction numbers and line number 6052284Sobrien notes in debugging dumps. 6152284Sobrien This must be defined here so that programs like gencodes can be linked. */ 6250397Sobrienint flag_dump_unnumbered = 0; 6352284Sobrien 6490075Sobrien/* Nonzero means use simplified format without flags, modes, etc. */ 6590075Sobrienint flag_simple = 0; 6690075Sobrien 6752284Sobrien/* Nonzero if we are dumping graphical description. */ 6852284Sobrienint dump_for_graph; 6952284Sobrien 70169689Skan#ifndef GENERATOR_FILE 71169689Skanstatic void 72169689Skanprint_decl_name (FILE *outfile, tree node) 73169689Skan{ 74169689Skan if (DECL_NAME (node)) 75169689Skan fputs (IDENTIFIER_POINTER (DECL_NAME (node)), outfile); 76169689Skan else 77169689Skan { 78169689Skan if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1) 79169689Skan fprintf (outfile, "L." HOST_WIDE_INT_PRINT_DEC, LABEL_DECL_UID (node)); 80169689Skan else 81169689Skan { 82169689Skan char c = TREE_CODE (node) == CONST_DECL ? 'C' : 'D'; 83169689Skan fprintf (outfile, "%c.%u", c, DECL_UID (node)); 84169689Skan } 85169689Skan } 86169689Skan} 8790075Sobrien 8890075Sobrienvoid 89132718Skanprint_mem_expr (FILE *outfile, tree expr) 9090075Sobrien{ 9190075Sobrien if (TREE_CODE (expr) == COMPONENT_REF) 9290075Sobrien { 9390075Sobrien if (TREE_OPERAND (expr, 0)) 94117395Skan print_mem_expr (outfile, TREE_OPERAND (expr, 0)); 9590075Sobrien else 9690075Sobrien fputs (" <variable>", outfile); 97169689Skan fputc ('.', outfile); 98169689Skan print_decl_name (outfile, TREE_OPERAND (expr, 1)); 9990075Sobrien } 100110611Skan else if (TREE_CODE (expr) == INDIRECT_REF) 101110611Skan { 102110611Skan fputs (" (*", outfile); 103110611Skan print_mem_expr (outfile, TREE_OPERAND (expr, 0)); 104110611Skan fputs (")", outfile); 105110611Skan } 106169689Skan else if (TREE_CODE (expr) == ALIGN_INDIRECT_REF) 107169689Skan { 108169689Skan fputs (" (A*", outfile); 109169689Skan print_mem_expr (outfile, TREE_OPERAND (expr, 0)); 110169689Skan fputs (")", outfile); 111169689Skan } 112169689Skan else if (TREE_CODE (expr) == MISALIGNED_INDIRECT_REF) 113169689Skan { 114169689Skan fputs (" (M*", outfile); 115169689Skan print_mem_expr (outfile, TREE_OPERAND (expr, 0)); 116169689Skan fputs (")", outfile); 117169689Skan } 11890075Sobrien else if (TREE_CODE (expr) == RESULT_DECL) 11990075Sobrien fputs (" <result>", outfile); 12090075Sobrien else 121169689Skan { 122169689Skan fputc (' ', outfile); 123169689Skan print_decl_name (outfile, expr); 124169689Skan } 12590075Sobrien} 126169689Skan#endif 12790075Sobrien 12818334Speter/* Print IN_RTX onto OUTFILE. This is the recursive part of printing. */ 12918334Speter 13018334Speterstatic void 131132718Skanprint_rtx (rtx in_rtx) 13218334Speter{ 13390075Sobrien int i = 0; 13490075Sobrien int j; 13590075Sobrien const char *format_ptr; 13690075Sobrien int is_insn; 13718334Speter 13818334Speter if (sawclose) 13918334Speter { 14090075Sobrien if (flag_simple) 14190075Sobrien fputc (' ', outfile); 14290075Sobrien else 14390075Sobrien fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, ""); 14418334Speter sawclose = 0; 14518334Speter } 14618334Speter 14718334Speter if (in_rtx == 0) 14818334Speter { 14952284Sobrien fputs ("(nil)", outfile); 15018334Speter sawclose = 1; 15118334Speter return; 15218334Speter } 15390075Sobrien else if (GET_CODE (in_rtx) > NUM_RTX_CODE) 15490075Sobrien { 15590075Sobrien fprintf (outfile, "(??? bad code %d\n)", GET_CODE (in_rtx)); 15690075Sobrien sawclose = 1; 15790075Sobrien return; 15890075Sobrien } 15918334Speter 16090075Sobrien is_insn = INSN_P (in_rtx); 16118334Speter 16252284Sobrien /* When printing in VCG format we write INSNs, NOTE, LABEL, and BARRIER 16352284Sobrien in separate nodes and therefore have to handle them special here. */ 16490075Sobrien if (dump_for_graph 165169689Skan && (is_insn || NOTE_P (in_rtx) 166169689Skan || LABEL_P (in_rtx) || BARRIER_P (in_rtx))) 16752284Sobrien { 16852284Sobrien i = 3; 16952284Sobrien indent = 0; 17052284Sobrien } 17152284Sobrien else 17252284Sobrien { 17390075Sobrien /* Print name of expression code. */ 17490075Sobrien if (flag_simple && GET_CODE (in_rtx) == CONST_INT) 17590075Sobrien fputc ('(', outfile); 17690075Sobrien else 17790075Sobrien fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx))); 178117395Skan 17990075Sobrien if (! flag_simple) 18090075Sobrien { 181117395Skan if (RTX_FLAG (in_rtx, in_struct)) 18290075Sobrien fputs ("/s", outfile); 18318334Speter 184117395Skan if (RTX_FLAG (in_rtx, volatil)) 18590075Sobrien fputs ("/v", outfile); 186117395Skan 187117395Skan if (RTX_FLAG (in_rtx, unchanging)) 18890075Sobrien fputs ("/u", outfile); 189117395Skan 190117395Skan if (RTX_FLAG (in_rtx, frame_related)) 19190075Sobrien fputs ("/f", outfile); 192117395Skan 193117395Skan if (RTX_FLAG (in_rtx, jump)) 19490075Sobrien fputs ("/j", outfile); 195117395Skan 196117395Skan if (RTX_FLAG (in_rtx, call)) 19790075Sobrien fputs ("/c", outfile); 19818334Speter 199169689Skan if (RTX_FLAG (in_rtx, return_val)) 200169689Skan fputs ("/i", outfile); 201169689Skan 202169689Skan /* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */ 203169689Skan if (GET_CODE (in_rtx) == EXPR_LIST 204169689Skan || GET_CODE (in_rtx) == INSN_LIST) 205169689Skan fprintf (outfile, ":%s", 206169689Skan GET_REG_NOTE_NAME (GET_MODE (in_rtx))); 207169689Skan 208169689Skan /* For other rtl, print the mode if it's not VOID. */ 209169689Skan else if (GET_MODE (in_rtx) != VOIDmode) 210169689Skan fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx))); 21152284Sobrien } 21218334Speter } 21318334Speter 214117395Skan#ifndef GENERATOR_FILE 215117395Skan if (GET_CODE (in_rtx) == CONST_DOUBLE && FLOAT_MODE_P (GET_MODE (in_rtx))) 216117395Skan i = 5; 217117395Skan#endif 218117395Skan 21952284Sobrien /* Get the format string and skip the first elements if we have handled 22052284Sobrien them already. */ 22152284Sobrien format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i; 22252284Sobrien for (; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++) 22318334Speter switch (*format_ptr++) 22418334Speter { 22590075Sobrien const char *str; 22690075Sobrien 22790075Sobrien case 'T': 22890075Sobrien str = XTMPL (in_rtx, i); 22990075Sobrien goto string; 23090075Sobrien 23118334Speter case 'S': 23218334Speter case 's': 23390075Sobrien str = XSTR (in_rtx, i); 23490075Sobrien string: 23590075Sobrien 23690075Sobrien if (str == 0) 23790075Sobrien fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile); 23890075Sobrien else 23950397Sobrien { 24090075Sobrien if (dump_for_graph) 24190075Sobrien fprintf (outfile, " (\\\"%s\\\")", str); 24290075Sobrien else 24390075Sobrien fprintf (outfile, " (\"%s\")", str); 24450397Sobrien } 24590075Sobrien sawclose = 1; 24690075Sobrien break; 24750397Sobrien 24890075Sobrien /* 0 indicates a field for internal use that should not be printed. 24990075Sobrien An exception is the third field of a NOTE, where it indicates 25090075Sobrien that the field has several different valid contents. */ 25190075Sobrien case '0': 252169689Skan if (i == 1 && REG_P (in_rtx)) 25350397Sobrien { 25490075Sobrien if (REGNO (in_rtx) != ORIGINAL_REGNO (in_rtx)) 25590075Sobrien fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx)); 25650397Sobrien } 257132718Skan#ifndef GENERATOR_FILE 258132718Skan else if (i == 1 && GET_CODE (in_rtx) == SYMBOL_REF) 25950397Sobrien { 260132718Skan int flags = SYMBOL_REF_FLAGS (in_rtx); 261132718Skan if (flags) 262132718Skan fprintf (outfile, " [flags 0x%x]", flags); 263132718Skan } 264132718Skan else if (i == 2 && GET_CODE (in_rtx) == SYMBOL_REF) 265132718Skan { 266132718Skan tree decl = SYMBOL_REF_DECL (in_rtx); 267132718Skan if (decl) 268132718Skan print_node_brief (outfile, "", decl, 0); 269132718Skan } 270132718Skan#endif 271169689Skan else if (i == 4 && NOTE_P (in_rtx)) 272132718Skan { 27390075Sobrien switch (NOTE_LINE_NUMBER (in_rtx)) 27490075Sobrien { 27590075Sobrien case NOTE_INSN_EH_REGION_BEG: 27690075Sobrien case NOTE_INSN_EH_REGION_END: 27790075Sobrien if (flag_dump_unnumbered) 27890075Sobrien fprintf (outfile, " #"); 27990075Sobrien else 28090075Sobrien fprintf (outfile, " %d", NOTE_EH_HANDLER (in_rtx)); 28190075Sobrien sawclose = 1; 28290075Sobrien break; 28350397Sobrien 28490075Sobrien case NOTE_INSN_BLOCK_BEG: 28590075Sobrien case NOTE_INSN_BLOCK_END: 286169689Skan#ifndef GENERATOR_FILE 287169689Skan dump_addr (outfile, " ", NOTE_BLOCK (in_rtx)); 288169689Skan#endif 28990075Sobrien sawclose = 1; 29090075Sobrien break; 29118334Speter 29290075Sobrien case NOTE_INSN_BASIC_BLOCK: 29390075Sobrien { 294169689Skan#ifndef GENERATOR_FILE 29590075Sobrien basic_block bb = NOTE_BASIC_BLOCK (in_rtx); 29690075Sobrien if (bb != 0) 29790075Sobrien fprintf (outfile, " [bb %d]", bb->index); 298169689Skan#endif 29990075Sobrien break; 30090075Sobrien } 30190075Sobrien 30290075Sobrien case NOTE_INSN_EXPECTED_VALUE: 30390075Sobrien indent += 2; 30490075Sobrien if (!sawclose) 30590075Sobrien fprintf (outfile, " "); 30690075Sobrien print_rtx (NOTE_EXPECTED_VALUE (in_rtx)); 30790075Sobrien indent -= 2; 30890075Sobrien break; 30990075Sobrien 31090075Sobrien case NOTE_INSN_DELETED_LABEL: 311169689Skan { 312169689Skan const char *label = NOTE_DELETED_LABEL_NAME (in_rtx); 313169689Skan if (label) 314169689Skan fprintf (outfile, " (\"%s\")", label); 315169689Skan else 316169689Skan fprintf (outfile, " \"\""); 317169689Skan } 31890075Sobrien break; 31990075Sobrien 320169689Skan case NOTE_INSN_SWITCH_TEXT_SECTIONS: 321169689Skan { 322169689Skan#ifndef GENERATOR_FILE 323169689Skan basic_block bb = NOTE_BASIC_BLOCK (in_rtx); 324169689Skan if (bb != 0) 325169689Skan fprintf (outfile, " [bb %d]", bb->index); 326169689Skan#endif 327169689Skan break; 328169689Skan } 329169689Skan 330169689Skan case NOTE_INSN_VAR_LOCATION: 331169689Skan#ifndef GENERATOR_FILE 332169689Skan fprintf (outfile, " ("); 333169689Skan print_mem_expr (outfile, NOTE_VAR_LOCATION_DECL (in_rtx)); 334169689Skan fprintf (outfile, " "); 335169689Skan print_rtx (NOTE_VAR_LOCATION_LOC (in_rtx)); 336169689Skan fprintf (outfile, ")"); 337169689Skan#endif 338117395Skan break; 339117395Skan 34090075Sobrien default: 34190075Sobrien { 34290075Sobrien const char * const str = X0STR (in_rtx, i); 34390075Sobrien 34490075Sobrien if (NOTE_LINE_NUMBER (in_rtx) < 0) 34590075Sobrien ; 34690075Sobrien else if (str == 0) 34790075Sobrien fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile); 34890075Sobrien else 34990075Sobrien { 35090075Sobrien if (dump_for_graph) 35190075Sobrien fprintf (outfile, " (\\\"%s\\\")", str); 35290075Sobrien else 35390075Sobrien fprintf (outfile, " (\"%s\")", str); 35490075Sobrien } 35590075Sobrien break; 35690075Sobrien } 35790075Sobrien } 35890075Sobrien } 35918334Speter break; 36018334Speter 36118334Speter case 'e': 36290075Sobrien do_e: 36318334Speter indent += 2; 36418334Speter if (!sawclose) 36518334Speter fprintf (outfile, " "); 36618334Speter print_rtx (XEXP (in_rtx, i)); 36718334Speter indent -= 2; 36818334Speter break; 36918334Speter 37018334Speter case 'E': 37118334Speter case 'V': 37218334Speter indent += 2; 37318334Speter if (sawclose) 37418334Speter { 37590075Sobrien fprintf (outfile, "\n%s%*s", 376117395Skan print_rtx_head, indent * 2, ""); 37718334Speter sawclose = 0; 37818334Speter } 379117395Skan fputs (" [", outfile); 38018334Speter if (NULL != XVEC (in_rtx, i)) 38118334Speter { 38218334Speter indent += 2; 38318334Speter if (XVECLEN (in_rtx, i)) 38418334Speter sawclose = 1; 38518334Speter 38618334Speter for (j = 0; j < XVECLEN (in_rtx, i); j++) 38718334Speter print_rtx (XVECEXP (in_rtx, i, j)); 38818334Speter 38918334Speter indent -= 2; 39018334Speter } 39118334Speter if (sawclose) 39290075Sobrien fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, ""); 39318334Speter 394117395Skan fputs ("]", outfile); 39518334Speter sawclose = 1; 39618334Speter indent -= 2; 39718334Speter break; 39818334Speter 39918334Speter case 'w': 40090075Sobrien if (! flag_simple) 40190075Sobrien fprintf (outfile, " "); 40250397Sobrien fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, i)); 40390075Sobrien if (! flag_simple) 404132718Skan fprintf (outfile, " [" HOST_WIDE_INT_PRINT_HEX "]", 405132718Skan XWINT (in_rtx, i)); 40618334Speter break; 40718334Speter 40818334Speter case 'i': 409132718Skan if (i == 4 && INSN_P (in_rtx)) 41090075Sobrien { 411132718Skan#ifndef GENERATOR_FILE 412132718Skan /* Pretty-print insn locators. Ignore scoping as it is mostly 413132718Skan redundant with line number information and do not print anything 414132718Skan when there is no location information available. */ 415132718Skan if (INSN_LOCATOR (in_rtx) && insn_file (in_rtx)) 416132718Skan fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx)); 417132718Skan#endif 418132718Skan } 419169689Skan else if (i == 6 && NOTE_P (in_rtx)) 420132718Skan { 42190075Sobrien /* This field is only used for NOTE_INSN_DELETED_LABEL, and 42290075Sobrien other times often contains garbage from INSN->NOTE death. */ 42390075Sobrien if (NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_DELETED_LABEL) 42490075Sobrien fprintf (outfile, " %d", XINT (in_rtx, i)); 42590075Sobrien } 42690075Sobrien else 42790075Sobrien { 42890075Sobrien int value = XINT (in_rtx, i); 42990075Sobrien const char *name; 43018334Speter 431132718Skan#ifndef GENERATOR_FILE 432169689Skan if (REG_P (in_rtx) && value < FIRST_PSEUDO_REGISTER) 433132718Skan fprintf (outfile, " %d %s", REGNO (in_rtx), 434132718Skan reg_names[REGNO (in_rtx)]); 435169689Skan else if (REG_P (in_rtx) 43690075Sobrien && value <= LAST_VIRTUAL_REGISTER) 43790075Sobrien { 43890075Sobrien if (value == VIRTUAL_INCOMING_ARGS_REGNUM) 43990075Sobrien fprintf (outfile, " %d virtual-incoming-args", value); 44090075Sobrien else if (value == VIRTUAL_STACK_VARS_REGNUM) 44190075Sobrien fprintf (outfile, " %d virtual-stack-vars", value); 44290075Sobrien else if (value == VIRTUAL_STACK_DYNAMIC_REGNUM) 44390075Sobrien fprintf (outfile, " %d virtual-stack-dynamic", value); 44490075Sobrien else if (value == VIRTUAL_OUTGOING_ARGS_REGNUM) 44590075Sobrien fprintf (outfile, " %d virtual-outgoing-args", value); 44690075Sobrien else if (value == VIRTUAL_CFA_REGNUM) 44790075Sobrien fprintf (outfile, " %d virtual-cfa", value); 44890075Sobrien else 44990075Sobrien fprintf (outfile, " %d virtual-reg-%d", value, 45090075Sobrien value-FIRST_VIRTUAL_REGISTER); 45190075Sobrien } 452132718Skan else 453132718Skan#endif 454132718Skan if (flag_dump_unnumbered 455169689Skan && (is_insn || NOTE_P (in_rtx))) 45690075Sobrien fputc ('#', outfile); 45790075Sobrien else 45890075Sobrien fprintf (outfile, " %d", value); 45990075Sobrien 460169689Skan#ifndef GENERATOR_FILE 461169689Skan if (REG_P (in_rtx) && REG_ATTRS (in_rtx)) 462132718Skan { 463132718Skan fputs (" [", outfile); 464132718Skan if (ORIGINAL_REGNO (in_rtx) != REGNO (in_rtx)) 465132718Skan fprintf (outfile, "orig:%i", ORIGINAL_REGNO (in_rtx)); 466132718Skan if (REG_EXPR (in_rtx)) 467132718Skan print_mem_expr (outfile, REG_EXPR (in_rtx)); 468132718Skan 469132718Skan if (REG_OFFSET (in_rtx)) 470132718Skan fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, 471132718Skan REG_OFFSET (in_rtx)); 472132718Skan fputs (" ]", outfile); 473132718Skan } 474169689Skan#endif 475132718Skan 47690075Sobrien if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i) 47790075Sobrien && XINT (in_rtx, i) >= 0 47890075Sobrien && (name = get_insn_name (XINT (in_rtx, i))) != NULL) 47990075Sobrien fprintf (outfile, " {%s}", name); 48090075Sobrien sawclose = 0; 48190075Sobrien } 48218334Speter break; 48318334Speter 48418334Speter /* Print NOTE_INSN names rather than integer codes. */ 48518334Speter 48618334Speter case 'n': 48790075Sobrien if (XINT (in_rtx, i) >= (int) NOTE_INSN_BIAS 48890075Sobrien && XINT (in_rtx, i) < (int) NOTE_INSN_MAX) 48918334Speter fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i))); 49018334Speter else 49118334Speter fprintf (outfile, " %d", XINT (in_rtx, i)); 49218334Speter sawclose = 0; 49318334Speter break; 49418334Speter 49518334Speter case 'u': 49618334Speter if (XEXP (in_rtx, i) != NULL) 49750397Sobrien { 49890075Sobrien rtx sub = XEXP (in_rtx, i); 49990075Sobrien enum rtx_code subc = GET_CODE (sub); 50090075Sobrien 50190075Sobrien if (GET_CODE (in_rtx) == LABEL_REF) 50290075Sobrien { 50390075Sobrien if (subc == NOTE 50490075Sobrien && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL) 50590075Sobrien { 50690075Sobrien if (flag_dump_unnumbered) 50790075Sobrien fprintf (outfile, " [# deleted]"); 50890075Sobrien else 50990075Sobrien fprintf (outfile, " [%d deleted]", INSN_UID (sub)); 51090075Sobrien sawclose = 0; 51190075Sobrien break; 51290075Sobrien } 51390075Sobrien 51490075Sobrien if (subc != CODE_LABEL) 51590075Sobrien goto do_e; 51690075Sobrien } 51790075Sobrien 51850397Sobrien if (flag_dump_unnumbered) 51990075Sobrien fputs (" #", outfile); 52050397Sobrien else 52190075Sobrien fprintf (outfile, " %d", INSN_UID (sub)); 52250397Sobrien } 52318334Speter else 52452284Sobrien fputs (" 0", outfile); 52518334Speter sawclose = 0; 52618334Speter break; 52718334Speter 52850397Sobrien case 'b': 529169689Skan#ifndef GENERATOR_FILE 53050397Sobrien if (XBITMAP (in_rtx, i) == NULL) 53152284Sobrien fputs (" {null}", outfile); 53250397Sobrien else 53350397Sobrien bitmap_print (outfile, XBITMAP (in_rtx, i), " {", "}"); 534169689Skan#endif 53550397Sobrien sawclose = 0; 53650397Sobrien break; 53750397Sobrien 53850397Sobrien case 't': 539169689Skan#ifndef GENERATOR_FILE 540169689Skan dump_addr (outfile, " ", XTREE (in_rtx, i)); 541169689Skan#endif 54250397Sobrien break; 54350397Sobrien 54418334Speter case '*': 54552284Sobrien fputs (" Unknown", outfile); 54618334Speter sawclose = 0; 54718334Speter break; 54818334Speter 549117395Skan case 'B': 550169689Skan#ifndef GENERATOR_FILE 551117395Skan if (XBBDEF (in_rtx, i)) 552117395Skan fprintf (outfile, " %i", XBBDEF (in_rtx, i)->index); 553169689Skan#endif 554117395Skan break; 555117395Skan 55618334Speter default: 557169689Skan gcc_unreachable (); 55818334Speter } 55918334Speter 56090075Sobrien switch (GET_CODE (in_rtx)) 56190075Sobrien { 562117395Skan#ifndef GENERATOR_FILE 56390075Sobrien case MEM: 564132718Skan fprintf (outfile, " [" HOST_WIDE_INT_PRINT_DEC, MEM_ALIAS_SET (in_rtx)); 56552284Sobrien 56690075Sobrien if (MEM_EXPR (in_rtx)) 56790075Sobrien print_mem_expr (outfile, MEM_EXPR (in_rtx)); 56890075Sobrien 56990075Sobrien if (MEM_OFFSET (in_rtx)) 570132718Skan fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, 571132718Skan INTVAL (MEM_OFFSET (in_rtx))); 57290075Sobrien 57390075Sobrien if (MEM_SIZE (in_rtx)) 574132718Skan fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC, 575132718Skan INTVAL (MEM_SIZE (in_rtx))); 57690075Sobrien 57790075Sobrien if (MEM_ALIGN (in_rtx) != 1) 57890075Sobrien fprintf (outfile, " A%u", MEM_ALIGN (in_rtx)); 57990075Sobrien 58090075Sobrien fputc (']', outfile); 58190075Sobrien break; 58290075Sobrien 58390075Sobrien case CONST_DOUBLE: 58490075Sobrien if (FLOAT_MODE_P (GET_MODE (in_rtx))) 58590075Sobrien { 586117395Skan char s[60]; 587117395Skan 588117395Skan real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx), 589117395Skan sizeof (s), 0, 1); 590117395Skan fprintf (outfile, " %s", s); 591117395Skan 592117395Skan real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx), 593117395Skan sizeof (s), 0, 1); 594117395Skan fprintf (outfile, " [%s]", s); 59590075Sobrien } 59690075Sobrien break; 59750397Sobrien#endif 59850397Sobrien 59990075Sobrien case CODE_LABEL: 60090075Sobrien fprintf (outfile, " [%d uses]", LABEL_NUSES (in_rtx)); 601117395Skan switch (LABEL_KIND (in_rtx)) 602117395Skan { 603117395Skan case LABEL_NORMAL: break; 604117395Skan case LABEL_STATIC_ENTRY: fputs (" [entry]", outfile); break; 605117395Skan case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", outfile); break; 606117395Skan case LABEL_WEAK_ENTRY: fputs (" [weak entry]", outfile); break; 607169689Skan default: gcc_unreachable (); 608117395Skan } 609260918Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 610260918Spfg if (LABEL_ALIGN_LOG (in_rtx) > 0) 611260918Spfg fprintf (outfile, " [log_align %u skip %u]", LABEL_ALIGN_LOG (in_rtx), 612260918Spfg LABEL_MAX_SKIP (in_rtx)); 613260918Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 61490075Sobrien break; 61590075Sobrien 61690075Sobrien default: 61790075Sobrien break; 61890075Sobrien } 61990075Sobrien 62052284Sobrien if (dump_for_graph 621169689Skan && (is_insn || NOTE_P (in_rtx) 622169689Skan || LABEL_P (in_rtx) || BARRIER_P (in_rtx))) 62352284Sobrien sawclose = 0; 62452284Sobrien else 62552284Sobrien { 62652284Sobrien fputc (')', outfile); 62752284Sobrien sawclose = 1; 62852284Sobrien } 62918334Speter} 63018334Speter 63150397Sobrien/* Print an rtx on the current line of FILE. Initially indent IND 63250397Sobrien characters. */ 63350397Sobrien 63450397Sobrienvoid 635132718Skanprint_inline_rtx (FILE *outf, rtx x, int ind) 63650397Sobrien{ 63750397Sobrien int oldsaw = sawclose; 63850397Sobrien int oldindent = indent; 63950397Sobrien 64050397Sobrien sawclose = 0; 64150397Sobrien indent = ind; 64250397Sobrien outfile = outf; 64350397Sobrien print_rtx (x); 64450397Sobrien sawclose = oldsaw; 64550397Sobrien indent = oldindent; 64650397Sobrien} 64750397Sobrien 64818334Speter/* Call this function from the debugger to see what X looks like. */ 64918334Speter 65018334Spetervoid 651132718Skandebug_rtx (rtx x) 65218334Speter{ 65318334Speter outfile = stderr; 654117395Skan sawclose = 0; 65518334Speter print_rtx (x); 65618334Speter fprintf (stderr, "\n"); 65718334Speter} 65818334Speter 65918334Speter/* Count of rtx's to print with debug_rtx_list. 66018334Speter This global exists because gdb user defined commands have no arguments. */ 66118334Speter 66218334Speterint debug_rtx_count = 0; /* 0 is treated as equivalent to 1 */ 66318334Speter 66418334Speter/* Call this function to print list from X on. 66518334Speter 66618334Speter N is a count of the rtx's to print. Positive values print from the specified 66718334Speter rtx on. Negative values print a window around the rtx. 66818334Speter EG: -5 prints 2 rtx's on either side (in addition to the specified rtx). */ 66918334Speter 67018334Spetervoid 671132718Skandebug_rtx_list (rtx x, int n) 67218334Speter{ 67318334Speter int i,count; 67418334Speter rtx insn; 67518334Speter 67618334Speter count = n == 0 ? 1 : n < 0 ? -n : n; 67718334Speter 67818334Speter /* If we are printing a window, back up to the start. */ 67918334Speter 68018334Speter if (n < 0) 68118334Speter for (i = count / 2; i > 0; i--) 68218334Speter { 68318334Speter if (PREV_INSN (x) == 0) 68418334Speter break; 68518334Speter x = PREV_INSN (x); 68618334Speter } 68718334Speter 68818334Speter for (i = count, insn = x; i > 0 && insn != 0; i--, insn = NEXT_INSN (insn)) 689117395Skan { 690117395Skan debug_rtx (insn); 691117395Skan fprintf (stderr, "\n"); 692117395Skan } 69318334Speter} 69418334Speter 69590075Sobrien/* Call this function to print an rtx list from START to END inclusive. */ 69690075Sobrien 69790075Sobrienvoid 698132718Skandebug_rtx_range (rtx start, rtx end) 69990075Sobrien{ 70090075Sobrien while (1) 70190075Sobrien { 70290075Sobrien debug_rtx (start); 703117395Skan fprintf (stderr, "\n"); 70490075Sobrien if (!start || start == end) 70590075Sobrien break; 70690075Sobrien start = NEXT_INSN (start); 70790075Sobrien } 70890075Sobrien} 70990075Sobrien 71018334Speter/* Call this function to search an rtx list to find one with insn uid UID, 71118334Speter and then call debug_rtx_list to print it, using DEBUG_RTX_COUNT. 71218334Speter The found insn is returned to enable further debugging analysis. */ 71318334Speter 71418334Speterrtx 715132718Skandebug_rtx_find (rtx x, int uid) 71618334Speter{ 71718334Speter while (x != 0 && INSN_UID (x) != uid) 71818334Speter x = NEXT_INSN (x); 71918334Speter if (x != 0) 72018334Speter { 72118334Speter debug_rtx_list (x, debug_rtx_count); 72218334Speter return x; 72318334Speter } 72418334Speter else 72518334Speter { 72618334Speter fprintf (stderr, "insn uid %d not found\n", uid); 72718334Speter return 0; 72818334Speter } 72918334Speter} 73018334Speter 73118334Speter/* External entry point for printing a chain of insns 73218334Speter starting with RTX_FIRST onto file OUTF. 73318334Speter A blank line separates insns. 73418334Speter 73518334Speter If RTX_FIRST is not an insn, then it alone is printed, with no newline. */ 73618334Speter 73718334Spetervoid 738132718Skanprint_rtl (FILE *outf, rtx rtx_first) 73918334Speter{ 74090075Sobrien rtx tmp_rtx; 74118334Speter 74218334Speter outfile = outf; 74318334Speter sawclose = 0; 74418334Speter 74518334Speter if (rtx_first == 0) 74690075Sobrien { 74790075Sobrien fputs (print_rtx_head, outf); 74890075Sobrien fputs ("(nil)\n", outf); 74990075Sobrien } 75018334Speter else 75118334Speter switch (GET_CODE (rtx_first)) 75218334Speter { 75318334Speter case INSN: 75418334Speter case JUMP_INSN: 75518334Speter case CALL_INSN: 75618334Speter case NOTE: 75718334Speter case CODE_LABEL: 75818334Speter case BARRIER: 75990075Sobrien for (tmp_rtx = rtx_first; tmp_rtx != 0; tmp_rtx = NEXT_INSN (tmp_rtx)) 76090075Sobrien if (! flag_dump_unnumbered 761169689Skan || !NOTE_P (tmp_rtx) || NOTE_LINE_NUMBER (tmp_rtx) < 0) 76290075Sobrien { 763117395Skan fputs (print_rtx_head, outfile); 76490075Sobrien print_rtx (tmp_rtx); 76590075Sobrien fprintf (outfile, "\n"); 76690075Sobrien } 76718334Speter break; 76818334Speter 76918334Speter default: 770117395Skan fputs (print_rtx_head, outfile); 77118334Speter print_rtx (rtx_first); 77218334Speter } 77318334Speter} 77450397Sobrien 77550397Sobrien/* Like print_rtx, except specify a file. */ 77652284Sobrien/* Return nonzero if we actually printed anything. */ 77750397Sobrien 77852284Sobrienint 779132718Skanprint_rtl_single (FILE *outf, rtx x) 78050397Sobrien{ 78150397Sobrien outfile = outf; 78250397Sobrien sawclose = 0; 78350397Sobrien if (! flag_dump_unnumbered 784169689Skan || !NOTE_P (x) || NOTE_LINE_NUMBER (x) < 0) 78550397Sobrien { 78690075Sobrien fputs (print_rtx_head, outfile); 78750397Sobrien print_rtx (x); 78850397Sobrien putc ('\n', outf); 78952284Sobrien return 1; 79050397Sobrien } 79152284Sobrien return 0; 79250397Sobrien} 79390075Sobrien 79490075Sobrien 79590075Sobrien/* Like print_rtl except without all the detail; for example, 79690075Sobrien if RTX is a CONST_INT then print in decimal format. */ 79790075Sobrien 79890075Sobrienvoid 799132718Skanprint_simple_rtl (FILE *outf, rtx x) 80090075Sobrien{ 80190075Sobrien flag_simple = 1; 80290075Sobrien print_rtl (outf, x); 80390075Sobrien flag_simple = 0; 80490075Sobrien} 805