11debfc3dSmrg /* Subroutines for log output for Atmel AVR back end.
2*8feb0f0bSmrg Copyright (C) 2011-2020 Free Software Foundation, Inc.
31debfc3dSmrg Contributed by Georg-Johann Lay (avr@gjlay.de)
41debfc3dSmrg
51debfc3dSmrg This file is part of GCC.
61debfc3dSmrg
71debfc3dSmrg GCC is free software; you can redistribute it and/or modify
81debfc3dSmrg it under the terms of the GNU General Public License as published by
91debfc3dSmrg the Free Software Foundation; either version 3, or (at your option)
101debfc3dSmrg any later version.
111debfc3dSmrg
121debfc3dSmrg GCC is distributed in the hope that it will be useful,
131debfc3dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
141debfc3dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
151debfc3dSmrg GNU General Public License for more details.
161debfc3dSmrg
171debfc3dSmrg You should have received a copy of the GNU General Public License
181debfc3dSmrg along with GCC; see the file COPYING3. If not see
191debfc3dSmrg <http://www.gnu.org/licenses/>. */
201debfc3dSmrg
21a2dc1f3fSmrg #define IN_TARGET_CODE 1
22a2dc1f3fSmrg
231debfc3dSmrg #include "config.h"
241debfc3dSmrg #include "system.h"
251debfc3dSmrg #include "coretypes.h"
261debfc3dSmrg #include "tm.h"
271debfc3dSmrg #include "function.h"
281debfc3dSmrg #include "rtl.h"
291debfc3dSmrg #include "tree.h"
301debfc3dSmrg #include "tree-pass.h" /* for current_pass */
311debfc3dSmrg #include "memmodel.h"
321debfc3dSmrg #include "tm_p.h"
331debfc3dSmrg #include "print-tree.h"
341debfc3dSmrg
351debfc3dSmrg /* This file supplies some functions for AVR back-end developers
361debfc3dSmrg with a printf-like interface. The functions are called through
371debfc3dSmrg macros `avr_dump', `avr_edump' or `avr_fdump' from avr-protos.h:
381debfc3dSmrg
391debfc3dSmrg avr_fdump (FILE *stream, const char *fmt, ...);
401debfc3dSmrg avr_edump (fmt, ...) is a shortcut for avr_fdump (stderr, fmt, ...)
411debfc3dSmrg avr_dump (fmt, ...) is a shortcut for avr_fdump (dump_file, fmt, ...)
421debfc3dSmrg
431debfc3dSmrg == known %-codes ==
441debfc3dSmrg
451debfc3dSmrg b: bool
461debfc3dSmrg r: rtx
471debfc3dSmrg t: tree
481debfc3dSmrg T: tree (brief)
491debfc3dSmrg C: enum rtx_code
501debfc3dSmrg m: machine_mode
511debfc3dSmrg R: enum reg_class
521debfc3dSmrg L: insn list
531debfc3dSmrg H: location_t
541debfc3dSmrg
551debfc3dSmrg == no arguments ==
561debfc3dSmrg
571debfc3dSmrg A: call abort()
581debfc3dSmrg f: current_function_name()
591debfc3dSmrg F: caller (via __FUNCTION__)
601debfc3dSmrg P: Pass name and number
611debfc3dSmrg ?: Print caller, current function and pass info
621debfc3dSmrg !: Ditto, but only print if in a pass with static pass number,
631debfc3dSmrg else return.
641debfc3dSmrg
651debfc3dSmrg == same as printf ==
661debfc3dSmrg
671debfc3dSmrg %: %
681debfc3dSmrg c: char
691debfc3dSmrg s: string
701debfc3dSmrg d: int (decimal)
711debfc3dSmrg x: int (hex)
721debfc3dSmrg */
731debfc3dSmrg
741debfc3dSmrg /* Set according to -mlog= option. */
751debfc3dSmrg avr_log_t avr_log;
761debfc3dSmrg
771debfc3dSmrg /* The worker function implementing the %-codes */
781debfc3dSmrg static void avr_log_vadump (FILE*, const char*, va_list);
791debfc3dSmrg
801debfc3dSmrg /* Wrapper for avr_log_vadump. If STREAM is NULL we are called by avr_dump,
811debfc3dSmrg i.e. output to dump_file if available. The 2nd argument is __FUNCTION__.
821debfc3dSmrg The 3rd argument is the format string. */
831debfc3dSmrg
841debfc3dSmrg int
avr_vdump(FILE * stream,const char * caller,...)851debfc3dSmrg avr_vdump (FILE *stream, const char *caller, ...)
861debfc3dSmrg {
871debfc3dSmrg va_list ap;
881debfc3dSmrg
89a2dc1f3fSmrg if (stream == NULL && dump_file)
901debfc3dSmrg stream = dump_file;
911debfc3dSmrg
921debfc3dSmrg va_start (ap, caller);
931debfc3dSmrg if (stream)
941debfc3dSmrg avr_log_vadump (stream, caller, ap);
951debfc3dSmrg va_end (ap);
961debfc3dSmrg
971debfc3dSmrg return 1;
981debfc3dSmrg }
991debfc3dSmrg
1001debfc3dSmrg
1011debfc3dSmrg /* Worker function implementing the %-codes and forwarding to
1021debfc3dSmrg respective print/dump function. */
1031debfc3dSmrg
1041debfc3dSmrg static void
avr_log_vadump(FILE * file,const char * caller,va_list ap)1051debfc3dSmrg avr_log_vadump (FILE *file, const char *caller, va_list ap)
1061debfc3dSmrg {
1071debfc3dSmrg char bs[3] = {'\\', '?', '\0'};
1081debfc3dSmrg
1091debfc3dSmrg /* 3rd proper argument is always the format string. */
1101debfc3dSmrg const char *fmt = va_arg (ap, const char*);
1111debfc3dSmrg
1121debfc3dSmrg while (*fmt)
1131debfc3dSmrg {
1141debfc3dSmrg switch (*fmt++)
1151debfc3dSmrg {
1161debfc3dSmrg default:
1171debfc3dSmrg fputc (*(fmt-1), file);
1181debfc3dSmrg break;
1191debfc3dSmrg
1201debfc3dSmrg case '\\':
1211debfc3dSmrg bs[1] = *fmt++;
1221debfc3dSmrg fputs (bs, file);
1231debfc3dSmrg break;
1241debfc3dSmrg
1251debfc3dSmrg case '%':
1261debfc3dSmrg switch (*fmt++)
1271debfc3dSmrg {
1281debfc3dSmrg case '%':
1291debfc3dSmrg fputc ('%', file);
1301debfc3dSmrg break;
1311debfc3dSmrg
1321debfc3dSmrg case 't':
1331debfc3dSmrg {
1341debfc3dSmrg tree t = va_arg (ap, tree);
1351debfc3dSmrg if (NULL_TREE == t)
1361debfc3dSmrg fprintf (file, "<NULL-TREE>");
1371debfc3dSmrg else
1381debfc3dSmrg {
1391debfc3dSmrg if (stderr == file)
1401debfc3dSmrg debug_tree (t);
1411debfc3dSmrg else
1421debfc3dSmrg {
1431debfc3dSmrg print_node (file, "", t, 0);
1441debfc3dSmrg putc ('\n', file);
1451debfc3dSmrg }
1461debfc3dSmrg }
1471debfc3dSmrg break;
1481debfc3dSmrg }
1491debfc3dSmrg
1501debfc3dSmrg case 'T':
151a2dc1f3fSmrg {
152a2dc1f3fSmrg tree t = va_arg (ap, tree);
153a2dc1f3fSmrg if (NULL_TREE == t)
154a2dc1f3fSmrg fprintf (file, "<NULL-TREE>");
155a2dc1f3fSmrg else
156a2dc1f3fSmrg print_node_brief (file, "", t, 3);
157a2dc1f3fSmrg }
1581debfc3dSmrg break;
1591debfc3dSmrg
1601debfc3dSmrg case 'd':
1611debfc3dSmrg fprintf (file, "%d", va_arg (ap, int));
1621debfc3dSmrg break;
1631debfc3dSmrg
1641debfc3dSmrg case 'x':
1651debfc3dSmrg fprintf (file, "%x", va_arg (ap, int));
1661debfc3dSmrg break;
1671debfc3dSmrg
1681debfc3dSmrg case 'b':
1691debfc3dSmrg fprintf (file, "%s", va_arg (ap, int) ? "true" : "false");
1701debfc3dSmrg break;
1711debfc3dSmrg
1721debfc3dSmrg case 'c':
1731debfc3dSmrg fputc (va_arg (ap, int), file);
1741debfc3dSmrg break;
1751debfc3dSmrg
1761debfc3dSmrg case 'r':
1771debfc3dSmrg print_inline_rtx (file, va_arg (ap, rtx), 0);
1781debfc3dSmrg break;
1791debfc3dSmrg
1801debfc3dSmrg case 'L':
1811debfc3dSmrg {
1821debfc3dSmrg rtx_insn *insn = safe_as_a <rtx_insn *> (va_arg (ap, rtx));
1831debfc3dSmrg
1841debfc3dSmrg while (insn)
1851debfc3dSmrg {
1861debfc3dSmrg print_inline_rtx (file, insn, 0);
1871debfc3dSmrg fprintf (file, "\n");
1881debfc3dSmrg insn = NEXT_INSN (insn);
1891debfc3dSmrg }
1901debfc3dSmrg break;
1911debfc3dSmrg }
1921debfc3dSmrg
1931debfc3dSmrg case 'f':
1941debfc3dSmrg if (cfun && cfun->decl)
1951debfc3dSmrg fputs (current_function_name(), file);
1961debfc3dSmrg break;
1971debfc3dSmrg
1981debfc3dSmrg case 's':
1991debfc3dSmrg {
2001debfc3dSmrg const char *str = va_arg (ap, char*);
2011debfc3dSmrg fputs (str ? str : "(null)", file);
2021debfc3dSmrg }
2031debfc3dSmrg break;
2041debfc3dSmrg
2051debfc3dSmrg case 'm':
2061debfc3dSmrg fputs (GET_MODE_NAME ((machine_mode) va_arg (ap, int)),
2071debfc3dSmrg file);
2081debfc3dSmrg break;
2091debfc3dSmrg
2101debfc3dSmrg case 'C':
2111debfc3dSmrg fputs (rtx_name[va_arg (ap, int)], file);
2121debfc3dSmrg break;
2131debfc3dSmrg
2141debfc3dSmrg case 'R':
2151debfc3dSmrg fputs (reg_class_names[va_arg (ap, int)], file);
2161debfc3dSmrg break;
2171debfc3dSmrg
2181debfc3dSmrg case 'F':
2191debfc3dSmrg fputs (caller, file);
2201debfc3dSmrg break;
2211debfc3dSmrg
2221debfc3dSmrg case 'H':
2231debfc3dSmrg {
2241debfc3dSmrg location_t loc = va_arg (ap, location_t);
2251debfc3dSmrg
2261debfc3dSmrg if (BUILTINS_LOCATION == loc)
2271debfc3dSmrg fprintf (file, "<BUILTIN-LOCATION>");
2281debfc3dSmrg else if (UNKNOWN_LOCATION == loc)
2291debfc3dSmrg fprintf (file, "<UNKNOWN-LOCATION>");
2301debfc3dSmrg else
2311debfc3dSmrg fprintf (file, "%s:%d",
2321debfc3dSmrg LOCATION_FILE (loc), LOCATION_LINE (loc));
2331debfc3dSmrg
2341debfc3dSmrg break;
2351debfc3dSmrg }
2361debfc3dSmrg
2371debfc3dSmrg case '!':
2381debfc3dSmrg if (!current_pass)
2391debfc3dSmrg return;
2401debfc3dSmrg /* FALLTHRU */
2411debfc3dSmrg
2421debfc3dSmrg case '?':
2431debfc3dSmrg avr_vdump (file, caller, "%F[%f:%P]");
2441debfc3dSmrg break;
2451debfc3dSmrg
2461debfc3dSmrg case 'P':
2471debfc3dSmrg if (current_pass)
2481debfc3dSmrg fprintf (file, "%s(%d)",
2491debfc3dSmrg current_pass->name,
2501debfc3dSmrg current_pass->static_pass_number);
2511debfc3dSmrg else
2521debfc3dSmrg fprintf (file, "pass=?");
2531debfc3dSmrg
2541debfc3dSmrg break;
2551debfc3dSmrg
2561debfc3dSmrg case 'A':
2571debfc3dSmrg fflush (file);
2581debfc3dSmrg abort();
2591debfc3dSmrg
2601debfc3dSmrg default:
2611debfc3dSmrg /* Unknown %-code: Stop printing */
2621debfc3dSmrg
2631debfc3dSmrg fprintf (file, "??? %%%c ???%s\n", *(fmt-1), fmt);
2641debfc3dSmrg fmt = "";
2651debfc3dSmrg
2661debfc3dSmrg break;
2671debfc3dSmrg }
2681debfc3dSmrg break; /* % */
2691debfc3dSmrg }
2701debfc3dSmrg }
2711debfc3dSmrg
2721debfc3dSmrg fflush (file);
2731debfc3dSmrg }
2741debfc3dSmrg
2751debfc3dSmrg
2761debfc3dSmrg /* Called from avr.c:avr_option_override().
2771debfc3dSmrg Parse argument of -mlog= and set respective fields in avr_log. */
2781debfc3dSmrg
2791debfc3dSmrg void
avr_log_set_avr_log(void)2801debfc3dSmrg avr_log_set_avr_log (void)
2811debfc3dSmrg {
2821debfc3dSmrg bool all = TARGET_ALL_DEBUG != 0;
2831debfc3dSmrg
2841debfc3dSmrg if (all)
2851debfc3dSmrg avr_log_details = "all";
2861debfc3dSmrg
2871debfc3dSmrg if (all || avr_log_details)
2881debfc3dSmrg {
2891debfc3dSmrg /* Adding , at beginning and end of string makes searching easier. */
2901debfc3dSmrg
2911debfc3dSmrg char *str = (char*) alloca (3 + strlen (avr_log_details));
2921debfc3dSmrg bool info;
2931debfc3dSmrg
2941debfc3dSmrg str[0] = ',';
2951debfc3dSmrg strcat (stpcpy (str+1, avr_log_details), ",");
2961debfc3dSmrg
297a2dc1f3fSmrg all |= strstr (str, ",all,") != NULL;
298a2dc1f3fSmrg info = strstr (str, ",?,") != NULL;
2991debfc3dSmrg
3001debfc3dSmrg if (info)
3011debfc3dSmrg fprintf (stderr, "\n-mlog=");
3021debfc3dSmrg
3031debfc3dSmrg #define SET_DUMP_DETAIL(S) \
3041debfc3dSmrg do { \
305a2dc1f3fSmrg avr_log.S = (all || strstr (str, "," #S ",") != NULL); \
3061debfc3dSmrg if (info) \
3071debfc3dSmrg fprintf (stderr, #S ","); \
3081debfc3dSmrg } while (0)
3091debfc3dSmrg
3101debfc3dSmrg SET_DUMP_DETAIL (address_cost);
3111debfc3dSmrg SET_DUMP_DETAIL (builtin);
3121debfc3dSmrg SET_DUMP_DETAIL (constraints);
313a2dc1f3fSmrg SET_DUMP_DETAIL (insn_addresses);
3141debfc3dSmrg SET_DUMP_DETAIL (legitimate_address_p);
3151debfc3dSmrg SET_DUMP_DETAIL (legitimize_address);
3161debfc3dSmrg SET_DUMP_DETAIL (legitimize_reload_address);
3171debfc3dSmrg SET_DUMP_DETAIL (progmem);
3181debfc3dSmrg SET_DUMP_DETAIL (rtx_costs);
3191debfc3dSmrg
3201debfc3dSmrg #undef SET_DUMP_DETAIL
3211debfc3dSmrg
3221debfc3dSmrg if (info)
3231debfc3dSmrg fprintf (stderr, "?\n\n");
3241debfc3dSmrg }
3251debfc3dSmrg }
326