Commit a66da2ee authored by Christian Würdig's avatar Christian Würdig
Browse files

initial checkin of firm ycomp debugger

[r8386]
parent 460d9286
#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);
}
}
#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_ */
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment