OSDN Git Service

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