3 * File name: ir/debug/firm_ycomp.c
4 * Purpose: Connect firm to ycomp
5 * Author: Christian Wuerdig
9 * Copyright: (c) 2001-2006 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
14 #endif /* HAVE_CONFIG_H */
27 #define SEND_BUF_SIZE 256
28 #define HASH_EDGE(edge) \
29 ((get_irn_node_nr((edge)->src) << 17) | \
30 ((get_irn_node_nr((edge)->tgt) & 0xEFFF) << 2) | \
33 typedef struct _exchange_node_outs_assoc_t {
36 } exchange_node_outs_assoc_t;
38 typedef struct _ycomp_edge_t {
44 enum _firm_ycomp_node_realizer_values {
50 NODE_REALIZER_STARTEND,
54 typedef struct _firm_ycomp_node_realizer_t {
56 const char *linecolor;
57 const char *fillcolor;
59 } firm_ycomp_node_realizer_t;
61 static firm_ycomp_node_realizer_t node_realizer[NODE_REALIZER_LAST] = {
62 { NODE_REALIZER_NORMAL, "black", "white", "box" },
63 { NODE_REALIZER_PROJ, "black", "yellow", "box" },
64 { NODE_REALIZER_BLOCK, "black", "yellow", "box" },
65 { NODE_REALIZER_MEM, "black", "blue", "box" },
66 { NODE_REALIZER_PHI, "black", "green", "box" },
67 { NODE_REALIZER_STARTEND, "black", "blue", "box" },
70 enum _firm_ycomp_edge_realizer_values {
78 typedef struct _firm_ycomp_edge_realizer_t {
80 const char *linecolor;
83 } firm_ycomp_edge_realizer_t;
85 static firm_ycomp_edge_realizer_t edge_realizer[EDGE_REALIZER_LAST] = {
86 { EDGE_REALIZER_DATA, "black", 1, "continuous" },
87 { EDGE_REALIZER_MEM, "blue", 1, "continuous" },
88 { EDGE_REALIZER_DEP, "green", 1, "continuous" },
89 { EDGE_REALIZER_CFG, "red", 1, "continuous" },
92 typedef struct _firm_ycomp_dbg_t {
95 pset *exchanged_nodes;
98 hook_entry_t hook_new_irg;
99 hook_entry_t hook_new_irn;
100 hook_entry_t hook_set_edge;
101 hook_entry_t hook_exchange;
104 static firm_ycomp_dbg_t yy_dbg;
106 static int cmp_edges(const void *a, const void *b) {
107 ycomp_edge_t *e1 = (ycomp_edge_t *)a;
108 ycomp_edge_t *e2 = (ycomp_edge_t *)b;
110 return (e1->src != e2->src) || (e1->tgt != e2->tgt) || (e1->pos != e2->pos);
113 static int cmp_nodes(const void *a, const void *b) {
114 exchange_node_outs_assoc_t *n1 = (exchange_node_outs_assoc_t *)a;
115 exchange_node_outs_assoc_t *n2 = (exchange_node_outs_assoc_t *)b;
117 return n1->irn != n2->irn;
120 static INLINE void send_cmd(const char *buf) {
123 fprintf(stderr, "'%s'\n", buf);
125 res = firmnet_send(yy_dbg.fd, (const void *)buf, len);
129 static void wait_for_sync(void) {
132 firmnet_recv(yy_dbg.fd, buf, 6, 5);
135 static void firm_ycomp_debug_init_realizer(void) {
137 char buf[SEND_BUF_SIZE];
139 for (i = 0; i < NODE_REALIZER_LAST; ++i) {
140 snprintf(buf, sizeof(buf), "addNodeRealizer \"%u\" \"%s\" \"%s\" \"%s\"\n",
142 node_realizer[i].linecolor,
143 node_realizer[i].fillcolor,
144 node_realizer[i].shape);
148 for (i = 0; i < EDGE_REALIZER_LAST; ++i) {
149 snprintf(buf, sizeof(buf), "addEdgeRealizer \"%u\" \"%s\" \"%u\" \"%s\"\n",
151 edge_realizer[i].linecolor,
152 edge_realizer[i].thickness,
153 edge_realizer[i].style);
158 static INLINE unsigned get_node_realizer(ir_node *node) {
160 opcode opc = get_irn_opcode(node);
164 realizer = NODE_REALIZER_BLOCK;
167 realizer = NODE_REALIZER_PHI;
170 if (get_irn_mode(node) == mode_M)
171 realizer = NODE_REALIZER_MEM;
173 realizer = NODE_REALIZER_PROJ;
177 realizer = NODE_REALIZER_STARTEND;
180 realizer = NODE_REALIZER_NORMAL;
186 static INLINE unsigned get_edge_realizer(ir_node *src, ir_node *tgt) {
190 assert(! is_Block(tgt));
192 mode = get_irn_mode(tgt);
195 realizer = EDGE_REALIZER_MEM;
196 else if (mode == mode_X)
197 realizer = EDGE_REALIZER_CFG;
199 realizer = EDGE_REALIZER_DATA;
204 static void firm_ycomp_debug_new_node(void *context, ir_graph *graph, ir_node *node) {
205 firm_ycomp_dbg_t *dbg = context;
206 char buf[SEND_BUF_SIZE];
208 unsigned src_idx = get_irn_node_nr(node);
210 if (get_const_code_irg() == graph)
216 ir_snprintf(buf, sizeof(buf), "addNode \"%u\" \"%u\" \"%+F\"\n",
217 src_idx, /* node id */
218 get_node_realizer(node), /* realizerId */
223 for (i = get_irn_arity(node) - 1; i >= 0; --i) {
224 ir_node *pred = get_irn_n(node, i);
225 unsigned tgt_idx = get_irn_node_nr(pred);
226 ycomp_edge_t key, *entry;
228 ir_snprintf(buf, sizeof(buf), "addEdge \"n%un%up%d\" \"%u\" \"%u\" \"%u\" \"%d\"\n",
229 src_idx, tgt_idx, i, /* edge id */
230 src_idx, /* source node id */
231 tgt_idx, /* target node id */
232 get_edge_realizer(node, pred), /* realizer id */
240 entry = pset_find(dbg->edges, &key, HASH_EDGE(&key));
242 entry = obstack_alloc(&dbg->obst, sizeof(*entry));
246 pset_insert(dbg->edges, entry, HASH_EDGE(entry));
255 static void firm_ycomp_debug_new_irg(void *context, ir_graph *irg, entity *ent) {
256 if (yy_dbg.has_data) {
257 send_cmd("deleteGraph\n");
265 static void firm_ycomp_debug_set_edge(void *context, ir_node *src, int pos, ir_node *tgt, ir_node *old_tgt) {
266 firm_ycomp_dbg_t *dbg = context;
267 exchange_node_outs_assoc_t *entry, key;
268 ycomp_edge_t *old_edge, *new_edge, edge_key;
269 char buf[SEND_BUF_SIZE];
270 unsigned src_idx, tgt_idx, old_tgt_idx;
272 /* ignore block edges for now */
276 /* check if the new edge exists */
280 new_edge = pset_find(dbg->edges, &edge_key, HASH_EDGE(&edge_key));
282 /* if the new edge already exists and the old target is the new target -> ignore */
283 if (new_edge && tgt == old_tgt)
286 /* check if the old edge exists */
288 edge_key.tgt = old_tgt;
290 old_edge = pset_find(dbg->edges, &edge_key, HASH_EDGE(&edge_key));
292 /* check if old target is marked for exchange */
294 entry = pset_find(dbg->exchanged_nodes, &key, HASH_PTR(old_tgt));
297 /* we are called from exchange() */
298 entry->n_out_edges--;
301 src_idx = get_irn_node_nr(src);
302 tgt_idx = get_irn_node_nr(tgt);
303 old_tgt_idx = get_irn_node_nr(old_tgt);
306 /* delete the old edge if it exists */
307 snprintf(buf, sizeof(buf), "deleteEdge \"n%un%up%d\"\n", src_idx, old_tgt_idx, pos);
309 pset_remove(dbg->edges, old_edge, HASH_EDGE(old_edge));
313 /* add the new edge if it doesn't exist */
314 snprintf(buf, sizeof(buf), "addEdge \"n%un%up%d\" \"%u\" \"%u\" \"%u\" \"%d\"\n",
315 src_idx, tgt_idx, pos, /* edge id */
316 src_idx, /* source node id */
317 tgt_idx, /* target node id */
318 get_edge_realizer(src, tgt), /* realizer id */
322 /* insert the new edge */
323 new_edge = obstack_alloc(&dbg->obst, sizeof(*new_edge));
327 pset_insert(dbg->edges, new_edge, HASH_EDGE(new_edge));
330 /* show and sync if all edges are rerouted or if it's a normal set_irn_n */
331 if (! entry || entry->n_out_edges == 0) {
338 static void firm_ycomp_debug_exchange(void *context, ir_node *old_node, ir_node *new_node) {
339 firm_ycomp_dbg_t *dbg = context;
340 exchange_node_outs_assoc_t key, *entry;
343 entry = pset_find(dbg->exchanged_nodes, &key, HASH_PTR(old_node));
345 entry->n_out_edges = get_irn_n_edges(old_node);
348 entry = obstack_alloc(&dbg->obst, sizeof(*entry));
349 entry->irn = old_node;
350 entry->n_out_edges = get_irn_n_edges(old_node);
351 pset_insert(dbg->exchanged_nodes, entry, HASH_PTR(old_node));
355 void firm_init_ycomp_debugger(const char *host, uint16_t port) {
356 static int init_once = 0;
361 memset(&yy_dbg, 0, sizeof(yy_dbg));
367 yy_dbg.fd = firmnet_connect_tcp(host, port);
369 if (yy_dbg.fd > -1) {
370 /* We could establish a connection to ycomp -> register hooks */
371 firm_ycomp_debug_init_realizer();
372 yy_dbg.exchanged_nodes = new_pset(cmp_nodes, 20);
373 yy_dbg.edges = new_pset(cmp_edges, 20);
374 obstack_init(&yy_dbg.obst);
377 yy_dbg.hook_new_irn.context = &yy_dbg;
378 yy_dbg.hook_new_irn.hook._hook_new_node = firm_ycomp_debug_new_node;
379 register_hook(hook_new_node, &yy_dbg.hook_new_irn);
382 yy_dbg.hook_new_irg.context = &yy_dbg;
383 yy_dbg.hook_new_irg.hook._hook_new_graph = firm_ycomp_debug_new_irg;
384 register_hook(hook_new_graph, &yy_dbg.hook_new_irg);
387 yy_dbg.hook_set_edge.context = &yy_dbg;
388 yy_dbg.hook_set_edge.hook._hook_set_irn_n = firm_ycomp_debug_set_edge;
389 register_hook(hook_set_irn_n, &yy_dbg.hook_set_edge);
391 /* replace (exchange) hook */
392 yy_dbg.hook_exchange.context = &yy_dbg;
393 yy_dbg.hook_exchange.hook._hook_replace = firm_ycomp_debug_exchange;
394 register_hook(hook_replace, &yy_dbg.hook_exchange);
400 void firm_finish_ycomp_debugger(void) {
401 if (yy_dbg.fd > -1) {
402 firmnet_close_socket(yy_dbg.fd);
403 unregister_hook(hook_new_graph, &yy_dbg.hook_new_irg);
404 unregister_hook(hook_new_node, &yy_dbg.hook_new_irn);
405 unregister_hook(hook_set_irn_n, &yy_dbg.hook_set_edge);
406 unregister_hook(hook_replace, &yy_dbg.hook_exchange);
407 del_pset(yy_dbg.exchanged_nodes);
408 del_pset(yy_dbg.edges);
409 yy_dbg.exchanged_nodes = NULL;
410 obstack_free(&yy_dbg.obst, NULL);