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
This commit is contained in:
parent
aec7773c94
commit
6c7dfafee6
@ -1,3 +1,18 @@
|
||||
2011-09-29 Georg-Johann Lay <avr@gjlay.de>
|
||||
|
||||
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 <artyom.shinkaroff@gmail.com>
|
||||
|
||||
* expr.c (do_store_flag): Expand vector comparison by
|
||||
|
@ -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"
|
||||
|
319
gcc/config/avr/avr-log.c
Normal file
319
gcc/config/avr/avr-log.c
Normal file
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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 > \
|
||||
|
Loading…
x
Reference in New Issue
Block a user