Replace memcpy() by simple assignment.
[libfirm] / ir / debug / firm_ycomp.c
index 4c1a40d..76fa41d 100644 (file)
@@ -1,13 +1,28 @@
 /*
- * Project:     libFIRM
- * File name:   ir/debug/firm_ycomp.c
- * Purpose:     Connect firm to ycomp
- * Author:      Christian Wuerdig
- * Modified by:
- * Created:     16.11.2006
- * CVS-ID:      $Id$
- * Copyright:   (c) 2001-2006 Universität Karlsruhe
- * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ * 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.
+ */
+
+/**
+ * @file
+ * @brief      Connect firm to ycomp
+ * @author     Christian Wuerdig
+ * @date       16.11.2006
+ * @version    $Id$
  */
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #include "iredges.h"
 #include "pset.h"
 #include "obst.h"
+#include "firmnet.h"
 
 #define SEND_BUF_SIZE 256
 #define HASH_EDGE(edge) \
        ((get_irn_node_nr((edge)->src) << 17)          | \
        ((get_irn_node_nr((edge)->tgt) & 0xEFFF) << 2) | \
-       ((edge)->pos & 0x2))
+       ((edge)->pos & 0x3))
 
 typedef struct _exchange_node_outs_assoc_t {
        int     n_out_edges;
        ir_node *irn;
+       ir_node *nw;
 } exchange_node_outs_assoc_t;
 
 typedef struct _ycomp_edge_t {
@@ -48,6 +65,8 @@ enum _firm_ycomp_node_realizer_values {
        NODE_REALIZER_MEM,
        NODE_REALIZER_PHI,
        NODE_REALIZER_STARTEND,
+       NODE_REALIZER_IRG,
+       NODE_REALIZER_ID,
        NODE_REALIZER_LAST
 };
 
@@ -55,16 +74,19 @@ typedef struct _firm_ycomp_node_realizer_t {
        unsigned   id;
        const char *linecolor;
        const char *fillcolor;
+       const char *textcolor;
        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" },
+       { NODE_REALIZER_NORMAL,   "black", "white",    "black", "box" },
+       { NODE_REALIZER_PROJ,     "black", "yellow",   "black", "box" },
+       { NODE_REALIZER_BLOCK,    "black", "yellow",   "white", "box" },
+       { NODE_REALIZER_MEM,      "black", "blue",     "black", "box" },
+       { NODE_REALIZER_PHI,      "black", "green",    "black", "box" },
+       { NODE_REALIZER_STARTEND, "black", "blue",     "black", "box" },
+       { NODE_REALIZER_IRG,      "black", "white",    "white", "box" },
+       { NODE_REALIZER_ID,       "black", "darkgrey", "black", "box" },
 };
 
 enum _firm_ycomp_edge_realizer_values {
@@ -78,15 +100,16 @@ enum _firm_ycomp_edge_realizer_values {
 typedef struct _firm_ycomp_edge_realizer_t {
        unsigned   id;
        const char *linecolor;
+       const char *textcolor;
        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" },
+       { EDGE_REALIZER_DATA, "black", "black", 1, "continuous" },
+       { EDGE_REALIZER_MEM,  "blue",  "black", 1, "continuous" },
+       { EDGE_REALIZER_DEP,  "green", "black", 1, "continuous" },
+       { EDGE_REALIZER_CFG,  "red",   "black", 1, "continuous" },
 };
 
 typedef struct _firm_ycomp_dbg_t {
@@ -94,11 +117,14 @@ typedef struct _firm_ycomp_dbg_t {
        int            has_data;
        pset           *exchanged_nodes;
        pset           *edges;
+       unsigned       in_dead_node_elim : 1;
        struct obstack obst;
-       hook_entry_t   hook_new_irg;
        hook_entry_t   hook_new_irn;
+       hook_entry_t   hook_new_irg;
        hook_entry_t   hook_set_edge;
        hook_entry_t   hook_exchange;
+       hook_entry_t   hook_into_id;
+       hook_entry_t   hook_dead_node;
 } firm_ycomp_dbg_t;
 
 static firm_ycomp_dbg_t yy_dbg;
@@ -117,47 +143,59 @@ static int cmp_nodes(const void *a, const void *b) {
        return n1->irn != n2->irn;
 }
 
-static INLINE void send_cmd(const char *buf) {
+static INLINE void send_cmd(firm_ycomp_dbg_t *dbg, 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);
+       res = firmnet_send(dbg->fd, (const void *)buf, len);
        assert(res == len);
 }
 
-static void wait_for_sync(void) {
+static void wait_for_sync(firm_ycomp_dbg_t *dbg) {
        char buf[6];
+       firmnet_recv(dbg->fd, buf, 6, 5);
+}
 
-       firmnet_recv(yy_dbg.fd, buf, 6, 5);
+static void show_and_sync(firm_ycomp_dbg_t *dbg) {
+       send_cmd(dbg, "show\n");
+       send_cmd(dbg, "sync\n");
+       wait_for_sync(dbg);
 }
 
-static void firm_ycomp_debug_init_realizer(void) {
+/**
+ * Register the edge and node realizer in yComp.
+ */
+static void firm_ycomp_debug_init_realizer(firm_ycomp_dbg_t *dbg) {
        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",
+               snprintf(buf, sizeof(buf), "addNodeRealizer \"%u\" \"%s\" \"%s\" \"%s\" \"%s\"\n",
                        node_realizer[i].id,
                        node_realizer[i].linecolor,
                        node_realizer[i].fillcolor,
+                       node_realizer[i].textcolor,
                        node_realizer[i].shape);
-               send_cmd(buf);
+               send_cmd(dbg, buf);
        }
 
        for (i = 0; i < EDGE_REALIZER_LAST; ++i) {
-               snprintf(buf, sizeof(buf), "addEdgeRealizer \"%u\" \"%s\" \"%u\" \"%s\"\n",
+               snprintf(buf, sizeof(buf), "addEdgeRealizer \"%u\" \"%s\" \"%s\" \"%u\" \"%s\"\n",
                        edge_realizer[i].id,
                        edge_realizer[i].linecolor,
+                       edge_realizer[i].textcolor,
                        edge_realizer[i].thickness,
                        edge_realizer[i].style);
-               send_cmd(buf);
+               send_cmd(dbg, buf);
        }
 }
 
+/**
+ * Retrieve the appropriate realizer for given node.
+ */
 static INLINE unsigned get_node_realizer(ir_node *node) {
        unsigned realizer;
-       opcode   opc = get_irn_opcode(node);
+       ir_opcode opc = get_irn_opcode(node);
 
        switch (opc) {
                case iro_Block:
@@ -183,17 +221,22 @@ static INLINE unsigned get_node_realizer(ir_node *node) {
        return realizer;
 }
 
+/**
+ * Retrieve the appropriate realizer for given edge.
+ */
 static INLINE unsigned get_edge_realizer(ir_node *src, ir_node *tgt) {
        unsigned realizer;
-       ir_mode  *mode;
+       ir_mode  *tgt_mode, *src_mode;
 
-       assert(! is_Block(tgt));
+       if (is_Block(tgt) || is_Block(src))
+               return EDGE_REALIZER_CFG;
 
-       mode = get_irn_mode(tgt);
+       tgt_mode = get_irn_mode(tgt);
+       src_mode = is_Block(src) ? NULL : get_irn_mode(src);
 
-       if (mode == mode_M)
+       if (tgt_mode == mode_M || (src_mode == mode_M && tgt_mode == mode_T))
                realizer = EDGE_REALIZER_MEM;
-       else if (mode == mode_X)
+       else if (tgt_mode == mode_X)
                realizer = EDGE_REALIZER_CFG;
        else
                realizer = EDGE_REALIZER_DATA;
@@ -201,23 +244,38 @@ static INLINE unsigned get_edge_realizer(ir_node *src, ir_node *tgt) {
        return realizer;
 }
 
+/**
+ * Hook: Add new nodes, resp. new blocks in yComp and add input edges.
+ */
 static void firm_ycomp_debug_new_node(void *context, ir_graph *graph, ir_node *node) {
        firm_ycomp_dbg_t *dbg = context;
-       char     buf[SEND_BUF_SIZE];
-       int      i;
-       unsigned src_idx = get_irn_node_nr(node);
+       char             buf[SEND_BUF_SIZE];
+       int              i;
+       unsigned         src_idx;
 
-       if (get_const_code_irg() == graph)
+       if (get_const_code_irg() == graph || dbg->in_dead_node_elim)
                return;
 
+       src_idx       = get_irn_node_nr(node);
        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);
+       if (is_Block(node)) {
+               /* add block (subgraph) */
+               ir_snprintf(buf, sizeof(buf), "addSubgraphNode \"%d\" \"%d\" \"%u\" \"%+F\"\n",
+                       0,                     /* parent id */
+                       get_irn_node_nr(node), /* graph id */
+                       NODE_REALIZER_BLOCK,   /* realizer id */
+                       node);                 /* label */
+       }
+       else {
+               /* add node */
+               ir_snprintf(buf, sizeof(buf), "addNode \"%d\" \"%u\" \"%u\" \"%+F\"\n",
+                       get_irn_node_nr(get_nodes_block(node)), /* parent id */
+                       src_idx,                                /* node id */
+                       get_node_realizer(node),                /* realizer id */
+                       node);                                  /* label */
+       }
+       send_cmd(dbg, buf);
 
        /* add edges */
        for (i = get_irn_arity(node) - 1; i >= 0; --i) {
@@ -231,7 +289,7 @@ static void firm_ycomp_debug_new_node(void *context, ir_graph *graph, ir_node *n
                        tgt_idx,                        /* target node id */
                        get_edge_realizer(node, pred),  /* realizer id */
                        i);                             /* title */
-               send_cmd(buf);
+               send_cmd(dbg, buf);
 
                /* insert edge */
                key.src = node;
@@ -247,32 +305,61 @@ static void firm_ycomp_debug_new_node(void *context, ir_graph *graph, ir_node *n
                }
        }
 
-       send_cmd("show\n");
-       send_cmd("sync\n");
-       wait_for_sync();
+       show_and_sync(dbg);
 }
 
-static void firm_ycomp_debug_new_irg(void *context, ir_graph *irg, entity *ent) {
+/**
+ * Clear the old irg if it has some data and create a new one.
+ */
+static void firm_ycomp_debug_new_irg(void *context, ir_graph *irg,
+                                     ir_entity *ent)
+{
+       firm_ycomp_dbg_t *dbg = context;
+       char             buf[SEND_BUF_SIZE];
+       (void) irg;
+
        if (yy_dbg.has_data) {
-               send_cmd("deleteGraph\n");
-               send_cmd("show\n");
+               send_cmd(dbg, "deleteGraph\n");
+//             send_cmd(dbg, "show\n");
        }
-       yy_dbg.has_data = 0;
-       send_cmd("sync\n");
-       wait_for_sync();
+       dbg->has_data = 0;
+
+       ir_snprintf(buf, sizeof(buf), "addSubgraphNode \"-1\" \"0\" \"%u\" \"%s\"\n",
+               NODE_REALIZER_IRG, get_entity_name(ent));
+       send_cmd(dbg, buf);
+       send_cmd(dbg, "sync\n");
+       wait_for_sync(dbg);
 }
 
+/**
+ * Hook: Handle set_irn_n calls.
+ * - set new Block      OR
+ * - remove old edge and add new one
+ */
 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;
+       firm_ycomp_dbg_t           *dbg   = context;
+       exchange_node_outs_assoc_t *entry = NULL;
+       exchange_node_outs_assoc_t key;
        ycomp_edge_t               *old_edge, *new_edge, edge_key;
        char                       buf[SEND_BUF_SIZE];
-       unsigned                   src_idx, tgt_idx, old_tgt_idx;
+       unsigned                   src_idx, tgt_idx;
 
-       /* ignore block edges for now */
-       if (pos < 0)
+       if (dbg->in_dead_node_elim)
                return;
 
+       src_idx = get_irn_node_nr(src);
+       tgt_idx = get_irn_node_nr(tgt);
+
+       /* set_irn_n with pos -1 means: node moves to new block  */
+       if (pos < 0) {
+               if (tgt != old_tgt) {
+                       snprintf(buf, sizeof(buf), "moveNode \"%d\" \"%d\"\n", src_idx, tgt_idx);
+                       send_cmd(dbg, buf);
+                       show_and_sync(dbg);
+               }
+               return;
+       }
+
        /* check if the new edge exists */
        edge_key.src = src;
        edge_key.tgt = tgt;
@@ -284,29 +371,29 @@ static void firm_ycomp_debug_set_edge(void *context, ir_node *src, int pos, ir_n
                return;
 
        /* check if the old edge exists */
-       edge_key.src = src;
-       edge_key.tgt = old_tgt;
-       edge_key.pos = pos;
-       old_edge     = pset_find(dbg->edges, &edge_key, HASH_EDGE(&edge_key));
+       if (old_tgt) {
+               int old_tgt_idx = get_irn_node_nr(old_tgt);
 
-       /* check if old target is marked for exchange */
-       key.irn = old_tgt;
-       entry   = pset_find(dbg->exchanged_nodes, &key, HASH_PTR(old_tgt));
+               edge_key.src = src;
+               edge_key.tgt = old_tgt;
+               edge_key.pos = pos;
+               old_edge     = pset_find(dbg->edges, &edge_key, HASH_EDGE(&edge_key));
 
-       if (entry) {
-               /* we are called from exchange() */
-               entry->n_out_edges--;
-       }
+               /* check if old target is marked for exchange */
+               key.irn = old_tgt;
+               entry   = pset_find(dbg->exchanged_nodes, &key, HASH_PTR(old_tgt));
 
-       src_idx     = get_irn_node_nr(src);
-       tgt_idx     = get_irn_node_nr(tgt);
-       old_tgt_idx = get_irn_node_nr(old_tgt);
+               if (entry) {
+                       /* we are called from exchange() */
+                       entry->n_out_edges--;
+               }
 
-       if (old_edge) {
                /* delete the old edge if it exists */
-               snprintf(buf, sizeof(buf), "deleteEdge \"n%un%up%d\"\n", src_idx, old_tgt_idx, pos);
-               send_cmd(buf);
-               pset_remove(dbg->edges, old_edge, HASH_EDGE(old_edge));
+               if (old_edge) {
+                       snprintf(buf, sizeof(buf), "deleteEdge \"n%un%up%d\"\n", src_idx, old_tgt_idx, pos);
+                       send_cmd(dbg, buf);
+                       pset_remove(dbg->edges, old_edge, HASH_EDGE(old_edge));
+               }
        }
 
        if (! new_edge) {
@@ -317,7 +404,7 @@ static void firm_ycomp_debug_set_edge(void *context, ir_node *src, int pos, ir_n
                        tgt_idx,                        /* target node id */
                        get_edge_realizer(src, tgt),    /* realizer id */
                        pos);                           /* title */
-               send_cmd(buf);
+               send_cmd(dbg, buf);
 
                /* insert the new edge */
                new_edge      = obstack_alloc(&dbg->obst, sizeof(*new_edge));
@@ -329,30 +416,111 @@ static void firm_ycomp_debug_set_edge(void *context, ir_node *src, int pos, ir_n
 
        /* 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();
+               show_and_sync(dbg);
        }
 }
 
+/**
+ * Hook: Put nodes, about to be exchanged into a set.
+ */
 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;
 
+       /* put nodes, which are about to be exchanged into a set */
+
        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);
+               entry->nw          = new_node;
        }
        else {
                entry              = obstack_alloc(&dbg->obst, sizeof(*entry));
                entry->irn         = old_node;
+               entry->nw          = new_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) {
+/**
+ * Hook: Remove all old in edges, turn node into id node, add new input edge.
+ */
+static void firm_ycomp_debug_turn_into_id(void *context, ir_node *old_node) {
+       firm_ycomp_dbg_t           *dbg = context;
+       exchange_node_outs_assoc_t key, *entry;
+       int                        i;
+       char                       buf[SEND_BUF_SIZE];
+       unsigned                   src_idx, tgt_idx;
+       ycomp_edge_t               edge_key, *new_edge;
+
+       key.irn = old_node;
+       entry   = pset_find(dbg->exchanged_nodes, &key, HASH_PTR(old_node));
+
+       assert(entry != NULL && "Exchange entry missing");
+
+       src_idx = get_irn_node_nr(old_node);
+       tgt_idx = get_irn_node_nr(entry->nw);
+
+       /* remove all old edges */
+       for (i = get_irn_arity(old_node) - 1; i >= 0; --i) {
+               ycomp_edge_t *old_edge;
+               unsigned     old_tgt_idx;
+
+               /* check if the old edge exists */
+               edge_key.src = old_node;
+               edge_key.tgt = get_irn_n(old_node, i);
+               edge_key.pos = i;
+               old_edge     = pset_find(dbg->edges, &edge_key, HASH_EDGE(&edge_key));
+
+               old_tgt_idx  = get_irn_node_nr(edge_key.tgt);
+
+               /* remove the old edge */
+               if (old_edge) {
+                       snprintf(buf, sizeof(buf), "deleteEdge \"n%un%up%d\"\n", src_idx, old_tgt_idx, i);
+                       send_cmd(dbg, buf);
+                       pset_remove(dbg->edges, old_edge, HASH_EDGE(old_edge));
+               }
+       }
+
+       /* change the old node into an id node */
+       snprintf(buf, sizeof(buf), "changeNode \"%ld\" \"%u\"\n", get_irn_node_nr(old_node), NODE_REALIZER_ID);
+       send_cmd(dbg, buf);
+
+       /* add new Id input */
+       snprintf(buf, sizeof(buf), "addEdge \"n%un%up%d\" \"%u\" \"%u\" \"%u\" \"%d\"\n",
+               src_idx, tgt_idx, 0,                       /* edge id */
+               src_idx,                                   /* source node id */
+               tgt_idx,                                   /* target node id */
+               get_edge_realizer(old_node, entry->nw),    /* realizer id */
+               0);                                        /* title */
+       send_cmd(dbg, buf);
+
+       /* go */
+       show_and_sync(dbg);
+
+       /* add the new edge to our pset */
+       new_edge = obstack_alloc(&dbg->obst, sizeof(*new_edge));
+       new_edge->src = old_node;
+       new_edge->tgt = entry->nw;
+       new_edge->pos = 0;
+       pset_insert(dbg->edges, new_edge, HASH_EDGE(new_edge));
+}
+
+/**
+ * Hook: Just mark start/end of dead node elimination.
+ */
+static void firm_ycomp_debug_dead_node_elim(void *context, ir_graph *irg, int start) {
+       firm_ycomp_dbg_t *dbg  = context;
+       (void) irg;
+       dbg->in_dead_node_elim = start != 0;
+}
+
+/**
+ * Establish connection to yComp and register all hooks.
+ */
+void firm_init_ycomp_debugger(const char *host, unsigned port) {
        static int init_once = 0;
 
        if (init_once)
@@ -361,52 +529,58 @@ void firm_init_ycomp_debugger(const char *host, uint16_t port) {
        memset(&yy_dbg, 0, sizeof(yy_dbg));
        yy_dbg.fd = -1;
 
-       host = "localhost";
-       port = 4242;
-
+       fprintf(stderr, "connecting to %s:%u\n", host, port);
        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();
+               firm_ycomp_debug_init_realizer(&yy_dbg);
                yy_dbg.exchanged_nodes = new_pset(cmp_nodes, 20);
                yy_dbg.edges           = new_pset(cmp_edges, 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);
+#define REGISTER_HOOK(ycomp_hook, firm_hook, func)     \
+       do {                                               \
+               yy_dbg.ycomp_hook.context           = &yy_dbg; \
+               yy_dbg.ycomp_hook.hook._##firm_hook = func;    \
+               register_hook(firm_hook, &yy_dbg.ycomp_hook);  \
+       } while(0)
+
+               REGISTER_HOOK(hook_new_irn,   hook_new_node,       firm_ycomp_debug_new_node);
+               REGISTER_HOOK(hook_new_irg,   hook_new_graph,      firm_ycomp_debug_new_irg);
+               REGISTER_HOOK(hook_set_edge,  hook_set_irn_n,      firm_ycomp_debug_set_edge);
+               REGISTER_HOOK(hook_exchange,  hook_replace,        firm_ycomp_debug_exchange);
+               REGISTER_HOOK(hook_into_id,   hook_turn_into_id,   firm_ycomp_debug_turn_into_id);
+               REGISTER_HOOK(hook_dead_node, hook_dead_node_elim, firm_ycomp_debug_dead_node_elim);
+
+#undef REGISTER_HOOK
        }
 
        init_once = 1;
 }
 
+/**
+ * Close connection to yComp, unregister all hooks and free memory.
+ */
 void firm_finish_ycomp_debugger(void) {
        if (yy_dbg.fd > -1) {
+               /* close connection */
                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);
+               yy_dbg.fd = -1;
+
+               /* unregister all hooks */
+               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);
+               unregister_hook(hook_dead_node_elim, &yy_dbg.hook_dead_node);
+               unregister_hook(hook_turn_into_id,   &yy_dbg.hook_into_id);
+
+               /* clear sets */
                del_pset(yy_dbg.exchanged_nodes);
                del_pset(yy_dbg.edges);
-               yy_dbg.exchanged_nodes = NULL;
+
+               /* free data obstack */
                obstack_free(&yy_dbg.obst, NULL);
        }
 }