Set SVN properties.
[libfirm] / ir / ir / instrument.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   Instrumentation of graphs.
23  * @date    14.4.2008
24  * @author  Michael Beck
25  * @version $Id$
26  */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include "irgraph_t.h"
32 #include "iredges.h"
33 #include "error.h"
34 #include "ircons.h"
35 #include "instrument.h"
36
37 /**
38  * Adds a Call at the beginning of the given irg.
39  */
40 void instrument_initcall(ir_graph *irg, ir_entity *ent) {
41         const ir_edge_t *edge;
42         ir_node         *initial_exec;
43         ir_node         *initial_mem;
44         ir_node         *start_block;
45         ir_node         *adr, *call, *new_mem;
46         ir_node         *first_block = NULL;
47         int             i, idx, need_new_block;
48         symconst_symbol sym;
49
50         edges_assure(irg);
51
52         /* find the first block */
53         initial_exec = get_irg_initial_exec(irg);
54         start_block  = get_irg_start_block(irg);
55
56         foreach_out_edge(initial_exec, edge) {
57                 ir_node *succ = get_edge_src_irn(edge);
58
59                 if (succ != start_block && is_Block(succ)) {
60                         /* found the first block */
61                         first_block = succ;
62                         break;
63                 }
64         }
65         if (first_block == NULL) {
66                 panic("Cannot find first block of irg %+F\n", irg);
67         }
68
69         /* check if this block has only one predecessor */
70         idx = -1;
71         need_new_block = 0;
72         for (i = get_Block_n_cfgpreds(first_block) - 1; i >= 0; --i) {
73                 ir_node *p = get_Block_cfgpred(first_block, i);
74
75                 if (is_Bad(p))
76                         continue;
77                 if (p == initial_exec)
78                         idx = i;
79                 else
80                         need_new_block = 1;
81         }
82
83         if (need_new_block) {
84                 ir_node *blk = new_r_Block(irg, 1, &initial_exec);
85                 set_Block_cfgpred(first_block, idx, new_r_Jmp(irg, blk));
86                 first_block = blk;
87         }
88
89         /* place the call */
90         sym.entity_p = ent;
91         adr = new_r_SymConst(irg, start_block, mode_P_code, sym, symconst_addr_ent);
92
93         call    = new_r_Call(irg, first_block, get_irg_no_mem(irg), adr, 0, NULL, get_entity_type(ent));
94         new_mem = new_r_Proj(irg, first_block, call, mode_M, pn_Call_M_regular);
95
96         initial_mem = get_irg_initial_mem(irg);
97         edges_reroute(initial_mem, new_mem, irg);
98         /* beware: reroute routes anchor edges also, revert this */
99         set_irg_initial_mem(irg, initial_mem);
100         set_Call_mem(call, initial_mem);
101 }