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
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
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
24 #include "coretypes.h"
29 #include "hard-reg-set.h"
30 #include "basic-block.h"
32 #include "diagnostic.h"
33 #include "tree-flow.h"
34 #include "tree-dump.h"
35 #include "tree-pass.h"
39 #include "tree-inline.h"
43 #include "tree-iterator.h"
46 #include "highlev-plugin-internal.h"
48 /* Info for function instrumentation. */
52 is_it_instrumentable (struct cgraph_node
*cg_func
)
54 if (cgraph_function_body_availability (cg_func
) == AVAIL_NOT_AVAILABLE
)
61 freeinstrinfo (instrinfo idi
)
63 /* free instrumentation info. */
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
);
79 is_in_instrument_list (const char *func_name
, const char *file_name
,
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)
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
;
102 basic_block bb
= NULL
;
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
= build_function_call_expr (func_decl
, NULL_TREE
);
109 location
= DECL_SOURCE_LOCATION(decl
);
110 DECL_SOURCE_LOCATION(func_decl
) = location
;
112 /*convert the call_expr (tree) to gimple_seq(gp_seq)*/
113 gimplify_stmt(&call_expr
, &gp_seq
);
115 func
= DECL_STRUCT_FUNCTION (decl
);
116 bb
= ENTRY_BLOCK_PTR_FOR_FUNCTION (func
)->next_bb
;
117 gsi
= gsi_start_bb(bb
);
119 gsi_insert_seq_after (&gsi
, gp_seq
, GSI_NEW_STMT
);
121 gsi_insert_seq_before (&gsi
, gp_seq
, GSI_NEW_STMT
);
122 stmt
= gsi_stmt (gsi
);
123 gimple_set_location (stmt
, location
);
125 cgraph_create_edge (cg_func
, cgraph_node (func_decl
),
127 bb
->count
, CGRAPH_FREQ_MAX
, bb
->loop_depth
);
132 add_timer_end (struct cgraph_node
*cg_func
, char *funname
)
136 gimple_stmt_iterator gsi
;
137 struct function
*func
= NULL
;
139 gimple_seq gp_seq
= NULL
;
140 tree decl
, ftype
, func_decl
, call_expr
;
143 decl
= cg_func
->decl
;
144 ftype
= build_function_type (void_type_node
, void_list_node
);
145 func_decl
= build_fn_decl (funname
, ftype
);
147 func
= DECL_STRUCT_FUNCTION (decl
);
148 location
= func
->function_end_locus
;
149 DECL_SOURCE_LOCATION(func_decl
) = location
;
151 FOR_EACH_EDGE (e
, ei
, EXIT_BLOCK_PTR_FOR_FUNCTION (func
)->preds
)
153 gsi
= gsi_last_bb (e
->src
);
155 call_expr
= build_function_call_expr (func_decl
, NULL_TREE
);
156 gimplify_stmt(&call_expr
, &gp_seq
);
158 if (gimple_code(gsi_stmt (gsi
)) == GIMPLE_RETURN
)
159 gsi_insert_seq_before (&gsi
, gp_seq
, GSI_NEW_STMT
);
161 gsi_insert_seq_after (&gsi
, gp_seq
, GSI_NEW_STMT
);
163 stmt
= gsi_stmt (gsi
);
164 gimple_set_location (stmt
, location
);
167 cgraph_create_edge (cg_func
, cgraph_node (func_decl
),
169 e
->src
->count
, CGRAPH_FREQ_MAX
,
175 exec_instrument_functions (void)
177 struct cgraph_node
*node
;
178 struct function
*saved_cfun
, *func
;
180 char *beginname
= NULL
, *endname
= NULL
;
182 idi
.numofinstrfun
= 0;
184 register_event_parameter("instr_info", &idi
, EP_VOID
);
185 call_plugin_event("load_instr_config");
186 unregister_event_parameter("instr_info");
188 if (idi
.numofinstrfun
== 0)
190 fprintf (stderr
, "No infomation for instrumentation pass\n");
194 /* Perform instrument to functions. */
195 for (node
= cgraph_nodes
; node
; node
= node
->next
)
197 const char *node_name
= NULL
;
198 const char *file_name
= NULL
;
199 func
= DECL_STRUCT_FUNCTION (node
->decl
);
201 node_name
= IDENTIFIER_POINTER (DECL_NAME (node
->decl
));
202 file_name
= expand_location(DECL_SOURCE_LOCATION (node
->decl
)).file
;
204 if (is_in_instrument_list (node_name
, file_name
, &nid
)
205 && is_it_instrumentable(node
))
208 if (*(idi
.cloned
+ nid
) == '1')
210 if (getenv ("ICI_VERBOSE") != NULL
)
211 printf("Now instrument function: %s \n", node_name
);
212 beginname
= (char *) alloca (strlen (node_name
) +
213 strlen (*(idi
.timer1
+ nid
)));
214 if ((*(idi
.timer1
+ nid
))[0] == '_')
215 sprintf (beginname
, "%s%s", node_name
, *(idi
.timer1
+ nid
));
217 sprintf (beginname
, "%s", *(idi
.timer1
+ nid
));
219 add_timer_begin (node
, beginname
, flag_cloned
);
221 endname
= (char *) alloca (strlen (node_name
) +
222 strlen (*(idi
.timer2
+ nid
)));
223 if ((*(idi
.timer2
+ nid
))[0] == '_')
224 sprintf (endname
, "%s%s", node_name
, *(idi
.timer2
+ nid
));
226 sprintf (endname
, "%s", *(idi
.timer2
+ nid
));
228 add_timer_end (node
, endname
);
232 set_cfun(saved_cfun
);
238 gate_instrument_functions(void)
240 return flag_api_instrument_functions
;
243 struct gimple_opt_pass pass_instrument_functions
= {
246 "instrumentation", /* name */
247 gate_instrument_functions
, /* gate */
248 exec_instrument_functions
, /* execute */
251 0, /* static_pass_number */
253 0, /* properties_required */
254 0, /* properties_provided */
255 0, /* properties_destroyed */
256 0, /* todo_flags_start */
257 TODO_dump_cgraph
| TODO_verify_flow
, /* todo_flags_finish */