From 35ed8c5d87f3eb7b564f89782b8e197b3f04cd67 Mon Sep 17 00:00:00 2001 From: Sebastian Hack Date: Wed, 15 Dec 2004 17:30:49 +0000 Subject: [PATCH] Added new firm debug functions. [r4666] --- ir/common/debug.c | 109 +++++++++++++++++++++++++++++++++++++++++ ir/common/debug.h | 121 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 230 insertions(+) create mode 100644 ir/common/debug.c create mode 100644 ir/common/debug.h diff --git a/ir/common/debug.c b/ir/common/debug.c new file mode 100644 index 000000000..62274438e --- /dev/null +++ b/ir/common/debug.c @@ -0,0 +1,109 @@ +/** + * Debug facility. + * @author Michael Beck, Sebastian Hack + * @date 15.12.2004 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "irprintf.h" +#include "debug.h" + +#include "hashptr.h" +#include "obst.h" +#include "set.h" + +static struct obstack dbg_obst; +static set *module_set; + +struct _firm_dbg_module_t { + unsigned mask; + const char *name; + FILE *file; +}; + +static int module_cmp(const void *p1, const void *p2, size_t size) +{ + const firm_dbg_module_t *m1 = p1; + const firm_dbg_module_t *m2 = p2; + return strcmp(m1->name, m2->name); +} + +static void firm_dbg_init(void) +{ + obstack_init(&dbg_obst); + module_set = new_set(module_cmp, 16); +} + +firm_dbg_module_t *firm_dbg_register(const char *name) +{ + firm_dbg_module_t mod; + mod.mask = 0; + mod.name = name; + mod.file = stderr; + + if(!module_set) + firm_dbg_init(); + + return set_insert(module_set, &mod, sizeof(mod), HASH_STR(name, strlen(name))); +} + +void firm_dbg_set_mask(firm_dbg_module_t *module, unsigned mask) +{ + module->mask = mask; +} + +unsigned firm_dbg_get_mask(const firm_dbg_module_t *module) +{ + return module->mask; +} + +void firm_dbg_set_file(firm_dbg_module_t *module, FILE *file) +{ + module->file = file; +} + +typedef struct _msg_info_t { + const char *msg; + const firm_dbg_module_t *mod; +} msg_info_t; + +static void *make_msg_info(const firm_dbg_module_t *mod, const char *fmt, va_list args) +{ + static const char msg_header[] = "%s(%d) %s: "; + msg_info_t *res = obstack_alloc(&dbg_obst, sizeof(*res)); + + obstack_grow(&dbg_obst, msg_header, sizeof(msg_header) - 1); + ir_obst_vprintf(&dbg_obst, fmt, args); + res->msg = obstack_finish(&dbg_obst); + res->mod = mod; + return res; +} + +void *_firm_dbg_make_msg(const firm_dbg_module_t *mod, unsigned mask, const char *fmt, ...) +{ + void *res = NULL; + + if(mask == 0 || (mod->mask & mask)) { + va_list args; + va_start(args, fmt); + res = make_msg_info(mod, fmt, args); + va_end(args); + } + + return res; +} + +void _firm_dbg_print_msg(const char *filename, int line, const char *func, void *mi_ptr) +{ + msg_info_t *mi = mi_ptr; + if(mi) { + fprintf(mi->mod->file, mi->msg, filename, line, func); + obstack_free(&dbg_obst, mi); + } +} diff --git a/ir/common/debug.h b/ir/common/debug.h new file mode 100644 index 000000000..2f0c53aff --- /dev/null +++ b/ir/common/debug.h @@ -0,0 +1,121 @@ +/** + * Debug facility. + * @author Michael Beck, Sebastian Hack + * @date 15.12.2004 + */ + +#ifndef _FIRM_DEBUG_H +#define _FIRM_DEBUG_H + +#include + +enum firm_dbg_level_t { + LEVEL_DEFAULT = 0, /**< Prints always. Use with DBG(). */ + LEVEL_1 = 1, + LEVEL_2 = 2, + LEVEL_3 = 4, + LEVEL_4 = 8, + LEVEL_5 = 16, + + SET_LEVEL_1 = 1, /**< use with firm_dbg_set_mask(). */ + SET_LEVEL_2 = 3, + SET_LEVEL_3 = 7, + SET_LEVEL_4 = 15, + SET_LEVEL_5 = 31 +}; + +typedef struct _firm_dbg_module_t firm_dbg_module_t; + +/* Internal function to the debug module. */ +void *_firm_dbg_make_msg(const firm_dbg_module_t *mod, unsigned mask, const char *fmt, ...); + +/* Internal function to the debug module. */ +void _firm_dbg_print_msg(const char *filename, int line, const char *func, void *data); + +/** + * Register a module to the firm debug facility. + * If the module has already been registered, no new module is allocated + * but the handle is returned. By default, all messages go to @c stderr + * and the debug mask is set to 0, i.e. the module is muted. + * @param name The name of the module to register. + * @return The module handle. + */ +firm_dbg_module_t *firm_dbg_register(const char *name); + +/** + * Set the mask of a module. + * @param module The module. + * @param mask The new mask for the module. + */ +void firm_dbg_set_mask(firm_dbg_module_t *module, unsigned mask); + +/** + * Get the mask of a module. + * @param module The module handle. + * @return The mask currently used by the module. + */ +unsigned firm_dbg_get_mask(const firm_dbg_module_t *module); + +/** + * Set the output file of a module. + * @param module The module handle. + * @param file The new file to use by this handle. + */ +void firm_dbg_set_file(firm_dbg_module_t *module, FILE *file); + + +/* If we have C99 use the __func__ variable for calling functions name. */ +#if defined(__STD_VERSION__) && __STD_VERSION >= 199901L +#define _DBG(args) _firm_dbg_print_msg(__FILE__, __LINE__, __func__, _firm_dbg_make_msg args) +#else + +/* Else, check for gcc and use the proprietary __FUNCTION__ macro. */ +#ifdef __GNUC__ +#define _DBG(args) _firm_dbg_print_msg(__FILE__, __LINE__, __FUNCTION__, _firm_dbg_make_msg args) +#else + +/* Else go without the name of the calling function. */ +#define _DBG(args) _firm_dbg_print_msg(__FILE__, __LINE__, "", _firm_dbg_make_msg args) +#endif +#endif + +/** + * Debug messages issued with this macro are always printed, even in + * retail versions. + * @see DBG() + */ +#define DBG_RETAIL(args) _DBG(args) + +#ifdef DEBUG + +/** + * Issue a debug message. + * @param args The arguments. + * + * The arguments is a list surrounded by parentheses. The items + * of the list are: + * - The module handle as returned by firm_dbg_register(). + * - The debug mask that you want associate with this message. + * - A format string for the message to pass to ir_printf(). + * - Further optional arguments are passed to ir_printf(). + * + * The mask is anded against the module's mask. If both have some bits + * in common, the message is issued. If the given mask is 0, the message + * is always dumped regardless of the module's mask. You can also use + * the mask in a level based manner, see firm_dbg_level_t. + * + * Here is an example: + * @code + * DBG((my_mod, MASK_ERR, "ir node %n is not green", node)) + * ... + * DBG((my_mod, LEVEL_DEFAULT, "entity %e has type %t", ent, type)) + * @endcode + */ +#define DBG(args) _DBG(args) + +#else +#define DBG(args) +#endif + + +#endif -- 2.20.1