1 /* High-level event callback mechanism for GCC plugins.
2 Copyright (C) 2009 Free Software Foundation, Inc.
6 Authors: Grigori Fursin <grigori.fursin@inria.fr>, Cupertino Miranda
7 <cupertinomiranda@gmail.com>, Zbigniew Chamski <zbigniew.chamski@gmail.com>.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
27 #include "coretypes.h"
30 #include "gcc-plugin.h"
31 #include "tree-pass.h"
33 #include "highlev-plugin-internal.h"
35 /* Event structure. */
36 struct hl_plugin_event
38 event_callback_t run
; /* Callback function */
39 const char *param_name
;
43 /* Parameter structure. */
44 struct event_parameter
46 const char *name
; /* Name for the parameter */
47 void *value
; /* Pointer to data */
48 event_parameter_type type
; /* Type enumeration of value */
52 static htab_t parameters_hash
= NULL
;
55 /* Hash dependent functions. */
57 string_htab_hash (const void *x
)
59 const char *p
= *((const char * const *) x
);
62 return htab_hash_string (p
);
69 string_htab_eq (const void *x
, const void *y
)
71 const char *s1
= *((const char * const *) x
);
72 const char *s2
= *((const char * const *) y
);
74 return !strcmp (s1
, s2
);
79 parameter_htab_del (void *p
)
81 struct parameter
*param
= (struct parameter
*) p
;
87 hash_param_callback (void *gcc_data
, void *user_data
)
89 struct hl_plugin_event
*ev
= (struct hl_plugin_event
*) user_data
;
97 /* Possible extension:
98 Might interpret gcc_data differently for specific values of
99 ev->event, e.g. we could get a struct loop and put all the
100 struct members in named parameters. */
101 va_copy (va
, * (va_list *) gcc_data
);
103 while ((name
= va_arg (va
, const char *)) != NULL
)
105 type
= va_arg (va
, int);
106 value
= va_arg (va
, void *);
107 register_event_parameter (name
, value
,
108 (event_parameter_type
) type
);
113 va_copy (va
, * (va_list *) gcc_data
);
114 while ((name
= va_arg (va
, const char *)) != NULL
)
116 unregister_event_parameter (name
);
122 status_callback (void *gcc_data
, void *user_data
)
124 struct hl_plugin_event
*ev
= (struct hl_plugin_event
*) user_data
;
126 register_event_parameter (ev
->param_name
, gcc_data
, EP_INT
);
128 unregister_event_parameter (ev
->param_name
);
132 pass_execution_callback (void *gcc_data
, void *user_data
)
134 struct hl_plugin_event
*ev
= (struct hl_plugin_event
*) user_data
;
135 struct opt_pass
*pass
= (struct opt_pass
*) gcc_data
;
137 register_event_parameter ("_pass_type", &(pass
->type
), EP_INT
);
139 unregister_event_parameter ("_pass_type");
142 /* Register a new event into hash table. */
144 register_plugin_event (const char *event_name
, event_callback_t func
)
147 struct hl_plugin_event
*ev
= XCNEW (struct hl_plugin_event
);
149 if (event_name
== NULL
)
150 internal_error ("Event cannot be registered with NULL name string\n");
152 event
= get_named_event_id (event_name
, INSERT
);
156 case PLUGIN_ALL_IPA_PASSES_EXECUTION
:
157 case PLUGIN_ALL_PASSES_EXECUTION
:
158 ev
->param_name
= "substitute_status";
159 register_callback ("ICI", event
, status_callback
, ev
);
161 case PLUGIN_AVOID_GATE
:
162 ev
->param_name
= "gate_status";
163 register_callback ("ICI", event
, status_callback
, ev
);
165 case PLUGIN_PASS_EXECUTION
:
166 register_callback ("ICI", event
, pass_execution_callback
, ev
);
169 register_callback ("ICI", event
, hash_param_callback
, ev
);
171 ici_refresh_internal_callbacks (event
);
175 /* Unregister an event. */
177 unregister_plugin_event (const char *event_name
)
179 int event
= get_named_event_id (event_name
, NO_INSERT
);
184 unregister_callback ("ICI", event
);
188 /* Return the array of all event names, terminated by NULL. */
190 list_plugin_events (void)
194 /* allocate space for all names + the terminating NULL */
195 const char **all_events
= XNEWVEC (const char *, (event_last
+ 1));
197 /* collect all event names */
198 for (i
= 0; i
< event_last
; i
++)
199 all_events
[i
] = plugin_event_name
[i
];
201 /* mark end-of-array */
202 all_events
[i
] = NULL
;
208 /* Register parameter.
209 * Insert parameter into hash table. Allocates hash table
212 register_event_parameter (const char *name
, void* value
,
213 event_parameter_type type
)
216 struct event_parameter
*param
= XCNEW (struct event_parameter
);
219 param
->value
= value
;
222 if (param
->name
== NULL
|| !strcmp ("", param
->name
))
223 internal_error ("Parameter cannot be registered with NULL name string\n");
225 if (parameters_hash
== NULL
)
227 htab_create_alloc (150, string_htab_hash
,
228 string_htab_eq
, parameter_htab_del
, xcalloc
, free
);
230 if (parameters_hash
!= NULL
)
232 slot
= htab_find_slot (parameters_hash
, param
, INSERT
);
233 *slot
= (void *) param
;
238 /* Unregister parameter. Remove it from hash table. */
240 unregister_event_parameter (const char *name
)
242 struct event_parameter param
;
245 if (parameters_hash
== NULL
)
246 internal_error ("Parameter hash not initialized.\n");
248 if (parameters_hash
!= NULL
)
249 htab_remove_elt (parameters_hash
, ¶m
);
253 /* Get parameter pointer to data.
254 Used by plugin to get pointer to data of the parameter <name>. */
256 get_event_parameter (const char *name
)
258 struct event_parameter tmp_param
, *param
;
259 tmp_param
.name
= name
;
261 if (parameters_hash
== NULL
)
262 internal_error ("Parameter hash not initialized.\n");
264 if (parameters_hash
!= NULL
)
266 param
= (struct event_parameter
*)
267 htab_find (parameters_hash
, &tmp_param
);
269 if (param
!= NULL
&& param
->value
!= NULL
)
275 /* Get parameter type.
276 Used by plugin to get type of data pointer of the parameter <name>. */
278 get_event_parameter_type (const char *name
)
280 struct event_parameter tmp_param
, *param
;
281 tmp_param
.name
= name
;
283 if (parameters_hash
== NULL
)
284 internal_error ("Parameter hash not initialized.\n");
286 if (parameters_hash
!= NULL
)
288 param
= (struct event_parameter
*)
289 htab_find (parameters_hash
, &tmp_param
);
291 if (param
!= NULL
&& param
->value
!= NULL
)
297 /* Get list of names of all registered ICI parameters.
298 * Traverse the hash table collecting the names of entries.
301 add_parameter_name (void **slot
, void *data
)
303 const char ***crnt_name_ptr
= (const char ***) data
;
304 struct event_parameter
*parameter
= *(struct event_parameter
**) slot
;
306 /* store the name of the current parameter at the corresponding
308 **crnt_name_ptr
= parameter
->name
;
310 /* advance the current location */
318 /* return the array of all parameter names, terminated by NULL */
320 list_event_parameters (void)
322 size_t num_parameters
= htab_elements (parameters_hash
);
324 /* allocate space for all names + the terminating NULL */
325 const char **all_parameters
= (const char **)
326 xmalloc (sizeof (const char *) * (num_parameters
+1));
328 const char ***data
= &all_parameters
; /* data ptr for mapped function */
329 const char **first_parameter
= all_parameters
; /* keep track of actual start */
331 /* mark end-of-array */
332 all_parameters
[num_parameters
] = NULL
;
334 /* collect all parameter names */
335 htab_traverse_noresize (parameters_hash
, add_parameter_name
, data
);
337 /* use the stored start-of-array - all_parameters has changed during
338 htab_traverse_noresize */
339 return first_parameter
;