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