From: Christian Würdig Date: Fri, 17 Nov 2006 12:48:37 +0000 (+0000) Subject: initial checkin of firm ycomp debugger X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=a66da2eee3e5645367cd579ddbde6f6b708d7141;p=libfirm initial checkin of firm ycomp debugger [r8386] --- diff --git a/ir/debug/firm_ycomp.c b/ir/debug/firm_ycomp.c new file mode 100644 index 000000000..7b2aaf318 --- /dev/null +++ b/ir/debug/firm_ycomp.c @@ -0,0 +1,336 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "assert.h" +#include "irhooks.h" +#include "firmnet.h" +#include "irnode.h" +#include "irgraph.h" +#include "irprintf.h" +#include "irprog.h" +#include "iredges.h" +#include "pset.h" +#include "obst.h" + +#define SEND_BUF_SIZE 256 + +typedef struct _exchange_node_outs_assoc_t { + int n_out_edges; + ir_node *irn; +} exchange_node_outs_assoc_t; + +enum _firm_ycomp_node_realizer_values { + NODE_REALIZER_NORMAL, + NODE_REALIZER_PROJ, + NODE_REALIZER_BLOCK, + NODE_REALIZER_MEM, + NODE_REALIZER_PHI, + NODE_REALIZER_STARTEND, + NODE_REALIZER_LAST +}; + +typedef struct _firm_ycomp_node_realizer_t { + unsigned id; + const char *linecolor; + const char *fillcolor; + const char *shape; +} firm_ycomp_node_realizer_t; + +static firm_ycomp_node_realizer_t node_realizer[NODE_REALIZER_LAST] = { + { NODE_REALIZER_NORMAL, "black", "white", "box" }, + { NODE_REALIZER_PROJ, "black", "yellow", "box" }, + { NODE_REALIZER_BLOCK, "black", "yellow", "box" }, + { NODE_REALIZER_MEM, "black", "blue", "box" }, + { NODE_REALIZER_PHI, "black", "green", "box" }, + { NODE_REALIZER_STARTEND, "black", "blue", "box" }, +}; + +enum _firm_ycomp_edge_realizer_values { + EDGE_REALIZER_DATA, + EDGE_REALIZER_MEM, + EDGE_REALIZER_DEP, + EDGE_REALIZER_CFG, + EDGE_REALIZER_LAST +}; + +typedef struct _firm_ycomp_edge_realizer_t { + unsigned id; + const char *linecolor; + unsigned thickness; + const char *style; +} firm_ycomp_edge_realizer_t; + +static firm_ycomp_edge_realizer_t edge_realizer[EDGE_REALIZER_LAST] = { + { EDGE_REALIZER_DATA, "black", 1, "continuous" }, + { EDGE_REALIZER_MEM, "blue", 1, "continuous" }, + { EDGE_REALIZER_DEP, "green", 1, "continuous" }, + { EDGE_REALIZER_CFG, "red", 1, "continuous" }, +}; + +typedef struct _firm_ycomp_dbg_t { + int fd; + int has_data; + pset *exchanged_nodes; + struct obstack obst; + hook_entry_t hook_new_irg; + hook_entry_t hook_new_irn; + hook_entry_t hook_set_edge; + hook_entry_t hook_exchange; +} firm_ycomp_dbg_t; + +static firm_ycomp_dbg_t yy_dbg; + +static int cmp_nodes(const void *a, const void *b) { + exchange_node_outs_assoc_t *n1 = *(exchange_node_outs_assoc_t **)a; + exchange_node_outs_assoc_t *n2 = *(exchange_node_outs_assoc_t **)b; + + return n1->irn != n2->irn; +} + +static INLINE void send_cmd(const char *buf) { + ssize_t res, len; + + fprintf(stderr, "'%s'\n", buf); + len = strlen(buf); + res = firmnet_send(yy_dbg.fd, (const void *)buf, len); + assert(res == len); +} + +static void wait_for_sync(void) { + char buf[6]; + + firmnet_recv(yy_dbg.fd, buf, 6, 5); +} + +static void firm_ycomp_debug_init_realizer(void) { + int i; + char buf[SEND_BUF_SIZE]; + + for (i = 0; i < NODE_REALIZER_LAST; ++i) { + snprintf(buf, sizeof(buf), "addNodeRealizer \"%u\" \"%s\" \"%s\" \"%s\"\n", + node_realizer[i].id, + node_realizer[i].linecolor, + node_realizer[i].fillcolor, + node_realizer[i].shape); + send_cmd(buf); + } + + for (i = 0; i < EDGE_REALIZER_LAST; ++i) { + snprintf(buf, sizeof(buf), "addEdgeRealizer \"%u\" \"%s\" \"%u\" \"%s\"\n", + edge_realizer[i].id, + edge_realizer[i].linecolor, + edge_realizer[i].thickness, + edge_realizer[i].style); + send_cmd(buf); + } +} + +static INLINE unsigned get_node_realizer(ir_node *node) { + unsigned realizer; + opcode opc = get_irn_opcode(node); + + switch (opc) { + case iro_Block: + realizer = NODE_REALIZER_BLOCK; + break; + case iro_Phi: + realizer = NODE_REALIZER_PHI; + break; + case iro_Proj: + if (get_irn_mode(node) == mode_M) + realizer = NODE_REALIZER_MEM; + else + realizer = NODE_REALIZER_PROJ; + break; + case iro_Start: + case iro_End: + realizer = NODE_REALIZER_STARTEND; + break; + default: + realizer = NODE_REALIZER_NORMAL; + }; + + return realizer; +} + +static INLINE unsigned get_edge_realizer(ir_node *src, ir_node *tgt) { + unsigned realizer; + ir_mode *mode; + + assert(! is_Block(tgt)); + + mode = get_irn_mode(tgt); + + if (mode == mode_M) + realizer = EDGE_REALIZER_MEM; + else if (mode == mode_X) + realizer = EDGE_REALIZER_CFG; + else + realizer = EDGE_REALIZER_DATA; + + return realizer; +} + +static void firm_ycomp_debug_new_node(void *context, ir_graph *graph, ir_node *node) { + char buf[SEND_BUF_SIZE]; + int i; + unsigned src_idx = get_irn_idx(node); + + if (get_const_code_irg() == graph) + return; + + yy_dbg.has_data = 1; + + /* add node */ + ir_snprintf(buf, sizeof(buf), "addNode \"%u\" \"%u\" \"%+F\"\n", + src_idx, /* node id */ + get_node_realizer(node), /* realizerId */ + node); /* label */ + send_cmd(buf); + + /* add edges */ + for (i = get_irn_arity(node) - 1; i >= 0; --i) { + ir_node *pred = get_irn_n(node, i); + unsigned tgt_idx = get_irn_idx(pred); + + ir_snprintf(buf, sizeof(buf), "addEdge \"n%un%up%d\" \"%u\" \"%u\" \"%u\" \"%d\"\n", + src_idx, tgt_idx, i, /* edge id */ + src_idx, /* source node id */ + tgt_idx, /* target node id */ + get_edge_realizer(node, pred), /* realizer id */ + i); /* title */ + send_cmd(buf); + } + + send_cmd("show\n"); + send_cmd("sync\n"); + wait_for_sync(); +} + +static void firm_ycomp_debug_new_irg(void *context, ir_graph *irg, entity *ent) { + if (yy_dbg.has_data) { + send_cmd("deleteGraph\n"); + send_cmd("show\n"); + } + yy_dbg.has_data = 0; + send_cmd("sync\n"); + wait_for_sync(); +} + +static void firm_ycomp_debug_set_edge(void *context, ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt) { + firm_ycomp_dbg_t *dbg = context; + exchange_node_outs_assoc_t *entry, key; + char buf[SEND_BUF_SIZE]; + unsigned src_idx, tgt_idx, old_tgt_idx; + + /* ignore block edges for now */ + if (pos < 0) + return; + + key.irn = old_tgt; + entry = pset_find(dbg->exchanged_nodes, &key, HASH_PTR(old_tgt)); + + if (entry) { + /* we are called from exchange() */ + entry->n_out_edges--; + } + + src_idx = get_irn_idx(src); + tgt_idx = get_irn_idx(tgt); + old_tgt_idx = get_irn_idx(old_tgt); + + /* delete the old edge */ + snprintf(buf, sizeof(buf), "deleteEdge \"n%un%up%d\"\n", src_idx, old_tgt_idx, pos); + send_cmd(buf); + + /* add the new edge */ + snprintf(buf, sizeof(buf), "addEdge \"n%un%up%d\" \"%u\" \"%u\" \"%u\" \"%d\"\n", + src_idx, tgt_idx, pos, /* edge id */ + src_idx, /* source node id */ + tgt_idx, /* target node id */ + get_edge_realizer(src, tgt), /* realizer id */ + pos); /* title */ + send_cmd(buf); + + /* show and sync if all edges are rerouted or if it's a normal set_irn_n */ + if (! entry || entry->n_out_edges == 0) { + send_cmd("show\n"); + send_cmd("sync\n"); + wait_for_sync(); + } +} + +static void firm_ycomp_debug_exchange(void *context, ir_node *old_node, ir_node *new_node) { + firm_ycomp_dbg_t *dbg = context; + exchange_node_outs_assoc_t key, *entry; + + key.irn = old_node; + entry = pset_find(dbg->exchanged_nodes, &key, HASH_PTR(old_node)); + if (entry) { + entry->n_out_edges = get_irn_n_edges(old_node); + } + else { + entry = obstack_alloc(&dbg->obst, sizeof(*entry)); + entry->irn = old_node; + entry->n_out_edges = get_irn_n_edges(old_node); + pset_insert(dbg->exchanged_nodes, entry, HASH_PTR(old_node)); + } +} + +void firm_init_ycomp_debugger(const char *host, uint16_t port) { + static int init_once = 0; + + if (init_once) + return; + + memset(&yy_dbg, 0, sizeof(yy_dbg)); + yy_dbg.fd = -1; + + host = "localhost"; + port = 4242; + + yy_dbg.fd = firmnet_connect_tcp(host, port); + + if (yy_dbg.fd > -1) { + /* We could establish a connection to ycomp -> register hooks */ + firm_ycomp_debug_init_realizer(); + yy_dbg.exchanged_nodes = new_pset(cmp_nodes, 20); + obstack_init(&yy_dbg.obst); + + /* new node hook */ + yy_dbg.hook_new_irn.context = &yy_dbg; + yy_dbg.hook_new_irn.hook._hook_new_node = firm_ycomp_debug_new_node; + register_hook(hook_new_node, &yy_dbg.hook_new_irn); + + /* new irg hook */ + yy_dbg.hook_new_irg.context = &yy_dbg; + yy_dbg.hook_new_irg.hook._hook_new_graph = firm_ycomp_debug_new_irg; + register_hook(hook_new_graph, &yy_dbg.hook_new_irg); + + /* set irn n hook */ + yy_dbg.hook_set_edge.context = &yy_dbg; + yy_dbg.hook_set_edge.hook._hook_set_irn_n = firm_ycomp_debug_set_edge; + register_hook(hook_set_irn_n, &yy_dbg.hook_set_edge); + + /* replace (exchange) hook */ + yy_dbg.hook_exchange.context = &yy_dbg; + yy_dbg.hook_exchange.hook._hook_replace = firm_ycomp_debug_exchange; + register_hook(hook_replace, &yy_dbg.hook_exchange); + } + + init_once = 1; +} + +void firm_finish_ycomp_debugger(void) { + if (yy_dbg.fd > -1) { + firmnet_close_socket(yy_dbg.fd); + unregister_hook(hook_new_graph, &yy_dbg.hook_new_irg); + unregister_hook(hook_new_node, &yy_dbg.hook_new_irn); + unregister_hook(hook_set_irn_n, &yy_dbg.hook_set_edge); + unregister_hook(hook_replace, &yy_dbg.hook_exchange); + del_pset(yy_dbg.exchanged_nodes); + yy_dbg.exchanged_nodes = NULL; + obstack_free(&yy_dbg.obst, NULL); + } +} diff --git a/ir/debug/firm_ycomp.h b/ir/debug/firm_ycomp.h new file mode 100644 index 000000000..060cd771e --- /dev/null +++ b/ir/debug/firm_ycomp.h @@ -0,0 +1,18 @@ +#ifndef _FIRM_YCOMP_H_ +#define _FIRM_YCOMP_H_ + +#include "firmnet.h" + +/** + * Establish connection to yComp and register debugger hooks. + * @param host Hostname where yComp is running + * @param port Port on which yComp is listening + */ +void firm_init_ycomp_debugger(const char *host, uint16_t port); + +/** + * Close connection to yComp and unregister debugger hooks. + */ +void firm_finish_ycomp_debugger(void); + +#endif /* _FIRM_YCOMP_H_ */