This is a tentative patch for better support of logging information for avr BE developers.
There are situations where it is more convenient to let the compiler produce information than to debug into the compiler. One example are -da dumps. This patch proposes a better support to print information by means of a printf-like function via %-codes. The current debug output with avr-gcc's option -mdeb produces bulk of information that is very hard to read because - there is much output - there is no information on current_function_decl - there is no information on current pass name/number - there is no print-like function so the trees, rtxes so that it is tedious to get formatted output. For example, the following call to avr_edump static int avr_OS_main_function_p (tree func) { avr_edump ("%?: %t\n", func); return avr_lookup_function_attribute1 (func, "OS_main"); } prints additional information in a convenient way (foo is function to be compiled): avr_OS_main_function_p[foo:pro_and_epilogue(202)]: <function_decl # foo type <function_type # type <void_type # void VOID ... Wondering that similar functionality is not provided by GCC itself, I wrote this patch. GCC's diagnostic seems to be overwhelmingly complicated and not intended for the purpose mentioned above. The code is dead code at the moment. No function in the BE uses the new functions. This patch just adds them. Moreover; I don't know if avr port maintainers or global reviewers like such stuff in the compiler... Therefore it's just tentative draft. Supported %-codes are: 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 args -- 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) These codes cover great deal of BE developers needs and if something is missing it can be added easily. The calling itself is not as straight forward as it could be in the presence of variadic macros (to get __FUNCTION__), but that should not matter here. Johann * config/avr/avr-protos.h (avr_edump, avr_fdump): New macros. (avr__set_caller_e, avr__set_caller_f): New prototypes. * config/avr/avr.c: Include tree-pass.h. (avr__caller, avr__stream): New static variables. (avr__fdump_e, avr__fdump_f, avr__vadump): New static functions. (avr__set_caller_e, avr__set_caller_f): New functions.
Index: config/avr/avr-protos.h =================================================================== --- config/avr/avr-protos.h (revision 179257) +++ config/avr/avr-protos.h (working copy) @@ -111,3 +111,9 @@ extern rtx avr_incoming_return_addr_rtx #ifdef REAL_VALUE_TYPE extern void asm_output_float (FILE *file, REAL_VALUE_TYPE n); #endif + +#define avr_edump (avr__set_caller_e (__FUNCTION__)) +#define avr_fdump (avr__set_caller_f (__FUNCTION__)) + +extern int (*avr__set_caller_e (const char*))(const char*, ...); +extern int (*avr__set_caller_f (const char*))(FILE*, const char*, ...); Index: config/avr/avr.c =================================================================== --- config/avr/avr.c (revision 179257) +++ config/avr/avr.c (working copy) @@ -7810,5 +7810,233 @@ avr_expand_builtin (tree exp, rtx target gcc_unreachable (); } + +/*********************************************************************** + ** Logging, for BE developers only + ***********************************************************************/ + +#include "tree-pass.h" + +static const char* avr__caller = "?"; +static FILE* avr__stream; + +static void avr__vadump (FILE*, const char*, va_list); + +static int +avr__fdump_f (FILE *stream, const char* fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + if (stream) + avr__vadump (stream, fmt, ap); + va_end (ap); + + return 1; +} + +int (* +avr__set_caller_f (const char* caller) + )(FILE*, const char*, ...) +{ + avr__caller = caller; + + return avr__fdump_f; +} + +static int +avr__fdump_e (const char* fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + avr__vadump (stderr, fmt, ap); + va_end (ap); + + return 1; +} + +int (* +avr__set_caller_e (const char* caller) + )(const char*, ...) +{ + avr__caller = caller; + avr__stream = stderr; + + return avr__fdump_e; +} + +/* + -- 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 args -- + 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) +*/ + +static void +avr__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); + } + 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__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__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': + abort(); + + default: + fputc (*(fmt-1), file); + } + break; /* % */ + } + } + + fflush (file); +} #include "gt-avr.h"