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