initial checkin of firm ycomp debugger
authorChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Fri, 17 Nov 2006 12:48:37 +0000 (12:48 +0000)
committerChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Fri, 17 Nov 2006 12:48:37 +0000 (12:48 +0000)
[r8386]

ir/debug/firm_ycomp.c [new file with mode: 0644]
ir/debug/firm_ycomp.h [new file with mode: 0644]

diff --git a/ir/debug/firm_ycomp.c b/ir/debug/firm_ycomp.c
new file mode 100644 (file)
index 0000000..7b2aaf3
--- /dev/null
@@ -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 (file)
index 0000000..060cd77
--- /dev/null
@@ -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_ */