From c9036234fbf4b8b9c2b26ea3ba46e3bacd6d46fa Mon Sep 17 00:00:00 2001 From: amylaar Date: Tue, 1 Dec 2009 19:12:29 +0000 Subject: 2009-12-01 Grigori Fursin Joern Rennecke * cgraphunit.c (plugin.h): Include. (ipa_passes): Invoke PLUGIN_ALL_IPA_PASSES_START / PLUGIN_ALL_IPA_PASSES_END at start / end of processing. * gcc-plugin.h (highlev-plugin-common.h, hashtab.h): Include. (enum plugin_event): Define by including plugin.def. Last enumerator is now called PLUGIN_EVENT_FIRST_DYNAMIC. (plugin_event_name): Change type to const char **. (get_event_last, get_named_event_id, unregister_callback): Declare. (register_callback): Change type of event argument to int. (highlev-plugin-common.h): New file. * Makefile.in (GCC_PLUGIN_H): Add highlev-plugin-common.h and $(HASHTAB_H) (tree-optimize.o passes.o): Depend on $(PLUGIN_H). (PLUGIN_HEADERS): Add opts.h, $(PARAMS_H) and plugin.def. (s-header-vars): New rule. (install-plugin): Depend on s-header-vars. Install b-header-vars. * params.c (get_num_compiler_params): New function. * params.h (get_num_compiler_params): Declare. * passes.c (plugin.h): Include. (make_pass_instance): Invoke PLUGIN_NEW_PASS. (do_per_function_toporder, pass_init_dump_file): No longer static. (pass_fini_dump_file): Likewise. (execute_one_pass): Likewise. Invoke PLUGIN_OVERRIDE_GATE and PLUGIN_PASS_EXECUTION. (execute_ipa_pass_list): Invoke PLUGIN_EARLY_GIMPLE_PASSES_START and PLUGIN_EARLY_GIMPLE_PASSES_END. * plugin.c (plugin_event_name_init): New array, defined by including plugin.def. (FMT_FOR_PLUGIN_EVENT): Update. (plugin_event_name): Change type to const char ** and initialize to plugin_event_name_init. (event_tab, event_last, event_horizon): New variable. (get_event_last): New function. (plugin_callbacks_init): New array. (plugin_callbacks: Change type to struct callback_info **. Initialize to plugin_callbacks_init. (htab_event_eq, get_named_event_id, unregister_callback): New function. (invoke_plugin_va_callbacks): Likewise. (register_callback): Change type of event argument to int. Handle new events. Allow dynamic events. (invoke_plugin_callbacks): Likewise. Return success status. (plugins_active_p): Allow dynamic callbacks. * plugin.def: New file. * plugin.h (invoke_plugin_callbacks): Update prototype. (invoke_plugin_va_callbacks): Declare. * tree-optimize.c (plugin.h): Include. (tree_rest_of_compilation): Invoke PLUGIN_ALL_PASSES_START and PLUGIN_ALL_PASSES_END. * tree-pass.h (execute_one_pass, pass_init_dump_file): Declare. (pass_fini_dump_file, do_per_function_toporder): Likewise. * doc/plugin.texi: Document new event types. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@154877 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/plugin.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 161 insertions(+), 29 deletions(-) (limited to 'gcc/plugin.c') diff --git a/gcc/plugin.c b/gcc/plugin.c index c43e0c844a1..84c9f4434dc 100644 --- a/gcc/plugin.c +++ b/gcc/plugin.c @@ -44,28 +44,30 @@ along with GCC; see the file COPYING3. If not see #include "plugin-version.h" #endif +#define GCC_PLUGIN_STRINGIFY0(X) #X +#define GCC_PLUGIN_STRINGIFY1(X) GCC_PLUGIN_STRINGIFY0 (X) + /* Event names as strings. Keep in sync with enum plugin_event. */ -const char *plugin_event_name[] = +static const char *plugin_event_name_init[] = { - "PLUGIN_PASS_MANAGER_SETUP", - "PLUGIN_FINISH_TYPE", - "PLUGIN_FINISH_UNIT", - "PLUGIN_CXX_CP_PRE_GENERICIZE", - "PLUGIN_FINISH", - "PLUGIN_INFO", - "PLUGIN_GGC_START", - "PLUGIN_GGC_MARKING", - "PLUGIN_GGC_END", - "PLUGIN_REGISTER_GGC_ROOTS", - "PLUGIN_REGISTER_GGC_CACHES", - "PLUGIN_ATTRIBUTES", - "PLUGIN_START_UNIT", - "PLUGIN_PRAGMAS", - "PLUGIN_EVENT_LAST" +# define DEFEVENT(NAME) GCC_PLUGIN_STRINGIFY1 (NAME), +# include "plugin.def" +# undef DEFEVENT }; /* A printf format large enough for the largest event above. */ -#define FMT_FOR_PLUGIN_EVENT "%-26s" +#define FMT_FOR_PLUGIN_EVENT "%-32s" + +const char **plugin_event_name = plugin_event_name_init; + +/* A hash table to map event names to the position of the names in the + plugin_event_name table. */ +static htab_t event_tab; + +/* Keep track of the limit of allocated events and space ready for + allocating events. */ +static int event_last = PLUGIN_EVENT_FIRST_DYNAMIC; +static int event_horizon = PLUGIN_EVENT_FIRST_DYNAMIC; /* Hash table for the plugin_name_args objects created during command-line parsing. */ @@ -81,7 +83,8 @@ struct callback_info }; /* An array of lists of 'callback_info' objects indexed by the event id. */ -static struct callback_info *plugin_callbacks[PLUGIN_EVENT_LAST] = { NULL }; +static struct callback_info *plugin_callbacks_init[PLUGIN_EVENT_FIRST_DYNAMIC]; +static struct callback_info **plugin_callbacks = plugin_callbacks_init; #ifdef ENABLE_PLUGIN @@ -290,6 +293,71 @@ register_plugin_info (const char* name, struct plugin_info *info) plugin->help = info->help; } +/* Helper function for the event hash table that compares the name of an + existing entry (E1) with the given string (S2). */ + +static int +htab_event_eq (const void *e1, const void *s2) +{ + const char *s1= *(const char * const *) e1; + return !strcmp (s1, (const char *) s2); +} + +/* Look up the event id for NAME. If the name is not found, return -1 + if INSERT is NO_INSERT. */ + +int +get_named_event_id (const char *name, enum insert_option insert) +{ + void **slot; + + if (!event_tab) + { + int i; + + event_tab = htab_create (150, htab_hash_string, htab_event_eq, NULL); + for (i = 0; i < PLUGIN_EVENT_FIRST_DYNAMIC; i++) + { + slot = htab_find_slot (event_tab, plugin_event_name[i], INSERT); + gcc_assert (*slot == HTAB_EMPTY_ENTRY); + *slot = &plugin_event_name[i]; + } + } + slot = htab_find_slot (event_tab, name, insert); + if (slot == NULL) + return -1; + if (*slot != HTAB_EMPTY_ENTRY) + return (const char **) *slot - &plugin_event_name[0]; + + if (event_last >= event_horizon) + { + event_horizon = event_last * 2; + if (plugin_event_name == plugin_event_name_init) + { + plugin_event_name = XNEWVEC (const char *, event_horizon); + memcpy (plugin_event_name, plugin_event_name_init, + sizeof plugin_event_name_init); + plugin_callbacks = XNEWVEC (struct callback_info *, event_horizon); + memcpy (plugin_callbacks, plugin_callbacks_init, + sizeof plugin_callbacks_init); + } + else + { + plugin_event_name + = XRESIZEVEC (const char *, plugin_event_name, event_horizon); + plugin_callbacks = XRESIZEVEC (struct callback_info *, + plugin_callbacks, event_horizon); + } + /* All the pointers in the hash table will need to be updated. */ + htab_delete (event_tab); + event_tab = NULL; + } + else + *slot = &plugin_event_name[event_last]; + plugin_event_name[event_last] = name; + return event_last++; +} + /* Called from the plugin's initialization code. Register a single callback. This function can be called multiple times. @@ -300,7 +368,7 @@ register_plugin_info (const char* name, struct plugin_info *info) void register_callback (const char *plugin_name, - enum plugin_event event, + int event, plugin_callback_func callback, void *user_data) { @@ -322,6 +390,15 @@ register_callback (const char *plugin_name, gcc_assert (!callback); ggc_register_cache_tab ((const struct ggc_cache_tab*) user_data); break; + case PLUGIN_EVENT_FIRST_DYNAMIC: + default: + if (event < PLUGIN_EVENT_FIRST_DYNAMIC || event >= event_last) + { + error ("Unknown callback event registered by plugin %s", + plugin_name); + return; + } + /* Fall through. */ case PLUGIN_FINISH_TYPE: case PLUGIN_START_UNIT: case PLUGIN_FINISH_UNIT: @@ -332,6 +409,15 @@ register_callback (const char *plugin_name, case PLUGIN_ATTRIBUTES: case PLUGIN_PRAGMAS: case PLUGIN_FINISH: + case PLUGIN_ALL_PASSES_START: + case PLUGIN_ALL_PASSES_END: + case PLUGIN_ALL_IPA_PASSES_START: + case PLUGIN_ALL_IPA_PASSES_END: + case PLUGIN_OVERRIDE_GATE: + case PLUGIN_PASS_EXECUTION: + case PLUGIN_EARLY_GIMPLE_PASSES_START: + case PLUGIN_EARLY_GIMPLE_PASSES_END: + case PLUGIN_NEW_PASS: { struct callback_info *new_callback; if (!callback) @@ -348,27 +434,52 @@ register_callback (const char *plugin_name, plugin_callbacks[event] = new_callback; } break; - case PLUGIN_EVENT_LAST: - default: - error ("Unknown callback event registered by plugin %s", - plugin_name); } } +/* Remove a callback for EVENT which has been registered with for a plugin + PLUGIN_NAME. Return PLUGEVT_SUCCESS if a matching callback was + found & removed, PLUGEVT_NO_CALLBACK if the event does not have a matching + callback, and PLUGEVT_NO_SUCH_EVENT if EVENT is invalid. */ +int +unregister_callback (const char *plugin_name, int event) +{ + struct callback_info *callback, **cbp; + + if (event >= event_last) + return PLUGEVT_NO_SUCH_EVENT; + + for (cbp = &plugin_callbacks[event]; (callback = *cbp); cbp = &callback->next) + if (strcmp (callback->plugin_name, plugin_name) == 0) + { + *cbp = callback->next; + return PLUGEVT_SUCCESS; + } + return PLUGEVT_NO_CALLBACK; +} /* Called from inside GCC. Invoke all plug-in callbacks registered with the specified event. + Return PLUGEVT_SUCCESS if at least one callback was called, + PLUGEVT_NO_CALLBACK if there was no callback. EVENT - the event identifier GCC_DATA - event-specific data provided by the compiler */ -void -invoke_plugin_callbacks (enum plugin_event event, void *gcc_data) +int +invoke_plugin_callbacks (int event, void *gcc_data) { + int retval = PLUGEVT_SUCCESS; + timevar_push (TV_PLUGIN_RUN); switch (event) { + case PLUGIN_EVENT_FIRST_DYNAMIC: + default: + gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC); + gcc_assert (event < event_last); + /* Fall through. */ case PLUGIN_FINISH_TYPE: case PLUGIN_START_UNIT: case PLUGIN_FINISH_UNIT: @@ -379,24 +490,35 @@ invoke_plugin_callbacks (enum plugin_event event, void *gcc_data) case PLUGIN_GGC_START: case PLUGIN_GGC_MARKING: case PLUGIN_GGC_END: + case PLUGIN_ALL_PASSES_START: + case PLUGIN_ALL_PASSES_END: + case PLUGIN_ALL_IPA_PASSES_START: + case PLUGIN_ALL_IPA_PASSES_END: + case PLUGIN_OVERRIDE_GATE: + case PLUGIN_PASS_EXECUTION: + case PLUGIN_EARLY_GIMPLE_PASSES_START: + case PLUGIN_EARLY_GIMPLE_PASSES_END: + case PLUGIN_NEW_PASS: { /* Iterate over every callback registered with this event and call it. */ struct callback_info *callback = plugin_callbacks[event]; + + if (!callback) + retval = PLUGEVT_NO_CALLBACK; for ( ; callback; callback = callback->next) (*callback->func) (gcc_data, callback->user_data); } break; case PLUGIN_PASS_MANAGER_SETUP: - case PLUGIN_EVENT_LAST: case PLUGIN_REGISTER_GGC_ROOTS: case PLUGIN_REGISTER_GGC_CACHES: - default: gcc_assert (false); } timevar_pop (TV_PLUGIN_RUN); + return retval; } #ifdef ENABLE_PLUGIN @@ -621,7 +743,7 @@ plugins_active_p (void) { int event; - for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++) + for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++) if (plugin_callbacks[event]) return true; @@ -641,7 +763,7 @@ dump_active_plugins (FILE *file) return; fprintf (file, FMT_FOR_PLUGIN_EVENT " | %s\n", _("Event"), _("Plugins")); - for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++) + for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++) if (plugin_callbacks[event]) { struct callback_info *ci; @@ -686,3 +808,13 @@ plugin_default_version_check (struct plugin_gcc_version *gcc_version, return false; return true; } + +/* Return the current value of event_last, so that plugins which provide + additional functionality for events for the benefit of high-level plugins + know how many valid entries plugin_event_name holds. */ + +int +get_event_last (void) +{ + return event_last; +} -- cgit v1.2.1