aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRazya Ladelsky <razya@il.ibm.com>2009-06-01 17:35:51 +0000
committerRazya Ladelsky <razya@il.ibm.com>2009-06-01 17:35:51 +0000
commit54a26bd853030cd72fcdca4f242b99ac7dffe504 (patch)
tree2159c0a54e51ccc25b18dbd3478f342b1f9228b6
parent26fccfee1b40551c5afb470eff0dbdf4831fab9c (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.c294
-rw-r--r--gcc/feature-internal.h65
-rw-r--r--gcc/feature-list.c515
-rw-r--r--gcc/feature.c210
-rw-r--r--gcc/feature.h44
-rw-r--r--gcc/highlev-plugin-internal.h53
-rw-r--r--gcc/highlev-plugin.h51
-rw-r--r--gcc/ic-interface.h33
-rw-r--r--gcc/ici-legacy.h24
-rw-r--r--gcc/pass-manager.c130
-rw-r--r--gcc/pass-manager.h38
-rw-r--r--gcc/plugin-loader.c140
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, &param);
+}
+
+
+/* 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");
+}
+