Move ici specific files to new directory ici; add new file ici/ici.c
[official-gcc.git] / gcc / ici / function-instrumentation.c
blobbb8d388ef6e1e50933748384e6953dbaf55c1cd4
1 /* Function Instrumentation.
2 Copyright (C) 2009 by Cupertino Miranda, Shuangde Huang, Liang Peng
3 INRIA Futurs, France; ICT, China;
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "rtl.h"
28 #include "tm_p.h"
29 #include "hard-reg-set.h"
30 #include "basic-block.h"
31 #include "output.h"
32 #include "diagnostic.h"
33 #include "tree-flow.h"
34 #include "tree-dump.h"
35 #include "tree-pass.h"
36 #include "timevar.h"
37 #include "cfgloop.h"
38 #include "flags.h"
39 #include "tree-inline.h"
40 #include "cgraph.h"
41 #include "ipa-prop.h"
42 #include "opts.h"
43 #include "tree-iterator.h"
44 #include "gimple.h"
45 #include "toplev.h"
46 #include "highlev-plugin-internal.h"
48 /* Info for function instrumentation. */
49 instrinfo idi;
51 static bool
52 is_it_instrumentable (struct cgraph_node *cg_func)
54 if (cgraph_function_body_availability (cg_func) == AVAIL_NOT_AVAILABLE)
55 return false;
56 else
57 return true;
60 static void
61 freeinstrinfo (instrinfo idi)
63 /* free instrumentation info. */
64 int i;
65 for(i=0; i<idi.numofinstrfun; i++)
67 free (*(idi.instrument_function_list + i));
68 free (*(idi.function_filename_list + i));
69 free (*(idi.timer1 + i));
70 free (*(idi.timer2 + i));
72 free (idi.instrument_function_list);
73 free (idi.function_filename_list);
74 free (idi.timer1);
75 free (idi.timer2);
78 static bool
79 is_in_instrument_list (const char *func_name, const char *file_name,
80 int *nid)
82 int i = 0;
83 for(i = 0; i < idi.numofinstrfun; i++)
85 if (strcmp (func_name, *(idi.instrument_function_list + i)) == 0
86 && strcmp (file_name, *(idi.function_filename_list + i)) == 0)
88 *nid = i;
89 return true;
92 return false;
95 static void
96 add_timer_begin (struct cgraph_node *cg_func, char *funname, int cloned)
98 gimple_stmt_iterator gsi;
99 struct function * func = NULL;
100 gimple_seq gp_seq = NULL;
101 gimple stmt = NULL;
102 basic_block bb = NULL;
103 location_t location;
105 tree decl = cg_func->decl;
106 tree ftype = build_function_type (void_type_node, void_list_node);
107 tree func_decl = build_fn_decl (funname, ftype);
108 tree call_expr
109 = build_function_call_expr (UNKNOWN_LOCATION, func_decl, NULL_TREE);
110 location = DECL_SOURCE_LOCATION(decl);
111 DECL_SOURCE_LOCATION(func_decl) = location;
113 /*convert the call_expr (tree) to gimple_seq(gp_seq)*/
114 gimplify_stmt(&call_expr, &gp_seq);
116 func = DECL_STRUCT_FUNCTION (decl);
117 bb = ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->next_bb;
118 gsi = gsi_start_bb(bb);
119 if(cloned == 1)
120 gsi_insert_seq_after (&gsi, gp_seq, GSI_NEW_STMT);
121 else
122 gsi_insert_seq_before (&gsi, gp_seq, GSI_NEW_STMT);
123 stmt = gsi_stmt (gsi);
124 gimple_set_location (stmt, location);
126 cgraph_create_edge (cg_func, cgraph_node (func_decl),
127 stmt,
128 bb->count, CGRAPH_FREQ_MAX, bb->loop_depth);
132 static void
133 add_timer_end (struct cgraph_node *cg_func, char *funname)
135 edge e;
136 edge_iterator ei;
137 gimple_stmt_iterator gsi;
138 struct function *func = NULL;
139 gimple stmt = NULL;
140 gimple_seq gp_seq = NULL;
141 tree decl, ftype, func_decl, call_expr;
142 location_t location;
144 decl = cg_func->decl;
145 ftype = build_function_type (void_type_node, void_list_node);
146 func_decl = build_fn_decl (funname, ftype);
148 func = DECL_STRUCT_FUNCTION (decl);
149 location = func->function_end_locus;
150 DECL_SOURCE_LOCATION(func_decl) = location;
152 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FUNCTION (func)->preds)
154 gsi = gsi_last_bb (e->src);
156 call_expr
157 = build_function_call_expr (UNKNOWN_LOCATION, func_decl, NULL_TREE);
158 gimplify_stmt(&call_expr, &gp_seq);
160 if (gimple_code(gsi_stmt (gsi)) == GIMPLE_RETURN)
161 gsi_insert_seq_before (&gsi, gp_seq, GSI_NEW_STMT);
162 else
163 gsi_insert_seq_after (&gsi, gp_seq, GSI_NEW_STMT);
165 stmt = gsi_stmt (gsi);
166 gimple_set_location (stmt, location);
167 gp_seq = NULL;
169 cgraph_create_edge (cg_func, cgraph_node (func_decl),
170 stmt,
171 e->src->count, CGRAPH_FREQ_MAX,
172 e->src->loop_depth);
176 static unsigned int
177 exec_instrument_functions (void)
179 struct cgraph_node *node;
180 struct function *saved_cfun, *func;
181 int nid = -1;
182 char *beginname = NULL, *endname = NULL;
183 saved_cfun = cfun;
184 idi.numofinstrfun = 0;
186 invoke_named_callbacks ("load_instr_config",
187 "instr_info", EP_VOID, &idi, EP_VOID, NULL);
189 if (idi.numofinstrfun == 0)
191 fprintf (stderr, "No infomation for instrumentation pass\n");
192 return 0;
195 /* Perform instrument to functions. */
196 for (node = cgraph_nodes; node; node = node->next)
198 const char *node_name = NULL;
199 const char *file_name = NULL;
200 func = DECL_STRUCT_FUNCTION (node->decl);
201 set_cfun (func);
202 node_name = IDENTIFIER_POINTER (DECL_NAME (node->decl));
203 file_name = expand_location(DECL_SOURCE_LOCATION (node->decl)).file;
205 if (is_in_instrument_list (node_name, file_name, &nid)
206 && is_it_instrumentable(node))
208 int flag_cloned = 0;
209 if (*(idi.cloned + nid) == '1')
210 flag_cloned = 1;
211 if (getenv ("ICI_VERBOSE") != NULL)
212 printf("Now instrument function: %s \n", node_name);
213 beginname = (char *) alloca (strlen (node_name) +
214 strlen (*(idi.timer1 + nid)));
215 if ((*(idi.timer1 + nid))[0] == '_')
216 sprintf (beginname, "%s%s", node_name, *(idi.timer1 + nid));
217 else
218 sprintf (beginname, "%s", *(idi.timer1 + nid));
220 add_timer_begin (node, beginname, flag_cloned);
222 endname = (char *) alloca (strlen (node_name) +
223 strlen (*(idi.timer2 + nid)));
224 if ((*(idi.timer2 + nid))[0] == '_')
225 sprintf (endname, "%s%s", node_name, *(idi.timer2 + nid));
226 else
227 sprintf (endname, "%s", *(idi.timer2 + nid));
229 add_timer_end (node, endname);
233 set_cfun(saved_cfun);
234 freeinstrinfo (idi);
235 return 0;
238 static bool
239 gate_instrument_functions(void)
241 return flag_api_instrument_functions;
244 struct gimple_opt_pass pass_instrument_functions = {
246 SIMPLE_IPA_PASS ,
247 "instrumentation", /* name */
248 gate_instrument_functions, /* gate */
249 exec_instrument_functions, /* execute */
250 NULL, /* sub */
251 NULL, /* next */
252 0, /* static_pass_number */
253 0, /* tv_id */
254 0, /* properties_required */
255 0, /* properties_provided */
256 0, /* properties_destroyed */
257 0, /* todo_flags_start */
258 TODO_dump_cgraph | TODO_verify_flow, /* todo_flags_finish */