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