1 /* Print RTL functions for GCC. 2 Copyright (C) 2016-2018 Free Software Foundation, Inc. 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 #include "config.h" 21 #include "system.h" 22 #include "coretypes.h" 23 #include "tm.h" 24 #include "rtl.h" 25 #include "alias.h" 26 #include "tree.h" 27 #include "flags.h" 28 #include "predict.h" 29 #include "function.h" 30 #include "basic-block.h" 31 #include "print-rtl.h" 32 #include "langhooks.h" 33 #include "memmodel.h" 34 #include "emit-rtl.h" 35 #include "varasm.h" 36 37 /* Print an "(edge-from)" or "(edge-to)" directive describing E 38 to OUTFILE. */ 39 40 static void 41 print_edge (FILE *outfile, edge e, bool from) 42 { 43 fprintf (outfile, " (%s ", from ? "edge-from" : "edge-to"); 44 basic_block bb = from ? e->src : e->dest; 45 gcc_assert (bb); 46 switch (bb->index) 47 { 48 case ENTRY_BLOCK: 49 fprintf (outfile, "entry"); 50 break; 51 case EXIT_BLOCK: 52 fprintf (outfile, "exit"); 53 break; 54 default: 55 fprintf (outfile, "%i", bb->index); 56 break; 57 } 58 59 /* Express edge flags as a string with " | " separator. 60 e.g. (flags "FALLTHRU | DFS_BACK"). */ 61 if (e->flags) 62 { 63 fprintf (outfile, " (flags \""); 64 bool seen_flag = false; 65 #define DEF_EDGE_FLAG(NAME,IDX) \ 66 do { \ 67 if (e->flags & EDGE_##NAME) \ 68 { \ 69 if (seen_flag) \ 70 fprintf (outfile, " | "); \ 71 fprintf (outfile, "%s", (#NAME)); \ 72 seen_flag = true; \ 73 } \ 74 } while (0); 75 #include "cfg-flags.def" 76 #undef DEF_EDGE_FLAG 77 78 fprintf (outfile, "\")"); 79 } 80 81 fprintf (outfile, ")\n"); 82 } 83 84 /* If BB is non-NULL, print the start of a "(block)" directive for it 85 to OUTFILE, otherwise do nothing. */ 86 87 static void 88 begin_any_block (FILE *outfile, basic_block bb) 89 { 90 if (!bb) 91 return; 92 93 edge e; 94 edge_iterator ei; 95 96 fprintf (outfile, " (block %i\n", bb->index); 97 FOR_EACH_EDGE (e, ei, bb->preds) 98 print_edge (outfile, e, true); 99 } 100 101 /* If BB is non-NULL, print the end of a "(block)" directive for it 102 to OUTFILE, otherwise do nothing. */ 103 104 static void 105 end_any_block (FILE *outfile, basic_block bb) 106 { 107 if (!bb) 108 return; 109 110 edge e; 111 edge_iterator ei; 112 113 FOR_EACH_EDGE (e, ei, bb->succs) 114 print_edge (outfile, e, false); 115 fprintf (outfile, " ) ;; block %i\n", bb->index); 116 } 117 118 /* Determine if INSN is of a kind that can have a basic block. */ 119 120 static bool 121 can_have_basic_block_p (const rtx_insn *insn) 122 { 123 rtx_code code = GET_CODE (insn); 124 if (code == BARRIER) 125 return false; 126 gcc_assert (GET_RTX_FORMAT (code)[2] == 'B'); 127 return true; 128 } 129 130 /* Subroutine of print_param. Write the name of ARG, if any, to OUTFILE. */ 131 132 static void 133 print_any_param_name (FILE *outfile, tree arg) 134 { 135 if (DECL_NAME (arg)) 136 fprintf (outfile, " \"%s\"", IDENTIFIER_POINTER (DECL_NAME (arg))); 137 } 138 139 /* Print a "(param)" directive for ARG to OUTFILE. */ 140 141 static void 142 print_param (FILE *outfile, rtx_writer &w, tree arg) 143 { 144 fprintf (outfile, " (param"); 145 print_any_param_name (outfile, arg); 146 fprintf (outfile, "\n"); 147 148 /* Print the value of DECL_RTL (without lazy-evaluation). */ 149 fprintf (outfile, " (DECL_RTL "); 150 w.print_rtx (DECL_RTL_IF_SET (arg)); 151 w.finish_directive (); 152 153 /* Print DECL_INCOMING_RTL. */ 154 fprintf (outfile, " (DECL_RTL_INCOMING "); 155 w.print_rtx (DECL_INCOMING_RTL (arg)); 156 fprintf (outfile, ")"); 157 158 w.finish_directive (); 159 } 160 161 /* Write FN to OUTFILE in a form suitable for parsing, with indentation 162 and comments to make the structure easy for a human to grok. Track 163 the basic blocks of insns in the chain, wrapping those that are within 164 blocks within "(block)" directives. 165 166 If COMPACT, then instructions are printed in a compact form: 167 - INSN_UIDs are omitted, except for jumps and CODE_LABELs, 168 - INSN_CODEs are omitted, 169 - register numbers are omitted for hard and virtual regs, and 170 non-virtual pseudos are offset relative to the first such reg, and 171 printed with a '%' sigil e.g. "%0" for (LAST_VIRTUAL_REGISTER + 1), 172 - insn names are prefixed with "c" (e.g. "cinsn", "cnote", etc) 173 174 Example output (with COMPACT==true): 175 176 (function "times_two" 177 (param "i" 178 (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) 179 (const_int -4)) [1 i+0 S4 A32])) 180 (DECL_RTL_INCOMING (reg:SI di [ i ]))) 181 (insn-chain 182 (cnote 1 NOTE_INSN_DELETED) 183 (block 2 184 (edge-from entry (flags "FALLTHRU")) 185 (cnote 4 [bb 2] NOTE_INSN_BASIC_BLOCK) 186 (cinsn 2 (set (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) 187 (const_int -4)) [1 i+0 S4 A32]) 188 (reg:SI di [ i ])) "t.c":2) 189 (cnote 3 NOTE_INSN_FUNCTION_BEG) 190 (cinsn 6 (set (reg:SI <2>) 191 (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) 192 (const_int -4)) [1 i+0 S4 A32])) "t.c":3) 193 (cinsn 7 (parallel [ 194 (set (reg:SI <0> [ _2 ]) 195 (ashift:SI (reg:SI <2>) 196 (const_int 1))) 197 (clobber (reg:CC flags)) 198 ]) "t.c":3 199 (expr_list:REG_EQUAL (ashift:SI (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) 200 (const_int -4)) [1 i+0 S4 A32]) 201 (const_int 1)))) 202 (cinsn 10 (set (reg:SI <1> [ <retval> ]) 203 (reg:SI <0> [ _2 ])) "t.c":3) 204 (cinsn 14 (set (reg/i:SI ax) 205 (reg:SI <1> [ <retval> ])) "t.c":4) 206 (cinsn 15 (use (reg/i:SI ax)) "t.c":4) 207 (edge-to exit (flags "FALLTHRU")) 208 ) ;; block 2 209 ) ;; insn-chain 210 (crtl 211 (return_rtx 212 (reg/i:SI ax) 213 ) ;; return_rtx 214 ) ;; crtl 215 ) ;; function "times_two" 216 */ 217 218 DEBUG_FUNCTION void 219 print_rtx_function (FILE *outfile, function *fn, bool compact) 220 { 221 rtx_reuse_manager r; 222 rtx_writer w (outfile, 0, false, compact, &r); 223 224 /* Support "reuse_rtx" in the dump. */ 225 for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn)) 226 r.preprocess (insn); 227 228 tree fdecl = fn->decl; 229 230 const char *dname = lang_hooks.decl_printable_name (fdecl, 1); 231 232 fprintf (outfile, "(function \"%s\"\n", dname); 233 234 /* Params. */ 235 for (tree arg = DECL_ARGUMENTS (fdecl); arg; arg = DECL_CHAIN (arg)) 236 print_param (outfile, w, arg); 237 238 /* The instruction chain. */ 239 fprintf (outfile, " (insn-chain\n"); 240 basic_block curr_bb = NULL; 241 for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn)) 242 { 243 basic_block insn_bb; 244 if (can_have_basic_block_p (insn)) 245 insn_bb = BLOCK_FOR_INSN (insn); 246 else 247 insn_bb = NULL; 248 if (curr_bb != insn_bb) 249 { 250 end_any_block (outfile, curr_bb); 251 curr_bb = insn_bb; 252 begin_any_block (outfile, curr_bb); 253 } 254 w.print_rtl_single_with_indent (insn, curr_bb ? 6 : 4); 255 } 256 end_any_block (outfile, curr_bb); 257 fprintf (outfile, " ) ;; insn-chain\n"); 258 259 /* Additional RTL state. */ 260 fprintf (outfile, " (crtl\n"); 261 fprintf (outfile, " (return_rtx \n"); 262 w.print_rtl_single_with_indent (crtl->return_rtx, 6); 263 fprintf (outfile, " ) ;; return_rtx\n"); 264 fprintf (outfile, " ) ;; crtl\n"); 265 266 fprintf (outfile, ") ;; function \"%s\"\n", dname); 267 } 268