1 /* Subroutines for log output for Atmel AVR back end. 2 Copyright (C) 2011-2016 Free Software Foundation, Inc. 3 Contributed by Georg-Johann Lay (avr@gjlay.de) 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GCC is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #include "config.h" 22 #include "system.h" 23 #include "coretypes.h" 24 #include "tm.h" 25 #include "function.h" 26 #include "rtl.h" 27 #include "tree.h" 28 #include "tree-pass.h" /* for current_pass */ 29 #include "tm_p.h" 30 #include "print-tree.h" 31 32 /* This file supplies some functions for AVR back-end developers 33 with a printf-like interface. The functions are called through 34 macros `avr_dump', `avr_edump' or `avr_fdump' from avr-protos.h: 35 36 avr_fdump (FILE *stream, const char *fmt, ...); 37 avr_edump (fmt, ...) is a shortcut for avr_fdump (stderr, fmt, ...) 38 avr_dump (fmt, ...) is a shortcut for avr_fdump (dump_file, fmt, ...) 39 40 == known %-codes == 41 42 b: bool 43 r: rtx 44 t: tree 45 T: tree (brief) 46 C: enum rtx_code 47 m: machine_mode 48 R: enum reg_class 49 L: insn list 50 H: location_t 51 52 == no arguments == 53 54 A: call abort() 55 f: current_function_name() 56 F: caller (via __FUNCTION__) 57 P: Pass name and number 58 ?: Print caller, current function and pass info 59 !: Ditto, but only print if in a pass with static pass number, 60 else return. 61 62 == same as printf == 63 64 %: % 65 c: char 66 s: string 67 d: int (decimal) 68 x: int (hex) 69 */ 70 71 /* Set according to -mlog= option. */ 72 avr_log_t avr_log; 73 74 /* The worker function implementing the %-codes */ 75 static void avr_log_vadump (FILE*, const char*, va_list); 76 77 /* Wrapper for avr_log_vadump. If STREAM is NULL we are called by avr_dump, 78 i.e. output to dump_file if available. The 2nd argument is __FUNCTION__. 79 The 3rd argument is the format string. */ 80 81 int 82 avr_vdump (FILE *stream, const char *caller, ...) 83 { 84 va_list ap; 85 86 if (NULL == stream && dump_file) 87 stream = dump_file; 88 89 va_start (ap, caller); 90 if (stream) 91 avr_log_vadump (stream, caller, ap); 92 va_end (ap); 93 94 return 1; 95 } 96 97 98 /* Worker function implementing the %-codes and forwarding to 99 respective print/dump function. */ 100 101 static void 102 avr_log_vadump (FILE *file, const char *caller, va_list ap) 103 { 104 char bs[3] = {'\\', '?', '\0'}; 105 106 /* 3rd proper argument is always the format string. */ 107 const char *fmt = va_arg (ap, const char*); 108 109 while (*fmt) 110 { 111 switch (*fmt++) 112 { 113 default: 114 fputc (*(fmt-1), file); 115 break; 116 117 case '\\': 118 bs[1] = *fmt++; 119 fputs (bs, file); 120 break; 121 122 case '%': 123 switch (*fmt++) 124 { 125 case '%': 126 fputc ('%', file); 127 break; 128 129 case 't': 130 { 131 tree t = va_arg (ap, tree); 132 if (NULL_TREE == t) 133 fprintf (file, "<NULL-TREE>"); 134 else 135 { 136 if (stderr == file) 137 debug_tree (t); 138 else 139 { 140 print_node (file, "", t, 0); 141 putc ('\n', file); 142 } 143 } 144 break; 145 } 146 147 case 'T': 148 print_node_brief (file, "", va_arg (ap, tree), 3); 149 break; 150 151 case 'd': 152 fprintf (file, "%d", va_arg (ap, int)); 153 break; 154 155 case 'x': 156 fprintf (file, "%x", va_arg (ap, int)); 157 break; 158 159 case 'b': 160 fprintf (file, "%s", va_arg (ap, int) ? "true" : "false"); 161 break; 162 163 case 'c': 164 fputc (va_arg (ap, int), file); 165 break; 166 167 case 'r': 168 print_inline_rtx (file, va_arg (ap, rtx), 0); 169 break; 170 171 case 'L': 172 { 173 rtx_insn *insn = safe_as_a <rtx_insn *> (va_arg (ap, rtx)); 174 175 while (insn) 176 { 177 print_inline_rtx (file, insn, 0); 178 fprintf (file, "\n"); 179 insn = NEXT_INSN (insn); 180 } 181 break; 182 } 183 184 case 'f': 185 if (cfun && cfun->decl) 186 fputs (current_function_name(), file); 187 break; 188 189 case 's': 190 { 191 const char *str = va_arg (ap, char*); 192 fputs (str ? str : "(null)", file); 193 } 194 break; 195 196 case 'm': 197 fputs (GET_MODE_NAME ((machine_mode) va_arg (ap, int)), 198 file); 199 break; 200 201 case 'C': 202 fputs (rtx_name[va_arg (ap, int)], file); 203 break; 204 205 case 'R': 206 fputs (reg_class_names[va_arg (ap, int)], file); 207 break; 208 209 case 'F': 210 fputs (caller, file); 211 break; 212 213 case 'H': 214 { 215 location_t loc = va_arg (ap, location_t); 216 217 if (BUILTINS_LOCATION == loc) 218 fprintf (file, "<BUILTIN-LOCATION>"); 219 else if (UNKNOWN_LOCATION == loc) 220 fprintf (file, "<UNKNOWN-LOCATION>"); 221 else 222 fprintf (file, "%s:%d", 223 LOCATION_FILE (loc), LOCATION_LINE (loc)); 224 225 break; 226 } 227 228 case '!': 229 if (!current_pass) 230 return; 231 /* FALLTHRU */ 232 233 case '?': 234 avr_vdump (file, caller, "%F[%f:%P]"); 235 break; 236 237 case 'P': 238 if (current_pass) 239 fprintf (file, "%s(%d)", 240 current_pass->name, 241 current_pass->static_pass_number); 242 else 243 fprintf (file, "pass=?"); 244 245 break; 246 247 case 'A': 248 fflush (file); 249 abort(); 250 251 default: 252 /* Unknown %-code: Stop printing */ 253 254 fprintf (file, "??? %%%c ???%s\n", *(fmt-1), fmt); 255 fmt = ""; 256 257 break; 258 } 259 break; /* % */ 260 } 261 } 262 263 fflush (file); 264 } 265 266 267 /* Called from avr.c:avr_option_override(). 268 Parse argument of -mlog= and set respective fields in avr_log. */ 269 270 void 271 avr_log_set_avr_log (void) 272 { 273 bool all = TARGET_ALL_DEBUG != 0; 274 275 if (all) 276 avr_log_details = "all"; 277 278 if (all || avr_log_details) 279 { 280 /* Adding , at beginning and end of string makes searching easier. */ 281 282 char *str = (char*) alloca (3 + strlen (avr_log_details)); 283 bool info; 284 285 str[0] = ','; 286 strcat (stpcpy (str+1, avr_log_details), ","); 287 288 all |= NULL != strstr (str, ",all,"); 289 info = NULL != strstr (str, ",?,"); 290 291 if (info) 292 fprintf (stderr, "\n-mlog="); 293 294 #define SET_DUMP_DETAIL(S) \ 295 do { \ 296 avr_log.S = (all || NULL != strstr (str, "," #S ",")); \ 297 if (info) \ 298 fprintf (stderr, #S ","); \ 299 } while (0) 300 301 SET_DUMP_DETAIL (address_cost); 302 SET_DUMP_DETAIL (builtin); 303 SET_DUMP_DETAIL (constraints); 304 SET_DUMP_DETAIL (legitimate_address_p); 305 SET_DUMP_DETAIL (legitimize_address); 306 SET_DUMP_DETAIL (legitimize_reload_address); 307 SET_DUMP_DETAIL (progmem); 308 SET_DUMP_DETAIL (rtx_costs); 309 310 #undef SET_DUMP_DETAIL 311 312 if (info) 313 fprintf (stderr, "?\n\n"); 314 } 315 } 316