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