From 740cd0bed10b436b5ab592163341464e25a5fef7 Mon Sep 17 00:00:00 2001 From: bstarynk Date: Tue, 26 May 2009 17:33:33 +0000 Subject: [PATCH] 2009-05-26 Basile Starynkevitch * gcc/doc/plugins.texi (Loading plugins): typo. (Plugin callbacks): Documented PLUGIN_INFO, PLUGIN_GGC_START, PLUGIN_GGC_MARKING, PLUGIN_GGC_END, PLUGIN_REGISTER_GGC_ROOTS. (Interacting with the GCC Garbage Collector): Added new section. (Giving information about a plugin): Added new section for PLUGIN_INFO. * gcc/testsuite/gcc.dg/plugin/plugin.exp: Added ggcplug.c test plugin with ggcplug-test-1.c for testing PLUGIN_GGC_MARKING etc... * gcc/testsuite/gcc.dg/plugin/ggcplug-test-1.c: Added new file. * gcc/testsuite/gcc.dg/plugin/ggcplug.c: Added new file. * gcc/ggc.h (ggc_register_root_tab): Added declaration. * gcc/gcc-plugin.h (PLUGIN_GGC_START, PLUGIN_GGC_MARKING) (PLUGIN_GGC_END, PLUGIN_REGISTER_GGC_ROOTS): Added new events. (register_callback): Improved comment in declaration. * gcc/ggc-common.c (const_ggc_root_tab_t) Added new typedef for vectors. (extra_root_vec) Added static variable for dynamic roots registration. (ggc_register_root_tab) Added new routine. (ggc_mark_roots) Added iteration inside extra_root_vec, and invoke PLUGIN_GGC_MARKING event. * gcc/ggc-zone.c: Include plugin.h. (ggc_collect): Invoke PLUGIN_GGC_START & PLUGIN_GGC_END events. * gcc/ggc-page.c: Include plugin.h. (ggc_collect): Invoke PLUGIN_GGC_START & PLUGIN_GGC_END events. * gcc/plugin.c (plugin_event_name): added names of PLUGIN_GGC_START, PLUGIN_GGC_MARKING, PLUGIN_GGC_END, PLUGIN_REGISTER_GGC_ROOTS (register_callback): check lack of callbacks for pseudo-events. Added handling of PLUGIN_REGISTER_GGC_ROOTS, PLUGIN_GGC_START, PLUGIN_GGC_MARKING, PLUGIN_GGC_END. (invoke_plugin_callbacks): Handle PLUGIN_GGC_START, PLUGIN_GGC_MARKING, PLUGIN_GGC_END, PLUGIN_REGISTER_GGC_ROOTS. * gcc/Makefile.in (ggc-common.o, ggc-zone.o, ggc-page.o): Added dependency on plugin.h. (plugin.o): Added dependency on ggc.h... git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@147878 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 40 ++++++++++ gcc/Makefile.in | 11 +-- gcc/doc/plugins.texi | 77 ++++++++++++++++++- gcc/gcc-plugin.h | 14 +++- gcc/ggc-common.c | 49 +++++++++++- gcc/ggc-page.c | 5 ++ gcc/ggc-zone.c | 5 ++ gcc/ggc.h | 9 ++- gcc/plugin.c | 19 +++++ gcc/testsuite/gcc.dg/plugin/ggcplug-test-1.c | 12 +++ gcc/testsuite/gcc.dg/plugin/ggcplug.c | 109 +++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/plugin/plugin.exp | 4 +- 12 files changed, 341 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/plugin/ggcplug-test-1.c create mode 100644 gcc/testsuite/gcc.dg/plugin/ggcplug.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c5317626261..3528121988c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,43 @@ + +2009-05-26 Basile Starynkevitch + + * doc/plugins.texi + (Loading plugins): typo. + (Plugin callbacks): Documented PLUGIN_INFO, PLUGIN_GGC_START, + PLUGIN_GGC_MARKING, PLUGIN_GGC_END, PLUGIN_REGISTER_GGC_ROOTS. + (Interacting with the GCC Garbage Collector): Added new section. + (Giving information about a plugin): Added new section for + PLUGIN_INFO. + * testsuite/gcc.dg/plugin/plugin.exp: Added ggcplug.c test plugin + with ggcplug-test-1.c for testing PLUGIN_GGC_MARKING etc... + * testsuite/gcc.dg/plugin/ggcplug-test-1.c: Added new file. + * testsuite/gcc.dg/plugin/ggcplug.c: Added new file. + * ggc.h (ggc_register_root_tab): Added declaration. + * gcc-plugin.h (PLUGIN_GGC_START, PLUGIN_GGC_MARKING) + (PLUGIN_GGC_END, PLUGIN_REGISTER_GGC_ROOTS): Added new events. + (register_callback): Improved comment in declaration. + * ggc-common.c (const_ggc_root_tab_t) Added new typedef for + vectors. + (extra_root_vec) Added static variable for dynamic roots + registration. + (ggc_register_root_tab) Added new routine. + (ggc_mark_roots) Added iteration inside extra_root_vec, and invoke + PLUGIN_GGC_MARKING event. + * ggc-zone.c: Include plugin.h. + (ggc_collect): Invoke PLUGIN_GGC_START & PLUGIN_GGC_END events. + * ggc-page.c: Include plugin.h. + (ggc_collect): Invoke PLUGIN_GGC_START & PLUGIN_GGC_END events. + * plugin.c (plugin_event_name): added names of PLUGIN_GGC_START, + PLUGIN_GGC_MARKING, PLUGIN_GGC_END, PLUGIN_REGISTER_GGC_ROOTS + (register_callback): check lack of callbacks for + pseudo-events. Added handling of PLUGIN_REGISTER_GGC_ROOTS, + PLUGIN_GGC_START, PLUGIN_GGC_MARKING, PLUGIN_GGC_END. + (invoke_plugin_callbacks): Handle PLUGIN_GGC_START, + PLUGIN_GGC_MARKING, PLUGIN_GGC_END, PLUGIN_REGISTER_GGC_ROOTS. + * Makefile.in (ggc-common.o, ggc-zone.o, ggc-page.o): Added + dependency on plugin.h. + (plugin.o): Added dependency on ggc.h... + 2009-05-26 Richard Guenther PR middle-end/40248 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index dad6fba41ff..33b02032b8e 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2046,15 +2046,16 @@ gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(CPP_ID_DATA_H) tree-chrec.h $(CFGLAYOUT_H) $(EXCEPT_H) output.h \ $(CFGLOOP_H) -ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GGC_H) \ - $(HASHTAB_H) $(TOPLEV_H) $(PARAMS_H) hosthooks.h $(HOSTHOOKS_DEF_H) +ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ + $(GGC_H) $(HASHTAB_H) $(TOPLEV_H) $(PARAMS_H) hosthooks.h \ + $(HOSTHOOKS_DEF_H) vec.h plugin.h ggc-page.o: ggc-page.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \ - $(FLAGS_H) $(TOPLEV_H) $(GGC_H) $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H) $(TREE_FLOW_H) + $(FLAGS_H) $(TOPLEV_H) $(GGC_H) $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H) $(TREE_FLOW_H) plugin.h ggc-zone.o: ggc-zone.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) $(TOPLEV_H) $(GGC_H) $(TIMEVAR_H) $(TM_P_H) \ - $(PARAMS_H) $(BITMAP_H) $(VARRAY_H) + $(PARAMS_H) $(BITMAP_H) $(VARRAY_H) plugin.h ggc-none.o: ggc-none.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GGC_H) \ $(BCONFIG_H) @@ -2502,7 +2503,7 @@ passes.o : passes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ gt-passes.h $(DF_H) $(PREDICT_H) plugin.o : plugin.c $(PLUGIN_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \ - $(TOPLEV_H) $(TREE_H) $(TREE_PASS_H) intl.h $(PLUGIN_VERSION_H) + $(TOPLEV_H) $(TREE_H) $(TREE_PASS_H) intl.h $(PLUGIN_VERSION_H) $(GGC_H) main.o : main.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TOPLEV_H) diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi index cf5d2af1221..7f2f5a510f3 100644 --- a/gcc/doc/plugins.texi +++ b/gcc/doc/plugins.texi @@ -9,7 +9,7 @@ @section Loading Plugins -Plugins are supported on platforms that support @option{-ld +Plugins are supported on platforms that support @option{-ldl -rdynamic}. They are loaded by the compiler using @code{dlopen} and invoked at pre-determined locations in the compilation process. @@ -65,6 +65,25 @@ struct plugin_name_args If initialization fails, @code{plugin_init} must return a non-zero value. Otherwise, it should return 0. +The version of the GCC compiler loading the plugin is described by the +following structure: + +@smallexample +struct plugin_gcc_version +@{ + const char *basever; + const char *datestamp; + const char *devphase; + const char *revision; + const char *configuration_arguments; +@}; +@end smallexample + +The function @code{plugin_default_version_check} takes two pointers to +such structure and compare them field by field. It can be used by the +plugin's @code{plugin_init} function. + + @subsection Plugin callbacks Callback functions have the following prototype: @@ -87,13 +106,20 @@ enum plugin_event PLUGIN_FINISH_UNIT, /* Useful for summary processing. */ PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE. */ PLUGIN_FINISH, /* Called before GCC exits. */ + PLUGIN_INFO, /* Information about the plugin. */ + PLUGIN_GGC_START, /* Called at start of GCC Garbage Collection. */ + PLUGIN_GGC_MARKING, /* Extend the GGC marking. */ + PLUGIN_GGC_END, /* Called at end of GGC. */ + PLUGIN_REGISTER_GGC_ROOTS, /* Register an extra GGC root table. */ PLUGIN_ATTRIBUTES, /* Called during attribute registration */ PLUGIN_EVENT_LAST /* Dummy event used for indexing callback array. */ @}; @end smallexample -To register a callback, the plugin calls @code{register_callback} with the arguments: + +To register a callback, the plugin calls @code{register_callback} with +the arguments: @itemize @item @code{char *name}: Plugin name. @@ -102,6 +128,9 @@ To register a callback, the plugin calls @code{register_callback} with the argum @item @code{void *user_data}: Pointer to plugin-specific data. @end itemize +For the PLUGIN_PASS_MANAGER_SETUP, PLUGIN_INFO, and +PLUGIN_REGISTER_GGC_ROOTS pseudo-events the @code{callback} should be +null, and the @code{user_data} is specific. @section Interacting with the pass manager @@ -153,6 +182,50 @@ plugin_init (struct plugin_name_args *plugin_info, ... @} @end smallexample + + +@section Interacting with the GCC Garbage Collector + +Some plugins may want to be informed when GGC (the GCC Garbage +Collector) is running. They can register callbacks for the +@code{PLUGIN_GGC_START} and @code{PLUGIN_GGC_END} events (for which +the callback is called with a null @code{gcc_data}) to be notified of +the start or end of the GCC garbage collection. + +Some plugins may need to have GGC mark additional data. This can be +done by registering a callback (called with a null @code{gcc_data}) +for the @code{PLUGIN_GGC_MARKING} event. Such callbacks can call the +@code{ggc_set_mark} routine, preferably thru the @code{ggc_mark} macro +(and conversly, these routines should usually not be used in plugins +outside of the @code{PLUGIN_GGC_MARKING} event). + +Some plugins may need to add extra GGC root tables, e.g. to handle +their own @code{GTY}-ed data. This can be done with the +@code{PLUGIN_REGISTER_GGC_ROOTS} pseudo-event with a null callback and the +extra root table as @code{user_data}. + +You should understand the details of memory management inside GCC +before using @code{PLUGIN_GGC_MARKING} or +@code{PLUGIN_REGISTER_GGC_ROOTS}. + + +@section Giving information about a plugin + +A plugin should give some information to the user about itself. This +uses the following structure: + +@smallexample +struct plugin_info +@{ + const char *version; + const char *help; +@}; +@end smallexample + +Such a structure is passed as the @code{user_data} by the plugin's +init routine using @code{register_callback} with the +@code{PLUGIN_INFO} pseudo-event and a null callback. + @section Registering custom attributes For analysis purposes it is useful to be able to add custom attributes. diff --git a/gcc/gcc-plugin.h b/gcc/gcc-plugin.h index e788eb731bb..2567bf730d2 100644 --- a/gcc/gcc-plugin.h +++ b/gcc/gcc-plugin.h @@ -28,7 +28,11 @@ enum plugin_event PLUGIN_FINISH_UNIT, /* Useful for summary processing. */ PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE. */ PLUGIN_FINISH, /* Called before GCC exits. */ - PLUGIN_INFO, /* Information about the plugin */ + PLUGIN_INFO, /* Information about the plugin. */ + PLUGIN_GGC_START, /* Called at start of GCC Garbage Collection. */ + PLUGIN_GGC_MARKING, /* Extend the GGC marking. */ + PLUGIN_GGC_END, /* Called at end of GGC. */ + PLUGIN_REGISTER_GGC_ROOTS, /* Register an extra GGC root table. */ PLUGIN_ATTRIBUTES, /* Called during attribute registration. */ PLUGIN_EVENT_LAST /* Dummy event used for indexing callback array. */ @@ -128,7 +132,13 @@ typedef void (*plugin_callback_func) (void *gcc_data, void *user_data); PLUGIN_NAME - display name for this plugin EVENT - which event the callback is for CALLBACK - the callback to be called at the event - USER_DATA - plugin-provided data */ + USER_DATA - plugin-provided data. +*/ + +/* This is also called without a callback routine for the + PLUGIN_PASS_MANAGER_SETUP, PLUGIN_INFO, PLUGIN_REGISTER_GGC_ROOTS + pseudo-events, with a specific user_data. + */ extern void register_callback (const char *plugin_name, enum plugin_event event, diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c index b6b9e1e3400..2499ff51cd7 100644 --- a/gcc/ggc-common.c +++ b/gcc/ggc-common.c @@ -30,6 +30,8 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "hosthooks.h" #include "hosthooks-def.h" +#include "plugin.h" +#include "vec.h" #ifdef HAVE_SYS_RESOURCE_H # include @@ -86,6 +88,34 @@ ggc_htab_delete (void **slot, void *info) return 1; } + +/* This extra vector of dynamically registered root_tab-s is used by + ggc_mark_roots and gives the ability to dynamically add new GGC root + tables, for instance from some plugins; this vector is a heap one + [since it is used by GGC internally!] */ +typedef const struct ggc_root_tab* const_ggc_root_tab_t; +DEF_VEC_P(const_ggc_root_tab_t); +DEF_VEC_ALLOC_P(const_ggc_root_tab_t, heap); +static VEC(const_ggc_root_tab_t, heap) *extra_root_vec; + + +/* Dynamically register a new GGC root table RT. This is useful for + plugins. */ + +void +ggc_register_root_tab (const struct ggc_root_tab* rt) +{ + if (!rt) + return; + if (!extra_root_vec) + { + int vlen = 32; + extra_root_vec = VEC_alloc (const_ggc_root_tab_t, heap, vlen); + } + VEC_safe_push (const_ggc_root_tab_t, heap, extra_root_vec, rt); +} + + /* Iterate through all registered roots and mark each element. */ void @@ -104,7 +134,21 @@ ggc_mark_roots (void) for (rt = gt_ggc_rtab; *rt; rt++) for (rti = *rt; rti->base != NULL; rti++) for (i = 0; i < rti->nelt; i++) - (*rti->cb)(*(void **)((char *)rti->base + rti->stride * i)); + (*rti->cb) (*(void **)((char *)rti->base + rti->stride * i)); + + if (extra_root_vec + && VEC_length(const_ggc_root_tab_t,extra_root_vec) > 0) + { + const_ggc_root_tab_t rtp = NULL; + for (i=0; + VEC_iterate(const_ggc_root_tab_t, extra_root_vec, i, rtp); + i++) + { + for (rti = rtp; rti->base != NULL; rti++) + for (i = 0; i < rti->nelt; i++) + (*rti->cb) (*(void **) ((char *)rti->base + rti->stride * i)); + } + } if (ggc_protect_identifiers) ggc_mark_stringpool (); @@ -123,6 +167,9 @@ ggc_mark_roots (void) if (! ggc_protect_identifiers) ggc_purge_stringpool (); + + /* Some plugins may call ggc_set_mark from here. */ + invoke_plugin_callbacks (PLUGIN_GGC_MARKING, NULL); } /* Allocate a block of memory, then clear it. */ diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c index 41cbd44c585..4f872b294f1 100644 --- a/gcc/ggc-page.c +++ b/gcc/ggc-page.c @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see #include "timevar.h" #include "params.h" #include "tree-flow.h" +#include "plugin.h" /* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a file open. Prefer either to valloc. */ @@ -1937,6 +1938,8 @@ ggc_collect (void) /* Indicate that we've seen collections at this context depth. */ G.context_depth_collections = ((unsigned long)1 << (G.context_depth + 1)) - 1; + invoke_plugin_callbacks (PLUGIN_GGC_START, NULL); + clear_marks (); ggc_mark_roots (); #ifdef GATHER_STATISTICS @@ -1948,6 +1951,8 @@ ggc_collect (void) G.allocated_last_gc = G.allocated; + invoke_plugin_callbacks (PLUGIN_GGC_END, NULL); + timevar_pop (TV_GC); if (!quiet_flag) diff --git a/gcc/ggc-zone.c b/gcc/ggc-zone.c index 5031a01b404..442c80e6713 100644 --- a/gcc/ggc-zone.c +++ b/gcc/ggc-zone.c @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "timevar.h" #include "params.h" #include "bitmap.h" +#include "plugin.h" /* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a file open. Prefer either to valloc. */ @@ -2029,6 +2030,8 @@ ggc_collect (void) } } + invoke_plugin_callbacks (PLUGIN_GGC_START, NULL); + /* Start by possibly collecting the main zone. */ main_zone.was_collected = false; marked |= ggc_collect_1 (&main_zone, true); @@ -2093,6 +2096,8 @@ ggc_collect (void) } } + invoke_plugin_callbacks (PLUGIN_GGC_END, NULL); + timevar_pop (TV_GC); } diff --git a/gcc/ggc.h b/gcc/ggc.h index 5b2743b3386..e3471e45353 100644 --- a/gcc/ggc.h +++ b/gcc/ggc.h @@ -1,6 +1,7 @@ /* Garbage collection for the GNU compiler. - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 - Free Software Foundation, Inc. + + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, + 2008, 2009 Free Software Foundation, Inc. This file is part of GCC. @@ -270,6 +271,10 @@ extern const char *ggc_alloc_string (const char *contents, int length); function is called, not during allocations. */ extern void ggc_collect (void); +/* Register an additional root table. This can be useful for some + plugins. Does nothing if the passed pointer is null. */ +extern void ggc_register_root_tab (const struct ggc_root_tab *); + /* Return the number of bytes allocated at the indicated address. */ extern size_t ggc_get_size (const void *); diff --git a/gcc/plugin.c b/gcc/plugin.c index 6cee526cf76..0b5515e4907 100644 --- a/gcc/plugin.c +++ b/gcc/plugin.c @@ -38,6 +38,8 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "plugin.h" #include "timevar.h" +#include "ggc.h" + #ifdef ENABLE_PLUGIN #include "plugin-version.h" #endif @@ -51,6 +53,10 @@ const char *plugin_event_name[] = "PLUGIN_CXX_CP_PRE_GENERICIZE", "PLUGIN_FINISH", "PLUGIN_INFO", + "PLUGIN_GGC_START", + "PLUGIN_GGC_MARKING", + "PLUGIN_GGC_END", + "PLUGIN_REGISTER_GGC_ROOTS", "PLUGIN_EVENT_LAST" }; @@ -472,14 +478,23 @@ register_callback (const char *plugin_name, switch (event) { case PLUGIN_PASS_MANAGER_SETUP: + gcc_assert (!callback); register_pass (plugin_name, (struct plugin_pass *) user_data); break; case PLUGIN_INFO: + gcc_assert (!callback); register_plugin_info (plugin_name, (struct plugin_info *) user_data); break; + case PLUGIN_REGISTER_GGC_ROOTS: + gcc_assert (!callback); + ggc_register_root_tab ((const struct ggc_root_tab*) user_data); + break; case PLUGIN_FINISH_TYPE: case PLUGIN_FINISH_UNIT: case PLUGIN_CXX_CP_PRE_GENERICIZE: + case PLUGIN_GGC_START: + case PLUGIN_GGC_MARKING: + case PLUGIN_GGC_END: case PLUGIN_ATTRIBUTES: case PLUGIN_FINISH: { @@ -524,6 +539,9 @@ invoke_plugin_callbacks (enum plugin_event event, void *gcc_data) case PLUGIN_CXX_CP_PRE_GENERICIZE: case PLUGIN_ATTRIBUTES: case PLUGIN_FINISH: + case PLUGIN_GGC_START: + case PLUGIN_GGC_MARKING: + case PLUGIN_GGC_END: { /* Iterate over every callback registered with this event and call it. */ @@ -535,6 +553,7 @@ invoke_plugin_callbacks (enum plugin_event event, void *gcc_data) case PLUGIN_PASS_MANAGER_SETUP: case PLUGIN_EVENT_LAST: + case PLUGIN_REGISTER_GGC_ROOTS: default: gcc_assert (false); } diff --git a/gcc/testsuite/gcc.dg/plugin/ggcplug-test-1.c b/gcc/testsuite/gcc.dg/plugin/ggcplug-test-1.c new file mode 100644 index 00000000000..74e68bb82ec --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/ggcplug-test-1.c @@ -0,0 +1,12 @@ +/* Test the ggcplug plugin. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +int main() +{ + int i=0, j=0; + for (i= 0; i<1000; i++) + if (i%8 == 0) + j++; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/plugin/ggcplug.c b/gcc/testsuite/gcc.dg/plugin/ggcplug.c new file mode 100644 index 00000000000..136404ae65f --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/ggcplug.c @@ -0,0 +1,109 @@ +/* This plugin tests the GGC related plugin events. */ +/* { dg-options "-O" } */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "toplev.h" +#include "basic-block.h" +#include "gimple.h" +#include "tree.h" +#include "tree-pass.h" +#include "intl.h" +#include "gcc-plugin.h" + + +/* The initialization routine exposed to and called by GCC. The spec of this + function is defined in gcc/gcc-plugin.h. + + Note that this function needs to be named exactly "plugin_init". */ + + +/* our callback is the same for all PLUGIN_GGC_START, + PLUGIN_GGC_MARKING, PLUGIN_GGC_END events; it just increments the + user_data which is an int */ +static void increment_callback (void *gcc_data, void *user_data); + +/* our counters are user_data */ +static int our_ggc_start_counter; +static int our_ggc_end_counter; +static int our_ggc_marking_counter; + +/* our empty GGC extra root table */ +static const struct ggc_root_tab our_xtratab[] = { + LAST_GGC_ROOT_TAB +}; + +int +plugin_init ((struct plugin_name_args *plugin_info, + struct plugin_gcc_version *version) +{ + const char *plugin_name = plugin_info->base_name; + int argc = plugin_info->argc; + struct plugin_argument *argv = plugin_info->argv; + if (!plugin_default_version_check (version, version)) + return 1; + /* Process the plugin arguments. This plugin takes the following arguments: + count-ggc-start count-ggc-end count-ggc-mark */ + for (i = 0; i < argc; ++i) + { + if (!strcmp (argv[i].key, "count-ggc-start")) + { + if (argv[i].value) + warning (0, G_ ("option '-fplugin-arg-%s-count-ggc-start=%s'" + " ignored (superfluous '=%s')"), + plugin_name, argv[i].value, argv[i].value); + else + register_callback ("ggcplug", + PLUGIN_GGC_START, + increment_callback, + (void *) &our_ggc_start_counter); + } + else if (!strcmp (argv[i].key, "count-ggc-end")) + { + if (argv[i].value) + warning (0, G_ ("option '-fplugin-arg-%s-count-ggc-end=%s'" + " ignored (superfluous '=%s')"), + plugin_name, argv[i].value, argv[i].value); + else + register_callback ("ggcplug", + PLUGIN_GGC_END, + increment_callback, + (void *) &our_ggc_end_counter); + } + else if (!strcmp (argv[i].key, "count-ggc-mark")) + { + if (argv[i].value) + warning (0, G_ ("option '-fplugin-arg-%s-count-ggc-mark=%s'" + " ignored (superfluous '=%s')"), + plugin_name, argv[i].value, argv[i].value); + else + register_callback ("ggcplug", + PLUGIN_GGC_MARKING, + increment_callback, + (void *) &our_ggc_marking_counter); + } + else if (!strcmp (argv[i].key, "test-extra-root")) + { + if (argv[i].value) + warning (0, G_ ("option '-fplugin-arg-%s-test-extra-root=%s'" + " ignored (superfluous '=%s')"), + plugin_name, argv[i].value, argv[i].value); + else + register_callback ("ggcplug", + PLUGIN_REGISTER_GGC_ROOTS, + NULL, + (void *) our_xtratab); + } + } +} + +static void +increment_callback (void *gcc_data, void *user_data) +{ + int *usercountptr = (int *) user_data; + gcc_assert (!gcc_data); + gcc_assert (user_data); + (*usercountptr)++; +} diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp index 93c0c5cb848..63ee74427f6 100644 --- a/gcc/testsuite/gcc.dg/plugin/plugin.exp +++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp @@ -47,7 +47,9 @@ load_lib plugin-support.exp # Specify the plugin source file and the associated test files in a list. # plugin_test_list={ {plugin1 test1 test2 ...} {plugin2 test1 ...} ... } set plugin_test_list [list \ - { selfassign.c self-assign-test-1.c self-assign-test-2.c } ] + { selfassign.c self-assign-test-1.c self-assign-test-2.c } \ + { ggcplug.c ggcplug-test-1.c } \ +] foreach plugin_test $plugin_test_list { # Replace each source file with its full-path name -- 2.11.0