From 47fe598eb8e215961cb05d5424b5ef10c358ad9a Mon Sep 17 00:00:00 2001 From: gjl Date: Thu, 29 Sep 2011 11:51:59 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@179344 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 15 +++ gcc/config.gcc | 4 +- gcc/config/avr/avr-log.c | 319 ++++++++++++++++++++++++++++++++++++++++++++ gcc/config/avr/avr-protos.h | 21 +++ gcc/config/avr/avr.c | 2 + gcc/config/avr/avr.opt | 3 + gcc/config/avr/t-avr | 4 + 7 files changed, 366 insertions(+), 2 deletions(-) create mode 100644 gcc/config/avr/avr-log.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9cadb71..5cf8ceaa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2011-09-29 Georg-Johann Lay + + 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. + 2011-09-29 Artjoms Sinkarovs * expr.c (do_store_flag): Expand vector comparison by diff --git a/gcc/config.gcc b/gcc/config.gcc index cf11364..2456402 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -939,14 +939,14 @@ avr-*-rtems*) libgcc_tm_file="$libgcc_tm_file avr/avr-lib.h" tmake_file="avr/t-avr t-rtems avr/t-rtems" extra_gcc_objs="driver-avr.o avr-devices.o" - extra_objs="avr-devices.o" + extra_objs="avr-devices.o avr-log.o" ;; avr-*-*) tm_file="elfos.h avr/elf.h avr/avr.h dbxelf.h newlib-stdint.h" libgcc_tm_file="$libgcc_tm_file avr/avr-lib.h" use_gcc_stdint=wrap extra_gcc_objs="driver-avr.o avr-devices.o" - extra_objs="avr-devices.o" + extra_objs="avr-devices.o avr-log.o" ;; bfin*-elf*) tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h bfin/elf.h" 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 + . */ + +#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, ""); + 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, ""); + 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 > \ -- 2.7.4