diff options
author | Razya Ladelsky <razya@il.ibm.com> | 2009-06-01 17:35:51 +0000 |
---|---|---|
committer | Razya Ladelsky <razya@il.ibm.com> | 2009-06-01 17:35:51 +0000 |
commit | 54a26bd853030cd72fcdca4f242b99ac7dffe504 (patch) | |
tree | 2159c0a54e51ccc25b18dbd3478f342b1f9228b6 | |
parent | 26fccfee1b40551c5afb470eff0dbdf4831fab9c (diff) |
New files - support for ICI
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/milepost-branch@148059 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/events.c | 294 | ||||
-rw-r--r-- | gcc/feature-internal.h | 65 | ||||
-rw-r--r-- | gcc/feature-list.c | 515 | ||||
-rw-r--r-- | gcc/feature.c | 210 | ||||
-rw-r--r-- | gcc/feature.h | 44 | ||||
-rw-r--r-- | gcc/highlev-plugin-internal.h | 53 | ||||
-rw-r--r-- | gcc/highlev-plugin.h | 51 | ||||
-rw-r--r-- | gcc/ic-interface.h | 33 | ||||
-rw-r--r-- | gcc/ici-legacy.h | 24 | ||||
-rw-r--r-- | gcc/pass-manager.c | 130 | ||||
-rw-r--r-- | gcc/pass-manager.h | 38 | ||||
-rw-r--r-- | gcc/plugin-loader.c | 140 |
12 files changed, 1597 insertions, 0 deletions
diff --git a/gcc/events.c b/gcc/events.c new file mode 100644 index 00000000000..eb04f94d0e4 --- /dev/null +++ b/gcc/events.c @@ -0,0 +1,294 @@ +/* High-level event callback mechanism for GCC plugins. + Copyright (C) 2009 Free Software Foundation, Inc. + + Contributed by Inria. + + Authors: Grigori Fursin <grigori.fursin@inria.fr>, Cupertino Miranda + <cupertinomiranda@gmail.com>, Zbigniew Chamski <zbigniew.chamski@gmail.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "hashtab.h" +#include "toplev.h" +#include "errors.h" + +#include "highlev-plugin-internal.h" + +/* Event structure. */ +struct plugin_event { + const char *name; /* Name for the event */ + event_callback_t run; /* Callback function */ +}; + + +/* Parameter structure. */ +struct event_parameter { + const char *name; /* Name for the parameter */ + void *value; /* Pointer to data */ +}; + + +static htab_t events_hash = NULL; +static htab_t parameters_hash = NULL; + + +/* Hash dependent functions. */ +static hashval_t +string_htab_hash (const void *x) +{ + const char *p = *((const char * const *) x); + + if (p != NULL) + return htab_hash_string (p); + + return 0; +} + + +static int +string_htab_eq (const void *x, const void *y) +{ + const char *s1 = *((const char * const *) x); + const char *s2 = *((const char * const *) y); + + return !strcmp (s1, s2); +} + + +static void +parameter_htab_del (void *p) +{ + struct parameter *param = (struct parameter *) p; + free (param); +} + + +/* Register a new event into hash table. */ +void +register_plugin_event (const char *event_name, event_callback_t func) +{ + void **slot; + struct plugin_event *ev = XCNEW (struct plugin_event); + + ev->name = event_name; + ev->run = func; + + if (ev->name == NULL) + internal_error ("Event cannot be registered with NULL name string\n"); + + if (events_hash == NULL) + events_hash = htab_create_alloc (150, string_htab_hash, + string_htab_eq, NULL, xcalloc, free); + + if (events_hash != NULL) + { + slot = htab_find_slot (events_hash, ev, INSERT); + *slot = (void *) ev; + } +} + + +/* Used in GCC code to throw an event. + * If event is currently defined, its callback (if any) is executed. + * Return values: + * PLUGEVT_SUCCESS (== 0) if at least one event callback was executed, + * PLUGEVT_NO_EVENTS if no events whatsoever have been defined so far, + * PLUGEVT_NO_SUCH_EVENT if the event was not found, + * PLUGEVT_NO_CALLBACK if the callback list was empty. */ +int +call_plugin_event (const char *event_name) +{ + struct plugin_event tmp_event; + struct plugin_event *ev; + + tmp_event.name = event_name; + + /* no event hash means no events defined */ + if (events_hash == NULL) return PLUGEVT_NO_EVENTS; + + ev = (struct plugin_event *) htab_find (events_hash, &tmp_event); + + /* report the event-not-found condition */ + if (!ev) return PLUGEVT_NO_SUCH_EVENT; + + /* report the absence of callbacks */ + if (ev->run == NULL) return PLUGEVT_NO_CALLBACK; + + /* If all is OK, run the callback */ + ev->run (); + return PLUGEVT_SUCCESS; +} + + +/* Get list of names of all registered events. + * Traverse the hash table collecting the names of entries. + */ +static int +add_event_name (void **slot, void *data) +{ + const char ***crnt_name_ptr = (const char ***) data; + struct plugin_event *event = *(struct plugin_event **) slot; + + /* store the name of the current event at the corresponding + location */ + **crnt_name_ptr = event->name; + + /* advance the current location */ + (*crnt_name_ptr)++; + + /* return "OK" */ + return 1; +} + +/* return the array of all event names, terminated by NULL */ +const char ** +list_plugin_events (void) +{ + size_t num_events = htab_elements (events_hash); + + /* allocate space for all names + the terminating NULL */ + const char **all_events = (const char **) + xmalloc (sizeof (const char *) * (num_events + 1)); + + const char ***data = &all_events; /* data ptr for mapped function */ + const char **first_event = all_events; /* keep track of actual start */ + + /* mark end-of-array */ + all_events[num_events] = NULL; + + /* collect all event names */ + htab_traverse_noresize (events_hash, add_event_name, data); + + /* use the stored start-of-array - all_events has changed during + htab_traverse_noresize */ + return first_event; +} + + +/* Register parameter. + * Insert parameter into hash table. Allocates hash table + * if needed. */ +void +register_event_parameter (const char *name, void* value) +{ + void **slot; + struct event_parameter *param = XCNEW (struct event_parameter); + + param->name = name; + param->value = value; + + if (param->name == NULL || !strcmp ("", param->name)) + internal_error ("Parameter cannot be registered with NULL name string\n"); + + if (parameters_hash == NULL) + parameters_hash = + htab_create_alloc (150, string_htab_hash, + string_htab_eq, parameter_htab_del, xcalloc, free); + + if (parameters_hash != NULL) + { + slot = htab_find_slot (parameters_hash, param, INSERT); + *slot = (void *) param; + } +} + + +/* Unregister parameter. Remove it from hash table. */ +void +unregister_event_parameter (const char *name) +{ + struct event_parameter param; + param.name = name; + + if (parameters_hash == NULL) + internal_error ("Parameter hash not initialized.\n"); + + if (parameters_hash != NULL) + htab_remove_elt (parameters_hash, ¶m); +} + + +/* Get parameter pointer to data. + * Used by plugin to get pointer to data of the parameter <name>. */ +void * +get_event_parameter (const char *name) +{ + struct event_parameter tmp_param, *param; + tmp_param.name = name; + + if (parameters_hash == NULL) + internal_error ("Parameter hash not initialized.\n"); + + if (parameters_hash != NULL) + { + param = (struct event_parameter *) + htab_find (parameters_hash, &tmp_param); + + if (param != NULL && param->value != NULL) + return param->value; + } + return NULL; +} + + +/* Get list of names of all registered ICI parameters. + * Traverse the hash table collecting the names of entries. + */ +static int +add_parameter_name (void **slot, void *data) +{ + const char ***crnt_name_ptr = (const char ***) data; + struct event_parameter *parameter = *(struct event_parameter **) slot; + + /* store the name of the current parameter at the corresponding + location */ + **crnt_name_ptr = parameter->name; + + /* advance the current location */ + (*crnt_name_ptr)++; + + /* return "OK" */ + return 1; +} + + +/* return the array of all parameter names, terminated by NULL */ +const char ** +list_event_parameters (void) +{ + size_t num_parameters = htab_elements (parameters_hash); + + /* allocate space for all names + the terminating NULL */ + const char **all_parameters = (const char **) + xmalloc (sizeof (const char *) * (num_parameters+1)); + + const char ***data = &all_parameters; /* data ptr for mapped function */ + const char **first_parameter = all_parameters; /* keep track of actual start */ + + /* mark end-of-array */ + all_parameters[num_parameters] = NULL; + + /* collect all parameter names */ + htab_traverse_noresize (parameters_hash, add_parameter_name, data); + + /* use the stored start-of-array - all_parameters has changed during + htab_traverse_noresize */ + return first_parameter; +} diff --git a/gcc/feature-internal.h b/gcc/feature-internal.h new file mode 100644 index 00000000000..b2886c5ddd2 --- /dev/null +++ b/gcc/feature-internal.h @@ -0,0 +1,65 @@ +/* Compiler-side interface to global compiler state for GCC plugins. + Copyright (C) 2009 Free Software Foundation, Inc. + + Contributed by Inria. + + Authors: Grigori Fursin <grigori.fursin@inria.fr>, Cupertino Miranda + <cupertinomiranda@gmail.com>, Zbigniew Chamski <zbigniew.chamski@gmail.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef FEATURE_INTERNAL_H +#define FEATURE_INTERNAL_H + +/* Compiler feature: a well-defined compiler property (config or state + information) that can be modified at runtime in a limited and controlled + fashion. */ +struct feature { + const char *name; /* Feature name */ + void *data; /* Data for a static/memoized feature */ + long int data_size; /* size of the data - for copying etc. */ + const void * (*callback) (void); /* Callback to dynamically extract + feature value */ + const void * (*get_subfeature) (const char *name); + /* callback to dynamically get values of + subfeatures */ + void * (*set_subfeature) (const char *name, void *value); + /* callback to set values of subfeatures */ +}; + +/* Manipulation of feature directory (table) */ +extern void register_feature (const struct feature *feature); +extern struct feature *find_feature (const char *feature_name); +extern void init_features (void); + +/* Access to values of either features or elements of feature sets */ +extern const void *get_feature (const char *feature_name); +extern const void *get_subfeature (const char *feature_name, + const char *subfeat_name); +extern void *set_subfeature (const char *feature_name, + const char *subfeat_name, void *value); + +/* Extract the size of features and feature sets */ +extern int get_feature_size (const char *feature_name); +extern int get_num_features (int type); +extern int get_num_subfeatures (const char *feat_name, int type); + +/* List of all known features, or all known elements of a feature set */ +extern const char **list_features (void); +extern const char **list_subfeatures (const char *feat_name, int type); + +#endif /* FEATURE_INTERNAL_H */ diff --git a/gcc/feature-list.c b/gcc/feature-list.c new file mode 100644 index 00000000000..5e72d2f60ff --- /dev/null +++ b/gcc/feature-list.c @@ -0,0 +1,515 @@ +/* High-level access points to global compiler state in GCC. + Copyright (C) 2009 Free Software Foundation, Inc. + + Contributed by Inria. + + Authors: Grigori Fursin <grigori.fursin@inria.fr>, Cupertino Miranda + <cupertinomiranda@gmail.com>, Zbigniew Chamski <zbigniew.chamski@gmail.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "feature-internal.h" + +#include "config.h" +#include "system.h" + +#include "coretypes.h" +#include "tm.h" +#include "line-map.h" +#include "input.h" +#include "tree.h" +#include "basic-block.h" +#include "tree-inline.h" +#include "tree-flow.h" +#include "tree-pass.h" + +#include "version.h" +#include "opts.h" +#include "params.h" +#include "function.h" +#include "input.h" + +/* FORNOW: ZC: make declarations from "passes.c" visible here */ +/* A map from static pass dump id to optimization pass. */ +extern struct opt_pass **passes_by_id; +extern int passes_by_id_size; + + +/* FICI0: "function_name": get name of current function if the + current function is defined, and return NULL otherwise. */ +static const void *function_name (void) +{ + if (cfun) + return (const void *) current_function_name(); + else + return NULL; +} + +const struct feature feature_function_name = { + "function_name", /* name */ + NULL, /* data */ + 0, /* no data */ + &function_name, /* callback */ + NULL, /* no get subfeature callback */ + NULL /* no set subfeature callback */ +}; + +/* FICI0: "first_pass": get name of the first pass of the compiler */ +struct opt_pass *_pass_parents[] = { NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL}; +int _pass_parents_count = 0; +struct opt_pass *_current_pass = NULL; + +static const void *first_pass (void) +{ + _current_pass = all_passes; + return (const void *) _current_pass->name; +} + +const struct feature feature_first_pass = { + "first_pass", /* name */ + NULL, /* data */ + 0, /* no data */ + &first_pass, /* callback */ + NULL, /* no get subfeature callback */ + NULL /* no set subfeature callback */ +}; + +/* FICI0: "next_pass": get the name of the next pass to be executed */ +static const void *next_pass (void) +{ + if(_current_pass == NULL) + { + return (const void *) NULL; + } + + if(_current_pass->sub != NULL) + { + /* Insert _current_pass->next in parents list */ + _pass_parents[_pass_parents_count++] = _current_pass->next; + _current_pass = _current_pass->sub; + + return (const void *) _current_pass->name; + } + + if(_current_pass->next == NULL) + { + while(_pass_parents[_pass_parents_count] == NULL + && _pass_parents_count > 0) + _pass_parents_count--; + + _current_pass = _pass_parents[_pass_parents_count]; + /* Delete _current_pass in parents list */ + _pass_parents[_pass_parents_count] = NULL; + + return (const void *) (_current_pass != NULL ? + _current_pass->name : + NULL); + } + + _current_pass = _current_pass->next; + return (const void *) _current_pass->name; +} + +const struct feature feature_next_pass = { + "next_pass", /* name */ + NULL, /* data */ + 0, /* data size */ + &next_pass, /* callback */ + NULL, /* no get subfeature callback */ + NULL /* no set subfeature callback */ +}; + + +/* FICI0: compiler_all_passes */ +/* list of all passes requires names or address/sourceloc of each instance */ +static const void * +all_gcc_pass_names (void); /* forward declaration - code references feature */ + +struct feature feature_named_passes = { + "named_passes", /* name */ + NULL, /* initial data */ + 0, /* initially no data */ + &all_gcc_pass_names, /* callback */ + NULL, /* no get subfeature callback */ + NULL /* no set subfeature callback */ +}; + + +static const void * +all_gcc_pass_names (void) +{ + int i; + char *new_name; + const char **pass_name = + (const char **) xmalloc (passes_by_id_size * sizeof (const char *)); + + for (i = 0; i < passes_by_id_size; i++) + { + if (passes_by_id[i] == NULL) + pass_name[i] = "<no pass defined>"; + else + { + if (passes_by_id[i]->name != NULL) + pass_name[i] = passes_by_id[i]->name; + else + { + /* be defensive - do not allow string overflow */ + gcc_assert (passes_by_id_size < 1000); + new_name = (char *) xmalloc (strlen ("pass_XXX") + 1); + sprintf (new_name, "pass_%03d", i); + /* store the new name in the option as well */ + /* to keep memory clean when freeing a pass, any non-NULL + pass name of the format "pass_%03d" should be freed as + well, because it was dynamically allocated. */ + pass_name[i] = passes_by_id[i]->name = (const char *) new_name; + } + } + } + + /* memoize the result */ + feature_named_passes.data = (void *) pass_name ; + feature_named_passes.data_size = + passes_by_id_size * sizeof (char *); + return (void *) pass_name; +} + + +/* FICI0: get name of the current pass */ +static const void * +get_gcc_pass_name (void) +{ + return (const void *) get_current_pass_name (); +} + + +const struct feature feature_crnt_pass_name = { + "pass_name", /* name */ + NULL, /* data */ + 0, /* no data */ + &get_gcc_pass_name, /* callback */ + NULL, /* no get subfeature callback */ + NULL /* no set subfeature callback */ +}; + + +/* FICI0: "compiler_version": get version string of the compiler */ +static const void * +get_compiler_version_string (void); + + +/* FICI0: query compiler version */ +const struct feature feature_compiler_version = { + "compiler_version", /* GCC version */ + NULL, /* data */ + 0, /* no data */ + get_compiler_version_string, /* data: version_string of GCC */ + NULL, /* no get subfeature callback */ + NULL /* no set subfeature callback */ +}; + + +static const void * +get_compiler_version_string (void) +{ + /* this is the time to memoize the value if necessary */ + return (const void *) version_string; +} + + +/* FICI0: "flags": get the command-line flags of the compiler + * return values: + * - string subfeatures: pointer-to-char corresponding to the string; + * - integer/boolean/bit subfeatures: integer converted to pointer-to-void. + */ +static const void *get_gcc_option_names(void); + +static const void * +get_gcc_option_value (const char *opt) +{ + size_t opt_index; + const struct cl_option *option; + struct cl_option_state state; + bool was_set; + + opt_index = find_opt (opt, -1); + if (opt_index == cl_options_count) + return (const char *) NULL; + + /* at this point, the option is known to exist */ + option = &cl_options[opt_index]; + was_set = get_option_state (opt_index, &state); + + /* check if option is set, and return the value (int or ptr); IMPORANT: + the user has to know how to interpret the value that's returned. */ + if (!was_set) + return (const void *) NULL; + else switch (cl_options[opt_index].var_type) { + case CLVC_STRING: + /* for string options, return actual string */ + return (state.data ? state.data : (const void *) ""); + + case CLVC_BOOLEAN: + case CLVC_EQUAL: + /* booleans and integers are stored by converting them to a 'const + void *'. */ + return state.data; + case CLVC_BIT_CLEAR: + case CLVC_BIT_SET: + /* bits set/cleared: return the char (0 or 1) converted to 'const void *' */ + return (const void *) ((long int) state.ch); + default: + gcc_unreachable (); + } +} + + +/* value is a pointer to the actual value. NULL means no value. + Implementation is based on static unsigned int handle_option in gcc/opts.c +*/ +static void * +set_gcc_option_value (const char *opt __attribute__ ((unused)), + void *value __attribute__ ((unused))) +{ + /* not implemented yet */ + return NULL; +} + + +/* FICI0: "compiler_flags": get list/values of compiler flags. Example: + call 'ici_get_feature ("compiler_params")' to get the list of parameters. + The value returned by this call will be memoized in the 'data' field. + Reset the 'data' field to NULL (and 'data_size' to zero) to force + a recomputation of the list. +*/ +struct feature feature_compiler_flags = { + "compiler_flags", /* name */ + NULL, /* initially NULL to trigger callback, later + stores the memoized result */ + 0, /* no data */ + get_gcc_option_names, /* return list of option names */ + get_gcc_option_value, /* get value of named option */ + set_gcc_option_value /* set value of named option */ +}; + + +static const void *get_gcc_option_names (void) +{ + size_t i; + + const char **option_names = + (const char **) xmalloc (cl_options_count * sizeof (const char *)); + + for (i = 0; i < cl_options_count; i++) + option_names[i] = cl_options[i].opt_text; + + feature_compiler_flags.data = option_names; + feature_compiler_flags.data_size = cl_options_count * sizeof (const char *); + + return (const void *) option_names; +} + + +/* FICI0: "compiler_params": get list/values of compiler parameters. */ + +/* forward declaration - definition follows feature initializer */ +static const void *get_gcc_param_names (void); + + +static const void * +get_gcc_param_value (const char *name) +{ + size_t i; + + /* Scan the parameter table to find a matching entry - from 'set_param_value' */ + for (i = 0; i < num_compiler_params; ++i) + if (strcmp (compiler_params[i].option, name) == 0) + return (void *) ((long int) compiler_params[i].value); + + /* If we didn't find the parameter, return the invalid parameter value */ + return (void *)(-1); +} + +static void *set_gcc_param_value (const char *name, void *value) +{ + size_t i; + + /* Scan the parameter table to find a matching entry - from 'set_param_value' */ + for (i = 0; i < num_compiler_params; ++i) + if (strcmp (compiler_params[i].option, name) == 0) + compiler_params[i].value = (int) ((long int) value); + + /* If we didn't find the parameter, return the invalid parameter value */ + return (void *)(-1); +} + +/* FICI0: "compiler_params": get list/values of compiler parameters. + Call 'ici_get_feature ("compiler_params")' to get the list of parameters. + The value returned by this call will be memoized in the 'data' field. + Reset the 'data' field to NULL (and 'data_size' to zero) to force + a recomputation of the list. +*/ +struct feature feature_compiler_params = { + "compiler_params", /* name */ + NULL, /* initially NULL to trigger callback, later + stores memoized callback result */ + 0, /* no data */ + get_gcc_param_names, /* return list of parameter names */ + get_gcc_param_value, /* get value of named parameter - always an integer */ + set_gcc_param_value /* set value of named parameter */ +}; + + +static const void * +get_gcc_param_names (void) +{ + size_t i; + const char **param_list = + (const char **) xmalloc (num_compiler_params * sizeof (const char *)); + + /* collect all parameter names */ + for (i = 0; i < num_compiler_params; i++) + param_list[i] = compiler_params[i].option; + + /* memoize list in feature descriptor */ + feature_compiler_params.data = param_list; + feature_compiler_params.data_size = + num_compiler_params * sizeof (const char *); + + return (void *) param_list; +} + + +/* FICI3: Get cfun source code information: + - declaration line + - declaration filename + - definition start/end line + - definition filename +*/ + +static const void * +get_cfun_decl_line (void) +{ + if (!cfun) + return (const void *) -1; + + return (const void *) ((long int) LOCATION_LINE (DECL_SOURCE_LOCATION (cfun->decl))); +} + +static const void * +get_cfun_decl_filename (void) +{ + if (!cfun) + return NULL; + + return (const void *) LOCATION_FILE (DECL_SOURCE_LOCATION (cfun->decl)); +} + +static const void * +get_cfun_def_start_line (void) +{ + if (!cfun) + return (const void *) -1; + + return (const void *) ((long int) LOCATION_LINE (cfun->function_start_locus)); +} + +static const void * +get_cfun_def_end_line (void) +{ + if (!cfun) + return (const void *) -1; + + return (const void *) ((long int) LOCATION_LINE (cfun->function_end_locus)); +} + +static const void * +get_cfun_def_filename (void) +{ + if (!cfun) + return NULL; + + return (const void *) LOCATION_FILE (cfun->function_start_locus); +} + +const struct feature feature_function_start = { + "function_start_line", /* name */ + NULL, /* data */ + 0, /* no data */ + &get_cfun_def_start_line, /* callback */ + NULL, /* no get subfeature callback */ + NULL /* no set subfeature callback */ +}; + +const struct feature feature_function_end = { + "function_end_line", /* name */ + NULL, /* data */ + 0, /* no data */ + &get_cfun_def_end_line, /* callback */ + NULL, /* no get subfeature callback */ + NULL /* no set subfeature callback */ +}; + +const struct feature feature_function_file = { + "function_filename", /* name */ + NULL, /* data */ + 0, /* no data */ + &get_cfun_def_filename, /* callback */ + NULL, /* no get subfeature callback */ + NULL /* no set subfeature callback */ +}; + +const struct feature feature_function_decl_line = { + "function_decl_line", /* name */ + NULL, /* data */ + 0, /* no data */ + &get_cfun_decl_line, /* callback */ + NULL, /* no get subfeature callback */ + NULL /* no set subfeature callback */ +}; + +const struct feature feature_function_decl_file = { + "function_decl_filename", /* name */ + NULL, /* data */ + 0, /* no data */ + &get_cfun_decl_filename, /* callback */ + NULL, /* no get subfeature callback */ + NULL /* no set subfeature callback */ +}; + + +/* FICI0: initialize all known features */ +void init_features (void) +{ + register_feature (&feature_function_name); + register_feature (&feature_crnt_pass_name); + + register_feature (&feature_first_pass); + register_feature (&feature_next_pass); + register_feature (&feature_compiler_version); + + register_feature (&feature_compiler_flags); + register_feature (&feature_compiler_params); + register_feature (&feature_named_passes); + + register_feature (&feature_function_start); + register_feature (&feature_function_end); + register_feature (&feature_function_file); + register_feature (&feature_function_decl_line); + register_feature (&feature_function_decl_file); +} + diff --git a/gcc/feature.c b/gcc/feature.c new file mode 100644 index 00000000000..8d365dc4d74 --- /dev/null +++ b/gcc/feature.c @@ -0,0 +1,210 @@ +/* Features: a high-level mechanism for accessing global compiler state in GCC. + Copyright (C) 2009 Free Software Foundation, Inc. + + Contributed by Inria. + + Authors: Grigori Fursin <grigori.fursin@inria.fr>, Cupertino Miranda + <cupertinomiranda@gmail.com>, Zbigniew Chamski <zbigniew.chamski@gmail.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "hashtab.h" +#include "toplev.h" + +#include "feature-internal.h" + +htab_t features_hash = NULL; + + +/* Hash dependent functions. */ + +static hashval_t +features_htab_hash (const void *x) +{ + const struct feature *p = (const struct feature *) x; + + if (!p) + internal_error ("features_htab_hash: called with NULL feature pointer!"); + + if (p->name != NULL) + return htab_hash_string(p->name); + else + internal_error ("features_htab_hash: NULL-named feature!\n"); +} + + +static int +features_htab_eq (const void *x, const void *y) +{ + const struct feature *p1 = (const struct feature *) x; + const struct feature *p2 = (const struct feature *) y; + + return !strcmp (p1->name, p2->name); +} + + +/* Add feature to hash table. */ +void register_feature (const struct feature *feature) +{ + void const **slot; + + if (!feature) + internal_error ("register_feature() called with NULL feature!\n"); + + if (feature->name == NULL) + internal_error ("register_feature() called with NULL-named feature!\n"); + + if(features_hash == NULL) + features_hash = htab_create_alloc (150, features_htab_hash, + features_htab_eq, NULL, xcalloc, free); + + if(features_hash != NULL) + { + slot = (const void **) htab_find_slot (features_hash, feature, INSERT); + *slot = (const void *) feature; + } +} + + +/* FICI0: ici_find_feature: find the feature with a given name. + * Return values: + * - pointer to 'struct feature' if the named feature was found; + * - NULL if the feature could not be found. + */ +struct feature *find_feature (const char *feature_name) +{ + struct feature tmp_feature; + + tmp_feature.name = feature_name; + + return (struct feature *) htab_find (features_hash, &tmp_feature); +} + + +/* Get pointer to feature with <feature_name>. */ +const void *get_feature (const char *feature_name) +{ + const struct feature *feature; + + feature = find_feature (feature_name); + + if(feature == NULL) + return NULL; + + if(feature->data != NULL) + return (const void *) feature->data; + else if (feature->callback != NULL) + /* Call only non-NULL callbacks */ + return feature->callback (); + else + return NULL; +} + + +/* Return the size of the data associated with feature */ +int get_feature_size (const char *feature_name) +{ + const struct feature *feature; + + feature = find_feature (feature_name); + + if(feature == NULL) + return -1; + + return feature->data_size; +} + + +/* FICI0: get specific sub-feature of a main feature. + * Prerequisites: both feature and subfeature must exist (no diagnostics). + * Return values: + * - string subfeatures: pointer-to-char corresponding to the string; + * - integer/boolean/bit subfeatures: integer converted to pointer-to-void. + */ +const void * +get_subfeature (const char *feature_name, const char *subfeat_name) +{ + const struct feature *feature; + + feature = find_feature (feature_name); + + /* no feature or no subfeature callback: bail out. */ + if (!feature || !feature->get_subfeature) + return NULL; + + return (feature->get_subfeature (subfeat_name)); +} + + +/* FICI0: set sub-feature */ +void *set_subfeature (const char *feature_name, + const char *subfeat_name, + void *subfeat_value) +{ + struct feature *feature = find_feature (feature_name); + + /* no feature or no subfeature callback: bail out. */ + if (!feature || !feature->set_subfeature) return NULL; + + return feature->set_subfeature (subfeat_name, subfeat_value); +} + + +static int +add_feature_name (void **slot, void *data) +{ + const char ***crnt_name_ptr = (const char ***) data; + struct feature *feature = *(struct feature **) slot; + + /* store the name of the current fearute at the corresponding + location */ + **crnt_name_ptr = feature->name; + + /* advance the current location */ + (*crnt_name_ptr)++; + + /* return "OK" */ + return 1; +} + + +/* return the array of all feature names, terminated by NULL */ +const char ** +list_features (void) +{ + size_t num_features = htab_elements (features_hash); + + /* allocate space for all names + the terminating NULL */ + const char **all_features = (const char **) + xmalloc (sizeof (const char *) * (num_features+1)); + + const char ***data = &all_features; /* data ptr for mapped function */ + const char **first_feature = all_features; /* keep track of actual start */ + + /* mark end-of-array */ + all_features[num_features] = NULL; + + /* collect all feature names */ + htab_traverse_noresize (features_hash, add_feature_name, data); + + /* use the stored start-of-array - all_features has changed during + htab_traverse_noresize */ + return first_feature; +} diff --git a/gcc/feature.h b/gcc/feature.h new file mode 100644 index 00000000000..d6b7282d630 --- /dev/null +++ b/gcc/feature.h @@ -0,0 +1,44 @@ +/* Plugin-side interface to global compiler state for GCC plugins. + Copyright (C) 2009 Free Software Foundation, Inc. + + Contributed by Inria. + + Authors: Grigori Fursin <grigori.fursin@inria.fr>, Cupertino Miranda + <cupertinomiranda@gmail.com>, Zbigniew Chamski <zbigniew.chamski@gmail.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef FEATURE_H +#define FEATURE_H + +/* Access to values of either features or elements of feature sets */ +extern const void *get_feature (const char *feature_name); +extern const void *get_subfeature (const char *feature_name, + const char *subfeat_name); +extern void *set_subfeature (const char *feature_name, + const char *subfeat_name, void *value); + +/* Extract the size of features and feature sets */ +extern int get_feature_size (const char *feature_name); +extern int get_num_features (int type); +extern int get_num_subfeatures (const char *feat_name, int type); + +/* List of all known features, or all known elements of a feature set */ +extern const char **list_features (void); +extern const char **list_subfeatures (const char *feat_name, int type); + +#endif /* FEATURE_H */ diff --git a/gcc/highlev-plugin-internal.h b/gcc/highlev-plugin-internal.h new file mode 100644 index 00000000000..ae5048b109d --- /dev/null +++ b/gcc/highlev-plugin-internal.h @@ -0,0 +1,53 @@ +/* Compiler-side interface for high-level plugins in GCC. + Copyright (C) 2009 Free Software Foundation, Inc. + + Contributed by Inria. + + Authors: Grigori Fursin <grigori.fursin@inria.fr>, Cupertino Miranda + <cupertinomiranda@gmail.com>, Zbigniew Chamski <zbigniew.chamski@gmail.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef HIGHLEV_PLUGIN_INTERNAL +#define HIGHLEV_PLUGIN_INTERNAL + +/* Callback type for high-level argument-less event callbacks */ +typedef void (*event_callback_t) (void); + +/* Manipulation of events and event handlers */ +extern void register_plugin_event (const char *name, event_callback_t func); +extern void unregister_plugin_event (const char *name); +extern const char **list_plugin_events (void); +extern int call_plugin_event (const char *event_name); + +/* return codes for call_plugin_event */ +#define PLUGEVT_SUCCESS 0 +#define PLUGEVT_NO_EVENTS 1 +#define PLUGEVT_NO_SUCH_EVENT 2 +#define PLUGEVT_NO_CALLBACK 3 + +/* Manipulation of event parameters (callback arguments) */ +extern void register_event_parameter (const char *name, void *param); +extern void unregister_event_parameter (const char *name); +extern const char **list_event_parameters (void); +extern void *get_event_parameter (const char *name); + +/* ICI-specific, environment-based plugin loading */ +extern void load_ici_plugin (void); +extern void unload_ici_plugin (void); + +#endif /* HIGHLEV_PLUGIN_INTERNAL_H*/ diff --git a/gcc/highlev-plugin.h b/gcc/highlev-plugin.h new file mode 100644 index 00000000000..6f297ffd3ff --- /dev/null +++ b/gcc/highlev-plugin.h @@ -0,0 +1,51 @@ +/* Plugin-side interface for high-level plugins in GCC. + Copyright (C) 2009 Free Software Foundation, Inc. + + Contributed by Inria. + + Authors: Grigori Fursin <grigori.fursin@inria.fr>, Cupertino Miranda + <cupertinomiranda@gmail.com>, Zbigniew Chamski <zbigniew.chamski@gmail.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef HIGHLEV_PLUGIN_H +#define HIGHLEV_PLUGIN_H + +/* Callback type for high-level argument-less event callbacks */ +typedef void (*event_callback_t) (void); + +/* manipulation of event tables and callback lists */ +extern void register_plugin_event (const char *name, event_callback_t func); +extern void unregister_plugin_event (const char *name); +extern int call_plugin_event (const char *event_name); +extern const char **list_plugin_events (void); + +/* return codes for call_plugin_event */ +#define PLUGEVT_SUCCESS 0 +#define PLUGEVT_NO_EVENTS 1 +#define PLUGEVT_NO_SUCH_EVENT 2 +#define PLUGEVT_NO_CALLBACK 3 + +/* manipulation of event parameter (callback arg) tables */ +extern const char **list_event_parameters (void); +extern void *get_event_parameter (const char *name); + +/* pass management */ +extern void run_pass (char *pass_name); +extern const char **list_passes (void); + +#endif /* HIGHLEV_PLUGIN_H */ diff --git a/gcc/ic-interface.h b/gcc/ic-interface.h new file mode 100644 index 00000000000..4750645371f --- /dev/null +++ b/gcc/ic-interface.h @@ -0,0 +1,33 @@ +/* Toplevel interface file for legacy ICI plugins. + Copyright (C) 2009 Free Software Foundation, Inc. + + Contributed by Inria. + + Authors: Grigori Fursin <grigori.fursin@inria.fr>, Cupertino Miranda + <cupertinomiranda@gmail.com>, Zbigniew Chamski <zbigniew.chamski@gmail.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef IC_INTERFACE_H +#define IC_INTERFACE_H + +#include <stdio.h> +#include "highlev-plugin.h" +#include "feature.h" +#include "pass-manager.h" + +#endif /* IC_INTERFACE_H */ diff --git a/gcc/ici-legacy.h b/gcc/ici-legacy.h new file mode 100644 index 00000000000..ce157f64791 --- /dev/null +++ b/gcc/ici-legacy.h @@ -0,0 +1,24 @@ +#define event_func event_callback_t +#define ici_register_event register_plugin_event +#define ici_get_parameter get_event_parameter +#define ici_list_events list_plugin_events +#define ici_list_parameters list_event_parameters + +#define ici_run_pass run_pass +#define ici_add_pass register_pass +#define ici_list_passes list_passes +#define ici_load load_ici_plugin +#define ici_unload unload_ici_plugin + +#define ici_init_features init_features +#define ici_find_feature find_feature +#define ici_get_feature get_feature +#define ici_get_subfeature get_subfeature +#define ici_set_subfeature set_subfeature +#define ici_get_feature_size get_feature_size +#define ici_get_available_features list_features +#define ici_get_num_available_features get_num_features +#define ici_get_available_subfeatures list_subfeatures +#define ici_get_num_available_subfeatures get_sub_subfeatures +#define ici_init_features init_features +#define ici_list_features list_features diff --git a/gcc/pass-manager.c b/gcc/pass-manager.c new file mode 100644 index 00000000000..ee06f4b77f8 --- /dev/null +++ b/gcc/pass-manager.c @@ -0,0 +1,130 @@ +/* High-level pass management for GCC plugins. + Copyright (C) 2009 Free Software Foundation, Inc. + + Contributed by Inria. + + Authors: Grigori Fursin <grigori.fursin@inria.fr>, Cupertino Miranda + <cupertinomiranda@gmail.com>, Zbigniew Chamski <zbigniew.chamski@gmail.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#undef FLOAT /* This is for hpux. They should change hpux. */ +#undef FFS /* Some systems define this in param.h. */ +#include "system.h" +#include "coretypes.h" +#include "toplev.h" +#include "hashtab.h" +#include "tree-pass.h" +#include "highlev-plugin-internal.h" +#include "feature-internal.h" +#include "pass-manager.h" + +static htab_t passes_hash = NULL; + +/* Hash table dependent functions. */ +static hashval_t +passes_htab_hash (const void *x) +{ + const struct opt_pass *p = (const struct opt_pass *) x; + + if (!p) + internal_error ("passes_htab_hash: called with NULL pass pointer!"); + + if (p->name != NULL) + return htab_hash_string(p->name); + else + internal_error ("passes_htab_hash: NULL-named pass!\n"); +} + +static int +passes_htab_eq (const void *x, const void *y) +{ + const struct opt_pass *p1 = (const struct opt_pass *) x; + const struct opt_pass *p2 = (const struct opt_pass *) y; + + return !strcmp (p1->name, p2->name); +} + + +/* Accumulate pass names. */ +static int add_pass_name (void **slot, void *data) +{ + const char ***tmp = (const char ***) data; + const char **list = *tmp; + struct opt_pass *pass = *(struct opt_pass **) slot; + + *list = pass->name; + + *tmp = *tmp + 1; + + return 1; +} + +/* Build the array of names of all registered passes. */ +const char **list_passes (void) +{ + size_t size = htab_elements (passes_hash); + const char **list = + (const char **) xmalloc (sizeof (const char *) * (size + 1)); + const char ***tmp = &list; + const char **ret = list; + + list[size] = NULL; + htab_traverse_noresize (passes_hash, add_pass_name, tmp); + + return ret; +} + + +/* Insert a pass mapped by is pass_name in hash table. + * Allocate hash table when used for the first time. */ +void register_pass (struct opt_pass *pass) +{ + void **slot; + + /* Bail out if the pass has no name or an empty name */ + if (pass->name == NULL) + internal_error ("Cannot register a pass with no name"); + + if (!strcmp (pass->name, "")) + internal_error ("Cannot register a pass with an empty name"); + + if (passes_hash == NULL) + passes_hash = htab_create_alloc (150, passes_htab_hash, passes_htab_eq, + NULL, xcalloc, free); + + if (passes_hash == NULL) + error ("Could not allocate the hastable for passes"); + + slot = htab_find_slot (passes_hash, pass, INSERT); + *slot = pass; +} + + +/* Executes a pass, from any plugin, by its pass_name. */ +void run_pass (char *pass_name) +{ + struct opt_pass tmp_pass; + struct opt_pass *pass; + + tmp_pass.name = pass_name; + + pass = (struct opt_pass *) htab_find (passes_hash, &tmp_pass); + + execute_one_pass (pass); +} diff --git a/gcc/pass-manager.h b/gcc/pass-manager.h new file mode 100644 index 00000000000..5a479321328 --- /dev/null +++ b/gcc/pass-manager.h @@ -0,0 +1,38 @@ +/* High-level pass management interface for plugins. + Copyright (C) 2009 Free Software Foundation, Inc. + + Contributed by Inria. + + Authors: Grigori Fursin <grigori.fursin@inria.fr>, Cupertino Miranda + <cupertinomiranda@gmail.com>, Zbigniew Chamski <zbigniew.chamski@gmail.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef PASS_MANAGER_H +#define PASS_MANAGER_H + +/* declare the struct opt_pass type without defining it - needed to make + the "pointer to struct opt_pass" type unambiguous withouth pulling in + the complete "tree-pass.h" with its dependencies. */ +typedef struct opt_pass opt_pass; + +extern const char **list_passes (void); +extern void register_pass (struct opt_pass *pass); +extern int unregister_pass (char *pass_name); +extern void run_pass (char *pass_name); + +#endif /* PASS_MANAGER_H */ diff --git a/gcc/plugin-loader.c b/gcc/plugin-loader.c new file mode 100644 index 00000000000..673871b8f80 --- /dev/null +++ b/gcc/plugin-loader.c @@ -0,0 +1,140 @@ +/* [Legacy] environment-based interface for loading high-level plugins. + Copyright (C) 2009 Free Software Foundation, Inc. + + Contributed by Inria. + + Authors: Grigori Fursin <grigori.fursin@inria.fr>, Cupertino Miranda + <cupertinomiranda@gmail.com>, Zbigniew Chamski <zbigniew.chamski@gmail.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "hashtab.h" +#include "toplev.h" +#include "gcc.h" +#include "options.h" /* flag_ici */ + +#include "highlev-plugin-internal.h" +#include "feature-internal.h" /* init_features() */ + +#include <dlfcn.h> + +int ici_loaded = 0; + +/* plugin initialization/cleanup function type */ +typedef void (*start_stop_func) (void); + +typedef union { + void *data_ptr; + start_stop_func function_ptr; +} dl_symbol_t ; + + +/* pointers to initialization/cleanup functions */ +start_stop_func ici_plugin_start = NULL; +start_stop_func ici_plugin_stop = NULL; + + +/* report any errors encountered during a dl* operation */ +static inline bool check_for_dlerror (void) +{ + const char *dlError; + dlError = dlerror (); + if (dlError) + { + fprintf (stderr, "Plugin manager error: DLerror: %s ...\n", dlError); + return true; + } + return false; +} + + +/* load the ICI plugin shared library file named 'dynlib_file'. + Return 0 if successful, and 1 otherwise. */ +static int +load_ici_plugin_file (char *dynlib_file) +{ + void *dlhandle; + bool error = 0; + dl_symbol_t dl_symbol; + + if (getenv ("ICI_VERBOSE") != NULL) + fprintf (stderr, "ICI: loading plugin ...\n"); + + dlhandle = dlopen (dynlib_file, RTLD_LAZY); + error |= check_for_dlerror (); + + /* assignment of data pointers to function pointers is forbidden in strict + ANSI mode - use a union to work around this dlsym() issue. */ + + /* plugin initialization function */ + dl_symbol.data_ptr = dlsym (dlhandle, "start"); + ici_plugin_start = dl_symbol.function_ptr; + error |= check_for_dlerror (); + + /* plugin cleanup function */ + dl_symbol.data_ptr = dlsym (dlhandle, "stop"); + ici_plugin_stop = dl_symbol.function_ptr; + error |= check_for_dlerror (); + + /* if init and cleanup functions are correctly resolverd, initialize the feature list */ + if (!error) + init_features (); + + return error; +} + + +/* load a plugin speficied by envariable ICI_PLUGIN if either -fici was + given on the command line or envariable ICI_USE is set to '1'. */ +void load_ici_plugin (void) +{ + char *ici_use = getenv ("ICI_USE"); + + if ((ici_use != NULL) && (ici_use[0] == '1')) + flag_ici = true; + + if (flag_ici) + { + char *dynlib_file = getenv ("ICI_PLUGIN"); + if (dynlib_file != NULL) + { + if ((load_ici_plugin_file (dynlib_file) == 0) && ici_plugin_start) + { + ici_plugin_start (); + ici_loaded = 1; + } + } + else + { + fprintf (stderr, "ICI error: Environment variable ICI_PLUGIN is not defined ...\n"); + exit (-1); + } + } +} + +void unload_ici_plugin (void) +{ + if ((ici_loaded == 1) && ici_plugin_stop) + ici_plugin_stop (); + + if (getenv ("ICI_VERBOSE") != NULL) + fprintf (stderr, "ICI: unloading plugin...\n"); +} + |