aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2011-09-29 11:51:59 +0000
committerGeorg-Johann Lay <gjl@gcc.gnu.org>2011-09-29 11:51:59 +0000
commit6c7dfafee68e3c18aa6c0f7c42e3f86bce196d7e (patch)
treea686f9d9d2c7a4dd98ad61ff4e2b8ce052f3bc0c /gcc/config
parentaec7773c94d61d2b47632b9394abbc78417afa21 (diff)
downloadgcc-6c7dfafee68e3c18aa6c0f7c42e3f86bce196d7e.zip
gcc-6c7dfafee68e3c18aa6c0f7c42e3f86bce196d7e.tar.gz
gcc-6c7dfafee68e3c18aa6c0f7c42e3f86bce196d7e.tar.bz2
re PR target/50566 ([avr]: Add support for better logging similar to -mdeb)
PR target/50566 * config.gcc (extra_objs): Add avr-log.o for $target in: avr-*-rtems*, avr-*-*. * config/avr/t-avr (avr-log.o): New rule to compile... * config/avr/avr-log.c: ...this new file. * config/avr/avr.opt (mlog=): New option. * config/avr/avr-protos.h (avr_edump, avr_fdump): New macros. (avr_log_set_caller_e, avr_log_set_caller_f): New prototypes. (avr_log_set_avr_log): New prototype. (avr_log_t): New typedef. (avr_log): New declaration. * config/avr/avr.c (avr_option_override): Call avr_log_set_avr_log. From-SVN: r179344
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/avr/avr-log.c319
-rw-r--r--gcc/config/avr/avr-protos.h21
-rw-r--r--gcc/config/avr/avr.c2
-rw-r--r--gcc/config/avr/avr.opt3
-rw-r--r--gcc/config/avr/t-avr4
5 files changed, 349 insertions, 0 deletions
diff --git a/gcc/config/avr/avr-log.c b/gcc/config/avr/avr-log.c
new file mode 100644
index 0000000..87cbd23
--- /dev/null
+++ b/gcc/config/avr/avr-log.c
@@ -0,0 +1,319 @@
+/* Subroutines for log output for Atmel AVR back end.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+ Contributed by Georg-Johann Lay (avr@gjlay.de)
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tree.h"
+#include "output.h"
+#include "input.h"
+#include "function.h"
+#include "tm_p.h"
+#include "tree-pass.h"
+
+/* This file supplies some functions for AVR back-end developers
+ with a printf-like interface. The functions are called through
+ macros avr_edump or avr_fdump from avr-protos.h:
+
+ avr_edump (const char * fmt, ...);
+
+ avr_fdump (FILE * stream, const char * fmt, ...);
+
+ avr_edump (fmt, ...) is a shortcut for avr_fdump (stderr, fmt, ...)
+
+ == known %-codes ==
+
+ r: rtx
+ t: tree
+ T: tree (brief)
+ C: enum rtx_code
+ m: enum machine_mode
+ R: enum reg_class
+ L: insn list
+ H: location_t
+
+ == no arguments ==
+
+ A: call abort()
+ f: current_function_name()
+ F: caller (via __FUNCTION__)
+ P: Pass name and number
+ ?: Print caller, current function and pass info
+
+ == same as printf ==
+
+ %: %
+ c: char
+ s: string
+ d: int (decimal)
+ x: int (hex)
+*/
+
+/* Set according to -mlog= option. */
+avr_log_t avr_log;
+
+/* The caller as of __FUNCTION__ */
+static const char *avr_log_caller = "?";
+
+/* The worker function implementing the %-codes */
+static void avr_log_vadump (FILE*, const char*, va_list);
+
+/* As we have no variadic macros, avr_edump maps to a call to
+ avr_log_set_caller_e which saves __FUNCTION__ to avr_log_caller and
+ returns a function pointer to avr_log_fdump_e. avr_fdump_e
+ gets the printf-like arguments and calls avr_log_vadump, the
+ worker function. avr_fdump works the same way. */
+
+/* Provide avr_log_fdump_e/f so that avr_log_set_caller_e/_f can return
+ their address. */
+
+static int
+avr_log_fdump_e (const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ avr_log_vadump (stderr, fmt, ap);
+ va_end (ap);
+
+ return 1;
+}
+
+static int
+avr_log_fdump_f (FILE *stream, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ if (stream)
+ avr_log_vadump (stream, fmt, ap);
+ va_end (ap);
+
+ return 1;
+}
+
+/* Macros avr_edump/avr_fdump map to calls of the following two functions,
+ respectively. You don't need to call them directly. */
+
+int (*
+avr_log_set_caller_e (const char *caller)
+ )(const char*, ...)
+{
+ avr_log_caller = caller;
+
+ return avr_log_fdump_e;
+}
+
+int (*
+avr_log_set_caller_f (const char *caller)
+ )(FILE*, const char*, ...)
+{
+ avr_log_caller = caller;
+
+ return avr_log_fdump_f;
+}
+
+/* Worker function implementing the %-codes and forwarning to
+ respective print/dump function. */
+
+static void
+avr_log_vadump (FILE *file, const char *fmt, va_list ap)
+{
+ char bs[3] = {'\\', '?', '\0'};
+
+ while (*fmt)
+ {
+ switch (*fmt++)
+ {
+ default:
+ fputc (*(fmt-1), file);
+ break;
+
+ case '\\':
+ bs[1] = *fmt++;
+ fputs (bs, file);
+ break;
+
+ case '%':
+ switch (*fmt++)
+ {
+ case '%':
+ fputc ('%', file);
+ break;
+
+ case 't':
+ {
+ tree t = va_arg (ap, tree);
+ if (NULL_TREE == t)
+ fprintf (file, "<NULL-TREE>");
+ else
+ {
+ if (stderr == file)
+ debug_tree (t);
+ else
+ {
+ print_node (file, "", t, 0);
+ putc ('\n', file);
+ }
+ }
+ break;
+ }
+
+ case 'T':
+ print_node_brief (file, "", va_arg (ap, tree), 3);
+ break;
+
+ case 'd':
+ fprintf (file, "%d", va_arg (ap, int));
+ break;
+
+ case 'x':
+ fprintf (file, "%x", va_arg (ap, int));
+ break;
+
+ case 'c':
+ fputc (va_arg (ap, int), file);
+ break;
+
+ case 'r':
+ print_inline_rtx (file, va_arg (ap, rtx), 0);
+ break;
+
+ case 'L':
+ {
+ rtx insn = va_arg (ap, rtx);
+
+ while (insn)
+ {
+ print_inline_rtx (file, insn, 0);
+ fprintf (file, "\n");
+ insn = NEXT_INSN (insn);
+ }
+ break;
+ }
+
+ case 'f':
+ if (cfun && cfun->decl)
+ fputs (current_function_name(), file);
+ break;
+
+ case 's':
+ {
+ const char *str = va_arg (ap, char*);
+ fputs (str ? str : "(null)", file);
+ }
+ break;
+
+ case 'm':
+ fputs (GET_MODE_NAME (va_arg (ap, enum machine_mode)), file);
+ break;
+
+ case 'C':
+ fputs (rtx_name[va_arg (ap, enum rtx_code)], file);
+ break;
+
+ case 'R':
+ fputs (reg_class_names[va_arg (ap, enum reg_class)], file);
+ break;
+
+ case 'F':
+ fputs (avr_log_caller, file);
+ break;
+
+ case 'H':
+ {
+ location_t loc = va_arg (ap, location_t);
+
+ if (BUILTINS_LOCATION == loc)
+ fprintf (file, "<BUILTIN-LOCATION");
+ else if (UNKNOWN_LOCATION == loc)
+ fprintf (file, "<UNKNOWN-LOCATION>");
+ else
+ fprintf (file, "%s:%d",
+ LOCATION_FILE (loc), LOCATION_LINE (loc));
+
+ break;
+ }
+
+ case '!':
+ if (!current_pass)
+ return;
+ /* FALLTHRU */
+
+ case '?':
+ avr_log_fdump_f (file, "%F[%f:%P]");
+ break;
+
+ case 'P':
+ if (current_pass)
+ fprintf (file, "%s(%d)",
+ current_pass->name,
+ current_pass->static_pass_number);
+ else
+ fprintf (file, "pass=?");
+
+ break;
+
+ case 'A':
+ fflush (file);
+ abort();
+
+ default:
+ fputc (*(fmt-1), file);
+ }
+ break; /* % */
+ }
+ }
+
+ fflush (file);
+}
+
+
+/* Called from avr.c:avr_option_override().
+ Parse argument of -mlog= and set respective fields in avr_log. */
+
+void
+avr_log_set_avr_log (void)
+{
+ if (avr_log_details)
+ {
+ /* Adding , at beginning and end of string makes searching easier. */
+
+ char *str = (char*) alloca (3 + strlen (avr_log_details));
+
+ str[0] = ',';
+ strcat (stpcpy (str+1, avr_log_details), ",");
+
+#define SET_DUMP_DETAIL(S) \
+ avr_log.S = (TARGET_ALL_DEBUG \
+ || NULL != strstr (str, "," #S ",") \
+ || NULL != strstr (str, ",all,"))
+
+ SET_DUMP_DETAIL (rtx_costs);
+ SET_DUMP_DETAIL (legitimate_address_p);
+ SET_DUMP_DETAIL (legitimize_address);
+ SET_DUMP_DETAIL (legitimize_reload_address);
+ SET_DUMP_DETAIL (constraints);
+
+#undef SET_DUMP_DETAIL
+ }
+}
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index ed88ef7..e34666c 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -111,3 +111,24 @@ extern rtx avr_incoming_return_addr_rtx (void);
#ifdef REAL_VALUE_TYPE
extern void asm_output_float (FILE *file, REAL_VALUE_TYPE n);
#endif
+
+/* From avr-log.c */
+
+#define avr_edump (avr_log_set_caller_e (__FUNCTION__))
+#define avr_fdump (avr_log_set_caller_f (__FUNCTION__))
+
+extern int (*avr_log_set_caller_e (const char*))(const char*, ...);
+extern int (*avr_log_set_caller_f (const char*))(FILE*, const char*, ...);
+
+extern void avr_log_set_avr_log (void);
+
+typedef struct
+{
+ unsigned rtx_costs :1;
+ unsigned legitimate_address_p :1;
+ unsigned legitimize_address :1;
+ unsigned legitimize_reload_address :1;
+ unsigned constraints :1;
+} avr_log_t;
+
+extern avr_log_t avr_log;
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 5ffa7fc..f3abf6c 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -359,6 +359,8 @@ avr_option_override (void)
zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO);
init_machine_status = avr_init_machine_status;
+
+ avr_log_set_avr_log();
}
/* Function to set up the backend function structure. */
diff --git a/gcc/config/avr/avr.opt b/gcc/config/avr/avr.opt
index 59d6393..1128dd3 100644
--- a/gcc/config/avr/avr.opt
+++ b/gcc/config/avr/avr.opt
@@ -29,6 +29,9 @@ Target RejectNegative Joined Var(avr_mcu_index) Init(0) Enum(avr_mcu)
mdeb
Target Report Undocumented Mask(ALL_DEBUG)
+mlog=
+Target RejectNegative Joined Undocumented Var(avr_log_details)
+
mint8
Target Report Mask(INT8)
Use an 8-bit 'int' type
diff --git a/gcc/config/avr/t-avr b/gcc/config/avr/t-avr
index 85f3745..30e8d96 100644
--- a/gcc/config/avr/t-avr
+++ b/gcc/config/avr/t-avr
@@ -30,6 +30,10 @@ avr-c.o: $(srcdir)/config/avr/avr-c.c \
$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(C_COMMON_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+avr-log.o: $(srcdir)/config/avr/avr-log.c \
+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(INPUT_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+
$(srcdir)/config/avr/avr-tables.opt: $(srcdir)/config/avr/genopt.sh \
$(srcdir)/config/avr/avr-mcus.def
$(SHELL) $(srcdir)/config/avr/genopt.sh $(srcdir)/config/avr > \