/*
- * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
- *
* This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
+ * Copyright (C) 2012 University of Karlsruhe.
*/
/**
* @brief Helper function for integrated debug support
* @author Michael Beck
* @date 2005
- * @version $Id$
*/
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
-
-#include "firm_config.h"
#ifdef DEBUG_libfirm
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-
-#define strncasecmp strnicmp
#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
+#include "debugger.h"
+#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
-
-#ifdef HAVE_STRING_H
#include <string.h>
-#endif
-#ifdef HAVE_STRINGS_H
#include <strings.h>
-#endif
+#include <time.h>
#include <ctype.h>
#include "irdump.h"
#include "iredges_t.h"
#include "debug.h"
+#include "error.h"
+#include "util.h"
#ifdef _WIN32
/* Break into the debugger. The Win32 way. */
-void firm_debug_break(void) {
+void firm_debug_break(void)
+{
DebugBreak();
}
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
/* Break into the debugger. The ia32/x86_64 way under GCC. */
-void firm_debug_break(void) {
+void firm_debug_break(void)
+{
__asm__ __volatile__("int3");
}
#else
/* Break into the debugger. Poor Unix way. */
-void firm_debug_break(void) {
+void firm_debug_break(void)
+{
raise(SIGINT);
}
#endif /* _WIN32 */
/**
* Reasons for node number breakpoints.
*/
-typedef enum _bp_reasons_t {
- BP_ON_NEW_NODE, /**< break if node with number is created */
+typedef enum bp_reasons_t {
+ BP_ON_NEW_THING, /**< break if node, entity or type with number is created */
BP_ON_REPLACE, /**< break if node with number is replaced */
BP_ON_LOWER, /**< break if node with number is lowered */
BP_ON_REMIRG, /**< break if an IRG is removed */
BP_ON_NEW_ENT, /**< break if a new entity is created */
- BP_ON_NEW_TYPE, /**< break if a new type is created */
BP_MAX_REASON
} bp_reasons_t;
/** A breakpoint. */
-typedef struct _breakpoint {
+typedef struct breakpoint {
bp_kind kind; /**< the kind of this break point */
unsigned bpnr; /**< break point number */
int active; /**< non-zero, if this break point is active */
bp_reasons_t reason; /**< reason for the breakpoint */
- struct _breakpoint *next; /**< link to the next one */
+ struct breakpoint *next; /**< link to the next one */
} breakpoint;
/** A number breakpoint. */
} bp_ident_t;
/** Calculate the hash value for an ident breakpoint. */
-#define HASH_IDENT_BP(key) (HASH_PTR((key).id) ^ (key).bp.reason)
+#define HASH_IDENT_BP(key) (hash_ptr((key).id) ^ (key).bp.reason)
/** The set containing the breakpoints on node numbers. */
static set *bp_numbers;
do { \
debugger_hooks[h].hook._##h = fkt; \
register_hook(h, &debugger_hooks[h]); \
-} while(0)
+} while (0)
/** unhook the hook h */
#define UNHOOK(h) \
do { \
unregister_hook(h, &debugger_hooks[h]); \
debugger_hooks[h].hook._##h = NULL; \
-} while(0)
+} while (0)
/** returns non-zero if a entry hook h is used */
#define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
#define FIRM_DBG_MINOR 0
/** for automatic detection of the debug extension */
-static const char firm_debug_info_string[] =
+static const char __attribute__((used)) firm_debug_info_string[] =
API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
-/**
- * Returns non-zero, if the debug extension is active
- */
-int firm_debug_active(void) {
+int firm_debug_active(void)
+{
return is_active;
-} /* firm_debug_active */
+}
/**
* Reset the debug text buffer.
*/
-static void reset_dbg_buf(void) {
+static void reset_dbg_buf(void)
+{
firm_dbg_msg_buf[0] = '\0';
-} /* reset_dbg_buf */
-
-/**
- * Add text to the debug text buffer.
- */
-static void add_to_dbg_buf(const char *buf) {
- strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
-} /* add_to_dbg_buf */
+}
-/**
- * Return the content of the debug text buffer.
- *
- * To be called from the debugger.
- */
-const char *firm_debug_text(void) {
+const char *firm_debug_text(void)
+{
firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
return firm_dbg_msg_buf;
-} /* firm_debug_text */
+}
/**
* debug output
*/
static void dbg_printf(const char *fmt, ...)
{
- char buf[1024];
-
- va_list args;
- va_start(args, fmt);
-
if (fmt[0] != '+')
reset_dbg_buf();
else
++fmt;
- ir_vsnprintf(buf, sizeof(buf), fmt, args);
+ va_list args;
+ va_start(args, fmt);
+ if (redir_output) {
+ size_t const cur = strlen(firm_dbg_msg_buf);
+ ir_vsnprintf(firm_dbg_msg_buf + cur, sizeof(firm_dbg_msg_buf) - cur, fmt, args);
+ } else {
+ ir_vprintf(fmt, args);
+ }
va_end(args);
-
- if (redir_output)
- add_to_dbg_buf(buf);
- else
- puts(buf);
-} /* dbg_printf */
+}
/**
* A new node is created.
(void) irg;
key.nr = get_irn_node_nr(node);
- key.bp.reason = BP_ON_NEW_NODE;
+ key.bp.reason = BP_ON_NEW_THING;
- elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem && elem->bp.active) {
dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
firm_debug_break();
}
-} /* dbg_new_node */
+}
/**
* A node is replaced.
key.nr = get_irn_node_nr(old);
key.bp.reason = BP_ON_REPLACE;
- elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem && elem->bp.active) {
dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
firm_debug_break();
}
-} /* dbg_replace */
+}
/**
* A new node is lowered.
key.nr = get_irn_node_nr(node);
key.bp.reason = BP_ON_LOWER;
- elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem && elem->bp.active) {
dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
firm_debug_break();
}
-} /* dbg_lower */
+}
/**
* A graph will be deleted.
key.nr = get_irg_graph_nr(irg);
key.bp.reason = BP_ON_REMIRG;
- elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem && elem->bp.active) {
ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
firm_debug_break();
key.id = get_entity_ident(ent);
key.bp.reason = BP_ON_REMIRG;
- elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
+ elem = set_find(bp_ident_t, bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
if (elem && elem->bp.active) {
dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
firm_debug_break();
}
}
-} /* dbg_free_graph */
+}
/**
* An entity was created.
key.id = get_entity_ident(ent);
key.bp.reason = BP_ON_NEW_ENT;
- elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
+ elem = set_find(bp_ident_t, bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
if (elem && elem->bp.active) {
ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
firm_debug_break();
bp_nr_t key, *elem;
key.nr = get_entity_nr(ent);
- key.bp.reason = BP_ON_NEW_ENT;
+ key.bp.reason = BP_ON_NEW_THING;
- elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem && elem->bp.active) {
dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
firm_debug_break();
}
}
-} /* dbg_new_entity */
+}
/**
* A type was created.
bp_nr_t key, *elem;
key.nr = get_type_nr(tp);
- key.bp.reason = BP_ON_NEW_TYPE;
+ key.bp.reason = BP_ON_NEW_THING;
- elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem && elem->bp.active) {
ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
firm_debug_break();
}
}
- {
- bp_ident_t key, *elem;
-
- key.id = get_type_ident(tp);
- key.bp.reason = BP_ON_NEW_TYPE;
-
- elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
- if (elem && elem->bp.active) {
- dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
- firm_debug_break();
- }
- }
-} /* dbg_new_type */
+}
/**
* Return the reason string.
static const char *reason_str(bp_reasons_t reason)
{
switch (reason) {
- case BP_ON_NEW_NODE: return "node creation";
- case BP_ON_REPLACE: return "node replace";
- case BP_ON_LOWER: return "node lowering";
- case BP_ON_REMIRG: return "removing IRG";
- case BP_ON_NEW_ENT: return "entity creation";
- case BP_ON_NEW_TYPE: return "type creation";
- default: assert(0);
+ case BP_ON_NEW_THING: return "node, entity or type creation";
+ case BP_ON_REPLACE: return "node replace";
+ case BP_ON_LOWER: return "node lowering";
+ case BP_ON_REMIRG: return "removing IRG";
+ case BP_ON_NEW_ENT: return "entity creation";
+ case BP_MAX_REASON: break;
}
- return "unknown";
-} /* reason_str */
+ panic("unsupported reason");
+}
/**
* Compare two number breakpoints.
*/
static int cmp_nr_bp(const void *elt, const void *key, size_t size)
{
- const bp_nr_t *e1 = elt;
- const bp_nr_t *e2 = key;
+ const bp_nr_t *e1 = (const bp_nr_t*)elt;
+ const bp_nr_t *e2 = (const bp_nr_t*)key;
(void) size;
return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
-} /* cmp_nr_bp */
+}
/**
* Compare two ident breakpoints.
*/
static int cmp_ident_bp(const void *elt, const void *key, size_t size)
{
- const bp_ident_t *e1 = elt;
- const bp_ident_t *e2 = key;
+ const bp_ident_t *e1 = (const bp_ident_t*)elt;
+ const bp_ident_t *e2 = (const bp_ident_t*)key;
(void) size;
return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
-} /* cmp_ident_bp */
+}
/**
* Update the hooks.
*/
static void update_hooks(breakpoint *bp)
{
-#define CASE_ON(a, b) case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
-#define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
+#define CASE_ON(a, hook, handler) case a: if (! IS_HOOKED(hook)) HOOK(hook, handler); break
+#define CASE_OFF(a, hook) case a: if (IS_HOOKED(hook)) UNHOOK(hook); break
if (bp->active)
++num_active_bp[bp->reason];
if (num_active_bp[bp->reason] > 0) {
/* register the hooks on demand */
switch (bp->reason) {
- CASE_ON(BP_ON_NEW_NODE, new_node);
- CASE_ON(BP_ON_REPLACE, replace);
- CASE_ON(BP_ON_LOWER, lower);
- CASE_ON(BP_ON_REMIRG, free_graph);
- CASE_ON(BP_ON_NEW_ENT, new_entity);
- CASE_ON(BP_ON_NEW_TYPE, new_type);
+ CASE_ON(BP_ON_REPLACE, hook_replace, dbg_replace);
+ CASE_ON(BP_ON_LOWER, hook_lower, dbg_lower);
+ CASE_ON(BP_ON_REMIRG, hook_free_graph, dbg_free_graph);
+ CASE_ON(BP_ON_NEW_ENT, hook_new_entity, dbg_new_entity);
+ case BP_ON_NEW_THING:
+ if (!IS_HOOKED(hook_new_node))
+ HOOK(hook_new_node, dbg_new_node);
+ if (!IS_HOOKED(hook_new_type))
+ HOOK(hook_new_type, dbg_new_type);
+ if (!IS_HOOKED(hook_new_entity))
+ HOOK(hook_new_entity, dbg_new_entity);
+ break;
default:
- ;
+ break;
}
}
else {
/* unregister the hook on demand */
switch (bp->reason) {
- CASE_OFF(BP_ON_NEW_NODE, new_node);
- CASE_OFF(BP_ON_REPLACE, replace);
- CASE_OFF(BP_ON_LOWER, lower);
- CASE_OFF(BP_ON_REMIRG, free_graph);
- CASE_OFF(BP_ON_NEW_ENT, new_entity);
- CASE_OFF(BP_ON_NEW_TYPE, new_type);
+ CASE_OFF(BP_ON_REPLACE, hook_replace);
+ CASE_OFF(BP_ON_LOWER, hook_lower);
+ CASE_OFF(BP_ON_REMIRG, hook_free_graph);
+ CASE_OFF(BP_ON_NEW_ENT, hook_new_entity);
+ case BP_ON_NEW_THING:
+ if (IS_HOOKED(hook_new_node))
+ UNHOOK(hook_new_node);
+ if (IS_HOOKED(hook_new_type))
+ UNHOOK(hook_new_type);
+ if (IS_HOOKED(hook_new_entity))
+ UNHOOK(hook_new_entity);
+ break;
default:
- ;
+ break;
}
}
#undef CASE_ON
#undef CASE_OFF
-} /* update_hooks */
+}
/**
* Break if nr is reached.
key.bp.reason = reason;
key.nr = nr;
- elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_insert(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem->bp.bpnr == 0) {
/* new break point */
update_hooks(&elem->bp);
}
-} /* break_on_nr */
+}
/**
* Break if ident name is reached.
*/
-static void break_on_ident(const char *name, bp_reasons_t reason) {
+static void break_on_ident(const char *name, bp_reasons_t reason)
+{
bp_ident_t key, *elem;
key.bp.kind = BP_IDENT;
key.bp.reason = reason;
key.id = new_id_from_str(name);
- elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
+ elem = set_insert(bp_ident_t, bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
if (elem->bp.bpnr == 0) {
/* new break point */
update_hooks(&elem->bp);
}
-} /* break_on_ident */
+}
/**
* Sets/resets the active flag of breakpoint bp.
}
}
dbg_printf("Error: Firm BP %u not exists.\n", bp);
-} /* bp_activate */
+}
/**
* Show a list of supported commands
*/
-static void show_commands(void) {
- dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
+static void show_commands(void)
+{
+ dbg_printf("Internal Firm debugger extension commands:\n"
"init break after initialization\n"
"create nr break if node nr was created\n"
"replace nr break if node nr is replaced by another node\n"
"setoutfile name file redirects debug output of module name to file\n"
"irgname name prints address and graph number of a method given by its name\n"
"irgldname ldname prints address and graph number of a method given by its ldname\n"
+ "initialnodenr n|rand set initial node number to n or random number\n"
"help list all commands\n"
);
-} /* show_commands */
+}
/**
* Shows all Firm breakpoints.
*/
-static void show_bp(void) {
+static void show_bp(void)
+{
breakpoint *p;
bp_nr_t *node_p;
bp_ident_t *ident_p;
dbg_printf(p->active ? "+enabled" : "+disabled");
}
dbg_printf(have_one ? "+\n" : "+ NONE\n");
-} /* show_bp */
+}
/**
* firm_dbg_register() expects that the name is stored persistent.
* So we need this little helper function
*/
-static firm_dbg_module_t *dbg_register(const char *name) {
+static firm_dbg_module_t *dbg_register(const char *name)
+{
ident *id = new_id_from_str(name);
return firm_dbg_register(get_id_str(id));
-} /* dbg_register */
+}
/**
* Sets the debug mask of module name to lvl
dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
}
-} /* set_dbg_level */
+}
/**
* Redirects the debug output of module name to fname
firm_dbg_set_file(module, f);
dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
-} /* set_dbg_outfile */
+}
/**
* Show info about a firm thing.
*/
-static void show_firm_object(void *firm_thing) {
+static void show_firm_object(void *firm_thing)
+{
FILE *f = stdout;
if (firm_thing == NULL) {
fprintf(f, "BAD: (%p)\n", firm_thing);
break;
case k_entity:
- dump_entity_to_file(f, firm_thing, dump_verbosity_max);
+ dump_entity_to_file(f, (ir_entity*)firm_thing);
break;
case k_type:
- dump_type_to_file(f, firm_thing, dump_verbosity_max);
+ dump_type_to_file(f, (ir_type*)firm_thing);
break;
case k_ir_graph:
case k_ir_node:
case k_ir_op:
case k_tarval:
case k_ir_loop:
- case k_ir_compound_graph_path:
- case k_ir_extblk:
case k_ir_prog:
fprintf(f, "NIY\n");
break;
default:
fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
}
-} /* show_firm_object */
+}
/**
* Find a firm type by its number.
*/
-static ir_type *find_type_nr(long nr) {
+static ir_type *find_type_nr(long nr)
+{
int i, n = get_irp_n_types();
ir_type *tp;
if (get_type_nr(tp) == nr)
return tp;
return NULL;
-} /* find_type_nr */
+}
/**
* Find a firm type by its name.
*/
-static ir_type *find_type_name(const char *name) {
+static ir_type *find_type_name(const char *name)
+{
int i, n = get_irp_n_types();
ir_type *tp;
for (i = 0; i < n; ++i) {
tp = get_irp_type(i);
- if (strcmp(get_type_name(tp), name) == 0)
+ if (!is_compound_type(tp))
+ continue;
+
+ if (strcmp(get_compound_name(tp), name) == 0)
return tp;
}
tp = get_glob_type();
- if (strcmp(get_type_name(tp), name) == 0)
+ if (strcmp(get_compound_name(tp), name) == 0)
return tp;
return NULL;
-} /* find_type_name */
+}
/** The environment for the entity search functions. */
typedef struct find_env {
/**
* Type-walker: Find an entity with given number.
*/
-static void check_ent_nr(type_or_ent *tore, void *ctx) {
- ir_entity *ent = (ir_entity *)tore;
- find_env_t *env = ctx;
+static void check_ent_nr(type_or_ent tore, void *ctx)
+{
+ find_env_t *env = (find_env_t*)ctx;
- if (is_entity(ent))
- if (get_entity_nr(ent) == env->u.nr) {
- env->res = ent;
+ if (is_entity(tore.ent)) {
+ if (get_entity_nr(tore.ent) == env->u.nr) {
+ env->res = tore.ent;
}
-} /* check_ent_nr */
+ }
+}
/**
* Type-walker: Find an entity with given name.
*/
-static void check_ent_name(type_or_ent *tore, void *ctx) {
- ir_entity *ent = (ir_entity *)tore;
- find_env_t *env = ctx;
+static void check_ent_name(type_or_ent tore, void *ctx)
+{
+ find_env_t *env = (find_env_t*)ctx;
- if (is_entity(ent))
- if (strcmp(get_entity_name(ent), env->u.name) == 0) {
- env->res = ent;
+ if (is_entity(tore.ent))
+ if (strcmp(get_entity_name(tore.ent), env->u.name) == 0) {
+ env->res = tore.ent;
}
-} /* check_ent_name */
+}
/**
* Find a firm entity by its number.
*/
-static ir_entity *find_entity_nr(long nr) {
+static ir_entity *find_entity_nr(long nr)
+{
find_env_t env;
env.u.nr = nr;
env.res = NULL;
type_walk(check_ent_nr, NULL, &env);
return env.res;
-} /* find_entity_nr */
+}
/**
* Find a firm entity by its name.
*/
-static ir_entity *find_entity_name(const char *name) {
+static ir_entity *find_entity_name(const char *name)
+{
find_env_t env;
env.u.name = name;
env.res = NULL;
type_walk(check_ent_name, NULL, &env);
return env.res;
-} /* find_entity_name */
+}
/**
* Search methods for a name.
*/
-static void show_by_name(type_or_ent *tore, void *env) {
+static void show_by_name(type_or_ent tore, void *env)
+{
ident *id = (ident *)env;
- if (is_entity(tore)) {
- ir_entity *ent = (ir_entity *)tore;
+ if (is_entity(tore.ent)) {
+ ir_entity *ent = tore.ent;
if (is_method_entity(ent)) {
if (get_entity_ident(ent) == id) {
ir_graph *irg = get_entity_irg(ent);
if (owner != get_glob_type()) {
- printf("%s::%s", get_type_name(owner), get_id_str(id));
+ printf("%s::%s", get_compound_name(owner), get_id_str(id));
} else {
printf("%s", get_id_str(id));
}
}
}
}
-} /* show_by_name */
+}
/**
* Search methods for a ldname.
*/
-static void show_by_ldname(type_or_ent *tore, void *env) {
+static void show_by_ldname(type_or_ent tore, void *env)
+{
ident *id = (ident *)env;
- if (is_entity(tore)) {
- ir_entity *ent = (ir_entity *)tore;
+ if (is_entity(tore.ent)) {
+ ir_entity *ent = tore.ent;
if (is_method_entity(ent)) {
if (get_entity_ld_ident(ent) == id) {
ir_graph *irg = get_entity_irg(ent);
if (owner != get_glob_type()) {
- printf("%s::%s", get_type_name(owner), get_id_str(id));
+ printf("%s::%s", get_compound_name(owner), get_id_str(id));
} else {
printf("%s", get_id_str(id));
}
}
}
}
-} /* show_by_ldname */
+}
/**
* prints the address and graph number of all irgs with given name
*/
-static void irg_name(const char *name) {
+static void irg_name(const char *name)
+{
ident *id = new_id_from_str(name);
type_walk(show_by_name, NULL, (void *)id);
-} /* irg_name */
+}
/**
* prints the address and graph number of all irgs with given ld_name
*/
-static void irg_ld_name(const char *name) {
+static void irg_ld_name(const char *name)
+{
ident *id = new_id_from_str(name);
type_walk(show_by_ldname, NULL, (void *)id);
-} /* irg_ld_name */
+}
enum tokens {
- tok_create = 256,
- tok_replace,
+ first_token = 256,
+ tok_bp = first_token,
+ tok_create,
+ tok_disable,
+ tok_dumpfilter,
+ tok_enable,
+ tok_help,
+ tok_init,
+ tok_irgldname,
+ tok_irgname,
tok_lower,
- tok_remirg,
tok_newent,
- tok_newtype,
- tok_showtype,
- tok_showent,
- tok_init,
- tok_bp,
- tok_enable,
- tok_disable,
- tok_setmask,
+ tok_remirg,
+ tok_replace,
tok_setlvl,
+ tok_setmask,
tok_setoutfile,
- tok_irgname,
- tok_irgldname,
- tok_help,
+ tok_showent,
+ tok_showtype,
+ tok_initialnodenr,
tok_identifier,
tok_number,
tok_eof,
};
static const char *reserved[] = {
+ "bp",
"create",
- "replace",
+ "disable",
+ "dumpfilter",
+ "enable",
+ "help",
+ "init",
+ "irgldname",
+ "irgname",
"lower",
- "remirg",
"newent",
- "newtype",
- "showtype",
- "showent",
- "init",
- "bp",
- "enable",
- "disable",
- "setmask",
+ "remirg",
+ "replace",
"setlvl",
+ "setmask",
"setoutfile",
- "irgname",
- "irgldname",
- "help"
+ "showent",
+ "showtype",
+ "initialnodenr",
};
/**
unsigned cur_token; /**< current token. */
unsigned number; /**< current token attribute. */
const char *s; /**< current token attribute. */
- unsigned len; /**< current token attribute. */
+ size_t len; /**< current token attribute. */
const char *curr_pos;
const char *end_pos;
/**
* Initialize the lexer.
*/
-static void init_lexer(const char *input) {
+static void init_lexer(const char *input)
+{
lexer.has_token = 0;
lexer.curr_pos = input;
lexer.end_pos = input + strlen(input);
-} /* init_lexer */
+}
/**
* Get the next char from the input.
*/
-static char next_char(void) {
+static char next_char(void)
+{
if (lexer.curr_pos >= lexer.end_pos)
return '\0';
return *lexer.curr_pos++;
-} /* next_char */
+}
-#define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
+#define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
#undef MIN
#define MIN(a, b) (a) < (b) ? (a) : (b)
/**
* The lexer.
*/
-static unsigned get_token(void) {
+static unsigned get_token(void)
+{
char c;
- int i;
+ size_t i;
/* skip white space */
do {
c = next_char();
- } while (c != '\0' && isspace(c));
+ } while (c != '\0' && isspace((unsigned char)c));
lexer.tok_start = lexer.curr_pos - 1;
- if (c == '.' || isalpha(c)) {
+ if (c == '.' || isalpha((unsigned char)c)) {
/* command begins here */
- int len = 0;
+ int len = 0;
+ const char* tok_start;
- if (c == '.') {
- /* skip the dot */
- ++lexer.tok_start;
- c = next_char();
- }
do {
c = next_char();
++len;
- } while (isalpha(c));
+ } while (isgraph((unsigned char)c));
unput();
- for (i = sizeof(reserved)/sizeof(reserved[0]) - 1; i >= 0; --i) {
- if (strncasecmp(lexer.tok_start, reserved[i], len) == 0 && reserved[i][len] == '\0')
- break;
+ tok_start = lexer.tok_start;
+ if (*tok_start == '.') {
+ ++tok_start;
+ --len;
+ }
+ for (i = ARRAY_SIZE(reserved); i-- != 0;) {
+ if (strncasecmp(tok_start, reserved[i], len) == 0 && reserved[i][len] == '\0')
+ return first_token + i;
}
- if (i >= 0)
- return 256 + i;
- return tok_error;
- } else if (isalpha(c)) {
- /* identifier */
- lexer.s = lexer.curr_pos - 1;
- do {
- c = next_char();
- } while (isgraph(c));
- unput();
+ /* identifier */
+ lexer.s = lexer.tok_start;
lexer.len = lexer.curr_pos - lexer.s;
return tok_identifier;
- } else if (isdigit(c) || c == '-') {
+ } else if (isdigit((unsigned char)c) || c == '-') {
unsigned number = 0;
unsigned sign = 0;
for (;;) {
c = next_char();
- if (! isxdigit(c))
+ if (! isxdigit((unsigned char)c))
break;
- if (isdigit(c))
+ if (isdigit((unsigned char)c))
number = (number << 4) | (c - '0');
else
- number = (number << 4) | (toupper(c) - 'A' + 10);
+ number = (number << 4) | (toupper((unsigned char)c) - 'A' + 10);
}
unput();
lexer.number = number;
}
}
for (;;) {
- if (! isdigit(c))
+ if (! isdigit((unsigned char)c))
break;
number = number * 10 + (c - '0');
c = next_char();
else if (c == '\0')
return tok_eof;
return c;
-} /* get_token */
+}
-/**
- * High level function to use from debugger interface
- *
- * See show_commands() for supported commands.
- */
-void firm_debug(const char *cmd) {
+void firm_debug(const char *cmd)
+{
char name[1024], fname[1024];
- int len;
+ size_t len;
init_lexer(cmd);
token = get_token();
if (token != tok_number)
goto error;
- break_on_nr(lexer.number, BP_ON_NEW_NODE);
+ break_on_nr(lexer.number, BP_ON_NEW_THING);
break;
case tok_replace:
token = get_token();
if (token == tok_number)
- break_on_nr(lexer.number, BP_ON_NEW_ENT);
+ break_on_nr(lexer.number, BP_ON_NEW_THING);
else if (token == tok_identifier) {
len = MIN(lexer.len, 1023);
strncpy(name, lexer.s, len);
goto error;
break;
- case tok_newtype:
- token = get_token();
-
- if (token == tok_number)
- break_on_nr(lexer.number, BP_ON_NEW_TYPE);
- else if (token == tok_identifier) {
- len = MIN(lexer.len, 1023);
- strncpy(name, lexer.s, len);
- name[len] = '\0';
- break_on_ident(name, BP_ON_NEW_TYPE);
- } else
- goto error;
- break;
-
case tok_showtype:
token = get_token();
strncpy(fname, lexer.s, len);
fname[len] = '\0';
set_dbg_outfile(name, fname);
+ break;
case tok_irgname:
token = get_token();
strncpy(name, lexer.s, len);
name[len] = '\0';
irg_name(name);
+ break;
+
+ case tok_initialnodenr:
+ token = get_token();
+ if (token == tok_number) {
+ dbg_printf("Setting initial node number to %u\n", lexer.number);
+ irp->max_node_nr = lexer.number;
+ } else if (token == tok_identifier && !strcmp(lexer.s, "rand")) {
+ dbg_printf("Randomizing initial node number\n");
+ srand(time(0));
+ irp->max_node_nr += rand() % 6666;
+ } else
+ goto error;
+ break;
case tok_irgldname:
token = get_token();
irg_ld_name(name);
break;
+ case tok_dumpfilter:
+ token = get_token();
+ if (token != tok_identifier)
+ goto error;
+ len = MIN(lexer.len, 1023);
+ strncpy(name, lexer.s, len);
+ name[len] = '\0';
+ ir_set_dump_filter(name);
+ break;
+
case tok_help:
show_commands();
break;
}
leave:
;
-} /* firm_debug */
+}
-/* creates the debugger tables */
void firm_init_debugger(void)
{
char *env;
if (break_on_init)
firm_debug_break();
-} /* firm_init_debugger */
+}
+
+void firm_finish_debugger(void)
+{
+ del_set(bp_numbers);
+ del_set(bp_idents);
+}
/**
* A gdb helper function to print firm objects.
*/
-const char *gdb_node_helper(void *firm_object) {
+const char *gdb_node_helper(void *firm_object)
+{
static char buf[1024];
ir_snprintf(buf, sizeof(buf), "%+F", firm_object);
return buf;
}
-/**
- * A gdb helper function to print tarvals.
- */
-const char *gdb_tarval_helper(void *tv_object) {
+const char *gdb_tarval_helper(void *tv_object)
+{
static char buf[1024];
ir_snprintf(buf, sizeof(buf), "%+T", tv_object);
return buf;
}
-const char *gdb_out_edge_helper(const ir_node *node) {
+const char *gdb_out_edge_helper(const ir_node *node)
+{
static char buf[4*1024];
char *b = buf;
size_t l;
size_t len = sizeof(buf);
- const ir_edge_t *edge;
foreach_out_edge(node, edge) {
ir_node *n = get_edge_src_irn(edge);