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