1*e4b17023SJohn Marino /* Support for GCC plugin mechanism.
2*e4b17023SJohn Marino Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
3*e4b17023SJohn Marino
4*e4b17023SJohn Marino This file is part of GCC.
5*e4b17023SJohn Marino
6*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
7*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
8*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
9*e4b17023SJohn Marino any later version.
10*e4b17023SJohn Marino
11*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
12*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
13*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*e4b17023SJohn Marino GNU General Public License for more details.
15*e4b17023SJohn Marino
16*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
17*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
18*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
19*e4b17023SJohn Marino
20*e4b17023SJohn Marino /* This file contains the support for GCC plugin mechanism based on the
21*e4b17023SJohn Marino APIs described in doc/plugin.texi. */
22*e4b17023SJohn Marino
23*e4b17023SJohn Marino #include "config.h"
24*e4b17023SJohn Marino #include "system.h"
25*e4b17023SJohn Marino #include "coretypes.h"
26*e4b17023SJohn Marino #include "diagnostic-core.h"
27*e4b17023SJohn Marino #include "tree.h"
28*e4b17023SJohn Marino #include "tree-pass.h"
29*e4b17023SJohn Marino #include "intl.h"
30*e4b17023SJohn Marino #include "plugin.h"
31*e4b17023SJohn Marino #include "timevar.h"
32*e4b17023SJohn Marino #include "ggc.h"
33*e4b17023SJohn Marino
34*e4b17023SJohn Marino #ifdef ENABLE_PLUGIN
35*e4b17023SJohn Marino #include "plugin-version.h"
36*e4b17023SJohn Marino #endif
37*e4b17023SJohn Marino
38*e4b17023SJohn Marino #define GCC_PLUGIN_STRINGIFY0(X) #X
39*e4b17023SJohn Marino #define GCC_PLUGIN_STRINGIFY1(X) GCC_PLUGIN_STRINGIFY0 (X)
40*e4b17023SJohn Marino
41*e4b17023SJohn Marino /* Event names as strings. Keep in sync with enum plugin_event. */
42*e4b17023SJohn Marino static const char *plugin_event_name_init[] =
43*e4b17023SJohn Marino {
44*e4b17023SJohn Marino # define DEFEVENT(NAME) GCC_PLUGIN_STRINGIFY1 (NAME),
45*e4b17023SJohn Marino # include "plugin.def"
46*e4b17023SJohn Marino # undef DEFEVENT
47*e4b17023SJohn Marino };
48*e4b17023SJohn Marino
49*e4b17023SJohn Marino /* A printf format large enough for the largest event above. */
50*e4b17023SJohn Marino #define FMT_FOR_PLUGIN_EVENT "%-32s"
51*e4b17023SJohn Marino
52*e4b17023SJohn Marino const char **plugin_event_name = plugin_event_name_init;
53*e4b17023SJohn Marino
54*e4b17023SJohn Marino /* A hash table to map event names to the position of the names in the
55*e4b17023SJohn Marino plugin_event_name table. */
56*e4b17023SJohn Marino static htab_t event_tab;
57*e4b17023SJohn Marino
58*e4b17023SJohn Marino /* Keep track of the limit of allocated events and space ready for
59*e4b17023SJohn Marino allocating events. */
60*e4b17023SJohn Marino static int event_last = PLUGIN_EVENT_FIRST_DYNAMIC;
61*e4b17023SJohn Marino static int event_horizon = PLUGIN_EVENT_FIRST_DYNAMIC;
62*e4b17023SJohn Marino
63*e4b17023SJohn Marino /* Hash table for the plugin_name_args objects created during command-line
64*e4b17023SJohn Marino parsing. */
65*e4b17023SJohn Marino static htab_t plugin_name_args_tab = NULL;
66*e4b17023SJohn Marino
67*e4b17023SJohn Marino /* List node for keeping track of plugin-registered callback. */
68*e4b17023SJohn Marino struct callback_info
69*e4b17023SJohn Marino {
70*e4b17023SJohn Marino const char *plugin_name; /* Name of plugin that registers the callback. */
71*e4b17023SJohn Marino plugin_callback_func func; /* Callback to be called. */
72*e4b17023SJohn Marino void *user_data; /* plugin-specified data. */
73*e4b17023SJohn Marino struct callback_info *next;
74*e4b17023SJohn Marino };
75*e4b17023SJohn Marino
76*e4b17023SJohn Marino /* An array of lists of 'callback_info' objects indexed by the event id. */
77*e4b17023SJohn Marino static struct callback_info *plugin_callbacks_init[PLUGIN_EVENT_FIRST_DYNAMIC];
78*e4b17023SJohn Marino static struct callback_info **plugin_callbacks = plugin_callbacks_init;
79*e4b17023SJohn Marino
80*e4b17023SJohn Marino /* For invoke_plugin_callbacks(), see plugin.h. */
81*e4b17023SJohn Marino bool flag_plugin_added = false;
82*e4b17023SJohn Marino
83*e4b17023SJohn Marino #ifdef ENABLE_PLUGIN
84*e4b17023SJohn Marino /* Each plugin should define an initialization function with exactly
85*e4b17023SJohn Marino this name. */
86*e4b17023SJohn Marino static const char *str_plugin_init_func_name = "plugin_init";
87*e4b17023SJohn Marino
88*e4b17023SJohn Marino /* Each plugin should define this symbol to assert that it is
89*e4b17023SJohn Marino distributed under a GPL-compatible license. */
90*e4b17023SJohn Marino static const char *str_license = "plugin_is_GPL_compatible";
91*e4b17023SJohn Marino #endif
92*e4b17023SJohn Marino
93*e4b17023SJohn Marino /* Helper function for the hash table that compares the base_name of the
94*e4b17023SJohn Marino existing entry (S1) with the given string (S2). */
95*e4b17023SJohn Marino
96*e4b17023SJohn Marino static int
htab_str_eq(const void * s1,const void * s2)97*e4b17023SJohn Marino htab_str_eq (const void *s1, const void *s2)
98*e4b17023SJohn Marino {
99*e4b17023SJohn Marino const struct plugin_name_args *plugin = (const struct plugin_name_args *) s1;
100*e4b17023SJohn Marino return !strcmp (plugin->base_name, (const char *) s2);
101*e4b17023SJohn Marino }
102*e4b17023SJohn Marino
103*e4b17023SJohn Marino
104*e4b17023SJohn Marino /* Given a plugin's full-path name FULL_NAME, e.g. /pass/to/NAME.so,
105*e4b17023SJohn Marino return NAME. */
106*e4b17023SJohn Marino
107*e4b17023SJohn Marino static char *
get_plugin_base_name(const char * full_name)108*e4b17023SJohn Marino get_plugin_base_name (const char *full_name)
109*e4b17023SJohn Marino {
110*e4b17023SJohn Marino /* First get the base name part of the full-path name, i.e. NAME.so. */
111*e4b17023SJohn Marino char *base_name = xstrdup (lbasename (full_name));
112*e4b17023SJohn Marino
113*e4b17023SJohn Marino /* Then get rid of '.so' part of the name. */
114*e4b17023SJohn Marino strip_off_ending (base_name, strlen (base_name));
115*e4b17023SJohn Marino
116*e4b17023SJohn Marino return base_name;
117*e4b17023SJohn Marino }
118*e4b17023SJohn Marino
119*e4b17023SJohn Marino
120*e4b17023SJohn Marino /* Create a plugin_name_args object for the given plugin and insert it
121*e4b17023SJohn Marino to the hash table. This function is called when
122*e4b17023SJohn Marino -fplugin=/path/to/NAME.so or -fplugin=NAME option is processed. */
123*e4b17023SJohn Marino
124*e4b17023SJohn Marino void
add_new_plugin(const char * plugin_name)125*e4b17023SJohn Marino add_new_plugin (const char* plugin_name)
126*e4b17023SJohn Marino {
127*e4b17023SJohn Marino struct plugin_name_args *plugin;
128*e4b17023SJohn Marino void **slot;
129*e4b17023SJohn Marino char *base_name;
130*e4b17023SJohn Marino bool name_is_short;
131*e4b17023SJohn Marino const char *pc;
132*e4b17023SJohn Marino
133*e4b17023SJohn Marino flag_plugin_added = true;
134*e4b17023SJohn Marino
135*e4b17023SJohn Marino /* Replace short names by their full path when relevant. */
136*e4b17023SJohn Marino name_is_short = !IS_ABSOLUTE_PATH (plugin_name);
137*e4b17023SJohn Marino for (pc = plugin_name; name_is_short && *pc; pc++)
138*e4b17023SJohn Marino if (*pc == '.' || IS_DIR_SEPARATOR (*pc))
139*e4b17023SJohn Marino name_is_short = false;
140*e4b17023SJohn Marino
141*e4b17023SJohn Marino if (name_is_short)
142*e4b17023SJohn Marino {
143*e4b17023SJohn Marino base_name = CONST_CAST (char*, plugin_name);
144*e4b17023SJohn Marino /* FIXME: the ".so" suffix is currently builtin, since plugins
145*e4b17023SJohn Marino only work on ELF host systems like e.g. Linux or Solaris.
146*e4b17023SJohn Marino When plugins shall be available on non ELF systems such as
147*e4b17023SJohn Marino Windows or MacOS, this code has to be greatly improved. */
148*e4b17023SJohn Marino plugin_name = concat (default_plugin_dir_name (), "/",
149*e4b17023SJohn Marino plugin_name, ".so", NULL);
150*e4b17023SJohn Marino if (access (plugin_name, R_OK))
151*e4b17023SJohn Marino fatal_error
152*e4b17023SJohn Marino ("inaccessible plugin file %s expanded from short plugin name %s: %m",
153*e4b17023SJohn Marino plugin_name, base_name);
154*e4b17023SJohn Marino }
155*e4b17023SJohn Marino else
156*e4b17023SJohn Marino base_name = get_plugin_base_name (plugin_name);
157*e4b17023SJohn Marino
158*e4b17023SJohn Marino /* If this is the first -fplugin= option we encounter, create
159*e4b17023SJohn Marino 'plugin_name_args_tab' hash table. */
160*e4b17023SJohn Marino if (!plugin_name_args_tab)
161*e4b17023SJohn Marino plugin_name_args_tab = htab_create (10, htab_hash_string, htab_str_eq,
162*e4b17023SJohn Marino NULL);
163*e4b17023SJohn Marino
164*e4b17023SJohn Marino slot = htab_find_slot (plugin_name_args_tab, base_name, INSERT);
165*e4b17023SJohn Marino
166*e4b17023SJohn Marino /* If the same plugin (name) has been specified earlier, either emit an
167*e4b17023SJohn Marino error or a warning message depending on if they have identical full
168*e4b17023SJohn Marino (path) names. */
169*e4b17023SJohn Marino if (*slot)
170*e4b17023SJohn Marino {
171*e4b17023SJohn Marino plugin = (struct plugin_name_args *) *slot;
172*e4b17023SJohn Marino if (strcmp (plugin->full_name, plugin_name))
173*e4b17023SJohn Marino error ("plugin %s was specified with different paths:\n%s\n%s",
174*e4b17023SJohn Marino plugin->base_name, plugin->full_name, plugin_name);
175*e4b17023SJohn Marino return;
176*e4b17023SJohn Marino }
177*e4b17023SJohn Marino
178*e4b17023SJohn Marino plugin = XCNEW (struct plugin_name_args);
179*e4b17023SJohn Marino plugin->base_name = base_name;
180*e4b17023SJohn Marino plugin->full_name = plugin_name;
181*e4b17023SJohn Marino
182*e4b17023SJohn Marino *slot = plugin;
183*e4b17023SJohn Marino }
184*e4b17023SJohn Marino
185*e4b17023SJohn Marino
186*e4b17023SJohn Marino /* Parse the -fplugin-arg-<name>-<key>[=<value>] option and create a
187*e4b17023SJohn Marino 'plugin_argument' object for the parsed key-value pair. ARG is
188*e4b17023SJohn Marino the <name>-<key>[=<value>] part of the option. */
189*e4b17023SJohn Marino
190*e4b17023SJohn Marino void
parse_plugin_arg_opt(const char * arg)191*e4b17023SJohn Marino parse_plugin_arg_opt (const char *arg)
192*e4b17023SJohn Marino {
193*e4b17023SJohn Marino size_t len = 0, name_len = 0, key_len = 0, value_len = 0;
194*e4b17023SJohn Marino const char *ptr, *name_start = arg, *key_start = NULL, *value_start = NULL;
195*e4b17023SJohn Marino char *name, *key, *value;
196*e4b17023SJohn Marino void **slot;
197*e4b17023SJohn Marino bool name_parsed = false, key_parsed = false;
198*e4b17023SJohn Marino
199*e4b17023SJohn Marino /* Iterate over the ARG string and identify the starting character position
200*e4b17023SJohn Marino of 'name', 'key', and 'value' and their lengths. */
201*e4b17023SJohn Marino for (ptr = arg; *ptr; ++ptr)
202*e4b17023SJohn Marino {
203*e4b17023SJohn Marino /* Only the first '-' encountered is considered a separator between
204*e4b17023SJohn Marino 'name' and 'key'. All the subsequent '-'s are considered part of
205*e4b17023SJohn Marino 'key'. For example, given -fplugin-arg-foo-bar-primary-key=value,
206*e4b17023SJohn Marino the plugin name is 'foo' and the key is 'bar-primary-key'. */
207*e4b17023SJohn Marino if (*ptr == '-' && !name_parsed)
208*e4b17023SJohn Marino {
209*e4b17023SJohn Marino name_len = len;
210*e4b17023SJohn Marino len = 0;
211*e4b17023SJohn Marino key_start = ptr + 1;
212*e4b17023SJohn Marino name_parsed = true;
213*e4b17023SJohn Marino continue;
214*e4b17023SJohn Marino }
215*e4b17023SJohn Marino else if (*ptr == '=')
216*e4b17023SJohn Marino {
217*e4b17023SJohn Marino if (key_parsed)
218*e4b17023SJohn Marino {
219*e4b17023SJohn Marino error ("malformed option -fplugin-arg-%s (multiple '=' signs)",
220*e4b17023SJohn Marino arg);
221*e4b17023SJohn Marino return;
222*e4b17023SJohn Marino }
223*e4b17023SJohn Marino key_len = len;
224*e4b17023SJohn Marino len = 0;
225*e4b17023SJohn Marino value_start = ptr + 1;
226*e4b17023SJohn Marino key_parsed = true;
227*e4b17023SJohn Marino continue;
228*e4b17023SJohn Marino }
229*e4b17023SJohn Marino else
230*e4b17023SJohn Marino ++len;
231*e4b17023SJohn Marino }
232*e4b17023SJohn Marino
233*e4b17023SJohn Marino if (!key_start)
234*e4b17023SJohn Marino {
235*e4b17023SJohn Marino error ("malformed option -fplugin-arg-%s (missing -<key>[=<value>])",
236*e4b17023SJohn Marino arg);
237*e4b17023SJohn Marino return;
238*e4b17023SJohn Marino }
239*e4b17023SJohn Marino
240*e4b17023SJohn Marino /* If the option doesn't contain the 'value' part, LEN is the KEY_LEN.
241*e4b17023SJohn Marino Otherwise, it is the VALUE_LEN. */
242*e4b17023SJohn Marino if (!value_start)
243*e4b17023SJohn Marino key_len = len;
244*e4b17023SJohn Marino else
245*e4b17023SJohn Marino value_len = len;
246*e4b17023SJohn Marino
247*e4b17023SJohn Marino name = XNEWVEC (char, name_len + 1);
248*e4b17023SJohn Marino strncpy (name, name_start, name_len);
249*e4b17023SJohn Marino name[name_len] = '\0';
250*e4b17023SJohn Marino
251*e4b17023SJohn Marino /* Check if the named plugin has already been specified earlier in the
252*e4b17023SJohn Marino command-line. */
253*e4b17023SJohn Marino if (plugin_name_args_tab
254*e4b17023SJohn Marino && ((slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT))
255*e4b17023SJohn Marino != NULL))
256*e4b17023SJohn Marino {
257*e4b17023SJohn Marino struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
258*e4b17023SJohn Marino
259*e4b17023SJohn Marino key = XNEWVEC (char, key_len + 1);
260*e4b17023SJohn Marino strncpy (key, key_start, key_len);
261*e4b17023SJohn Marino key[key_len] = '\0';
262*e4b17023SJohn Marino if (value_start)
263*e4b17023SJohn Marino {
264*e4b17023SJohn Marino value = XNEWVEC (char, value_len + 1);
265*e4b17023SJohn Marino strncpy (value, value_start, value_len);
266*e4b17023SJohn Marino value[value_len] = '\0';
267*e4b17023SJohn Marino }
268*e4b17023SJohn Marino else
269*e4b17023SJohn Marino value = NULL;
270*e4b17023SJohn Marino
271*e4b17023SJohn Marino /* Create a plugin_argument object for the parsed key-value pair.
272*e4b17023SJohn Marino If there are already arguments for this plugin, we will need to
273*e4b17023SJohn Marino adjust the argument array size by creating a new array and deleting
274*e4b17023SJohn Marino the old one. If the performance ever becomes an issue, we can
275*e4b17023SJohn Marino change the code by pre-allocating a larger array first. */
276*e4b17023SJohn Marino if (plugin->argc > 0)
277*e4b17023SJohn Marino {
278*e4b17023SJohn Marino struct plugin_argument *args = XNEWVEC (struct plugin_argument,
279*e4b17023SJohn Marino plugin->argc + 1);
280*e4b17023SJohn Marino memcpy (args, plugin->argv,
281*e4b17023SJohn Marino sizeof (struct plugin_argument) * plugin->argc);
282*e4b17023SJohn Marino XDELETEVEC (plugin->argv);
283*e4b17023SJohn Marino plugin->argv = args;
284*e4b17023SJohn Marino ++plugin->argc;
285*e4b17023SJohn Marino }
286*e4b17023SJohn Marino else
287*e4b17023SJohn Marino {
288*e4b17023SJohn Marino gcc_assert (plugin->argv == NULL);
289*e4b17023SJohn Marino plugin->argv = XNEWVEC (struct plugin_argument, 1);
290*e4b17023SJohn Marino plugin->argc = 1;
291*e4b17023SJohn Marino }
292*e4b17023SJohn Marino
293*e4b17023SJohn Marino plugin->argv[plugin->argc - 1].key = key;
294*e4b17023SJohn Marino plugin->argv[plugin->argc - 1].value = value;
295*e4b17023SJohn Marino }
296*e4b17023SJohn Marino else
297*e4b17023SJohn Marino error ("plugin %s should be specified before -fplugin-arg-%s "
298*e4b17023SJohn Marino "in the command line", name, arg);
299*e4b17023SJohn Marino
300*e4b17023SJohn Marino /* We don't need the plugin's name anymore. Just release it. */
301*e4b17023SJohn Marino XDELETEVEC (name);
302*e4b17023SJohn Marino }
303*e4b17023SJohn Marino
304*e4b17023SJohn Marino /* Register additional plugin information. NAME is the name passed to
305*e4b17023SJohn Marino plugin_init. INFO is the information that should be registered. */
306*e4b17023SJohn Marino
307*e4b17023SJohn Marino static void
register_plugin_info(const char * name,struct plugin_info * info)308*e4b17023SJohn Marino register_plugin_info (const char* name, struct plugin_info *info)
309*e4b17023SJohn Marino {
310*e4b17023SJohn Marino void **slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT);
311*e4b17023SJohn Marino struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
312*e4b17023SJohn Marino plugin->version = info->version;
313*e4b17023SJohn Marino plugin->help = info->help;
314*e4b17023SJohn Marino }
315*e4b17023SJohn Marino
316*e4b17023SJohn Marino /* Helper function for the event hash table that compares the name of an
317*e4b17023SJohn Marino existing entry (E1) with the given string (S2). */
318*e4b17023SJohn Marino
319*e4b17023SJohn Marino static int
htab_event_eq(const void * e1,const void * s2)320*e4b17023SJohn Marino htab_event_eq (const void *e1, const void *s2)
321*e4b17023SJohn Marino {
322*e4b17023SJohn Marino const char *s1= *(const char * const *) e1;
323*e4b17023SJohn Marino return !strcmp (s1, (const char *) s2);
324*e4b17023SJohn Marino }
325*e4b17023SJohn Marino
326*e4b17023SJohn Marino /* Look up the event id for NAME. If the name is not found, return -1
327*e4b17023SJohn Marino if INSERT is NO_INSERT. */
328*e4b17023SJohn Marino
329*e4b17023SJohn Marino int
get_named_event_id(const char * name,enum insert_option insert)330*e4b17023SJohn Marino get_named_event_id (const char *name, enum insert_option insert)
331*e4b17023SJohn Marino {
332*e4b17023SJohn Marino void **slot;
333*e4b17023SJohn Marino
334*e4b17023SJohn Marino if (!event_tab)
335*e4b17023SJohn Marino {
336*e4b17023SJohn Marino int i;
337*e4b17023SJohn Marino
338*e4b17023SJohn Marino event_tab = htab_create (150, htab_hash_string, htab_event_eq, NULL);
339*e4b17023SJohn Marino for (i = 0; i < event_last; i++)
340*e4b17023SJohn Marino {
341*e4b17023SJohn Marino slot = htab_find_slot (event_tab, plugin_event_name[i], INSERT);
342*e4b17023SJohn Marino gcc_assert (*slot == HTAB_EMPTY_ENTRY);
343*e4b17023SJohn Marino *slot = &plugin_event_name[i];
344*e4b17023SJohn Marino }
345*e4b17023SJohn Marino }
346*e4b17023SJohn Marino slot = htab_find_slot (event_tab, name, insert);
347*e4b17023SJohn Marino if (slot == NULL)
348*e4b17023SJohn Marino return -1;
349*e4b17023SJohn Marino if (*slot != HTAB_EMPTY_ENTRY)
350*e4b17023SJohn Marino return (const char **) *slot - &plugin_event_name[0];
351*e4b17023SJohn Marino
352*e4b17023SJohn Marino if (event_last >= event_horizon)
353*e4b17023SJohn Marino {
354*e4b17023SJohn Marino event_horizon = event_last * 2;
355*e4b17023SJohn Marino if (plugin_event_name == plugin_event_name_init)
356*e4b17023SJohn Marino {
357*e4b17023SJohn Marino plugin_event_name = XNEWVEC (const char *, event_horizon);
358*e4b17023SJohn Marino memcpy (plugin_event_name, plugin_event_name_init,
359*e4b17023SJohn Marino sizeof plugin_event_name_init);
360*e4b17023SJohn Marino plugin_callbacks = XNEWVEC (struct callback_info *, event_horizon);
361*e4b17023SJohn Marino memcpy (plugin_callbacks, plugin_callbacks_init,
362*e4b17023SJohn Marino sizeof plugin_callbacks_init);
363*e4b17023SJohn Marino }
364*e4b17023SJohn Marino else
365*e4b17023SJohn Marino {
366*e4b17023SJohn Marino plugin_event_name
367*e4b17023SJohn Marino = XRESIZEVEC (const char *, plugin_event_name, event_horizon);
368*e4b17023SJohn Marino plugin_callbacks = XRESIZEVEC (struct callback_info *,
369*e4b17023SJohn Marino plugin_callbacks, event_horizon);
370*e4b17023SJohn Marino }
371*e4b17023SJohn Marino /* All the pointers in the hash table will need to be updated. */
372*e4b17023SJohn Marino htab_delete (event_tab);
373*e4b17023SJohn Marino event_tab = NULL;
374*e4b17023SJohn Marino }
375*e4b17023SJohn Marino else
376*e4b17023SJohn Marino *slot = &plugin_event_name[event_last];
377*e4b17023SJohn Marino plugin_event_name[event_last] = name;
378*e4b17023SJohn Marino return event_last++;
379*e4b17023SJohn Marino }
380*e4b17023SJohn Marino
381*e4b17023SJohn Marino /* Called from the plugin's initialization code. Register a single callback.
382*e4b17023SJohn Marino This function can be called multiple times.
383*e4b17023SJohn Marino
384*e4b17023SJohn Marino PLUGIN_NAME - display name for this plugin
385*e4b17023SJohn Marino EVENT - which event the callback is for
386*e4b17023SJohn Marino CALLBACK - the callback to be called at the event
387*e4b17023SJohn Marino USER_DATA - plugin-provided data */
388*e4b17023SJohn Marino
389*e4b17023SJohn Marino void
register_callback(const char * plugin_name,int event,plugin_callback_func callback,void * user_data)390*e4b17023SJohn Marino register_callback (const char *plugin_name,
391*e4b17023SJohn Marino int event,
392*e4b17023SJohn Marino plugin_callback_func callback,
393*e4b17023SJohn Marino void *user_data)
394*e4b17023SJohn Marino {
395*e4b17023SJohn Marino switch (event)
396*e4b17023SJohn Marino {
397*e4b17023SJohn Marino case PLUGIN_PASS_MANAGER_SETUP:
398*e4b17023SJohn Marino gcc_assert (!callback);
399*e4b17023SJohn Marino register_pass ((struct register_pass_info *) user_data);
400*e4b17023SJohn Marino break;
401*e4b17023SJohn Marino case PLUGIN_INFO:
402*e4b17023SJohn Marino gcc_assert (!callback);
403*e4b17023SJohn Marino register_plugin_info (plugin_name, (struct plugin_info *) user_data);
404*e4b17023SJohn Marino break;
405*e4b17023SJohn Marino case PLUGIN_REGISTER_GGC_ROOTS:
406*e4b17023SJohn Marino gcc_assert (!callback);
407*e4b17023SJohn Marino ggc_register_root_tab ((const struct ggc_root_tab*) user_data);
408*e4b17023SJohn Marino break;
409*e4b17023SJohn Marino case PLUGIN_REGISTER_GGC_CACHES:
410*e4b17023SJohn Marino gcc_assert (!callback);
411*e4b17023SJohn Marino ggc_register_cache_tab ((const struct ggc_cache_tab*) user_data);
412*e4b17023SJohn Marino break;
413*e4b17023SJohn Marino case PLUGIN_EVENT_FIRST_DYNAMIC:
414*e4b17023SJohn Marino default:
415*e4b17023SJohn Marino if (event < PLUGIN_EVENT_FIRST_DYNAMIC || event >= event_last)
416*e4b17023SJohn Marino {
417*e4b17023SJohn Marino error ("unknown callback event registered by plugin %s",
418*e4b17023SJohn Marino plugin_name);
419*e4b17023SJohn Marino return;
420*e4b17023SJohn Marino }
421*e4b17023SJohn Marino /* Fall through. */
422*e4b17023SJohn Marino case PLUGIN_FINISH_TYPE:
423*e4b17023SJohn Marino case PLUGIN_FINISH_DECL:
424*e4b17023SJohn Marino case PLUGIN_START_UNIT:
425*e4b17023SJohn Marino case PLUGIN_FINISH_UNIT:
426*e4b17023SJohn Marino case PLUGIN_PRE_GENERICIZE:
427*e4b17023SJohn Marino case PLUGIN_GGC_START:
428*e4b17023SJohn Marino case PLUGIN_GGC_MARKING:
429*e4b17023SJohn Marino case PLUGIN_GGC_END:
430*e4b17023SJohn Marino case PLUGIN_ATTRIBUTES:
431*e4b17023SJohn Marino case PLUGIN_PRAGMAS:
432*e4b17023SJohn Marino case PLUGIN_FINISH:
433*e4b17023SJohn Marino case PLUGIN_ALL_PASSES_START:
434*e4b17023SJohn Marino case PLUGIN_ALL_PASSES_END:
435*e4b17023SJohn Marino case PLUGIN_ALL_IPA_PASSES_START:
436*e4b17023SJohn Marino case PLUGIN_ALL_IPA_PASSES_END:
437*e4b17023SJohn Marino case PLUGIN_OVERRIDE_GATE:
438*e4b17023SJohn Marino case PLUGIN_PASS_EXECUTION:
439*e4b17023SJohn Marino case PLUGIN_EARLY_GIMPLE_PASSES_START:
440*e4b17023SJohn Marino case PLUGIN_EARLY_GIMPLE_PASSES_END:
441*e4b17023SJohn Marino case PLUGIN_NEW_PASS:
442*e4b17023SJohn Marino {
443*e4b17023SJohn Marino struct callback_info *new_callback;
444*e4b17023SJohn Marino if (!callback)
445*e4b17023SJohn Marino {
446*e4b17023SJohn Marino error ("plugin %s registered a null callback function "
447*e4b17023SJohn Marino "for event %s", plugin_name, plugin_event_name[event]);
448*e4b17023SJohn Marino return;
449*e4b17023SJohn Marino }
450*e4b17023SJohn Marino new_callback = XNEW (struct callback_info);
451*e4b17023SJohn Marino new_callback->plugin_name = plugin_name;
452*e4b17023SJohn Marino new_callback->func = callback;
453*e4b17023SJohn Marino new_callback->user_data = user_data;
454*e4b17023SJohn Marino new_callback->next = plugin_callbacks[event];
455*e4b17023SJohn Marino plugin_callbacks[event] = new_callback;
456*e4b17023SJohn Marino }
457*e4b17023SJohn Marino break;
458*e4b17023SJohn Marino }
459*e4b17023SJohn Marino }
460*e4b17023SJohn Marino
461*e4b17023SJohn Marino /* Remove a callback for EVENT which has been registered with for a plugin
462*e4b17023SJohn Marino PLUGIN_NAME. Return PLUGEVT_SUCCESS if a matching callback was
463*e4b17023SJohn Marino found & removed, PLUGEVT_NO_CALLBACK if the event does not have a matching
464*e4b17023SJohn Marino callback, and PLUGEVT_NO_SUCH_EVENT if EVENT is invalid. */
465*e4b17023SJohn Marino int
unregister_callback(const char * plugin_name,int event)466*e4b17023SJohn Marino unregister_callback (const char *plugin_name, int event)
467*e4b17023SJohn Marino {
468*e4b17023SJohn Marino struct callback_info *callback, **cbp;
469*e4b17023SJohn Marino
470*e4b17023SJohn Marino if (event >= event_last)
471*e4b17023SJohn Marino return PLUGEVT_NO_SUCH_EVENT;
472*e4b17023SJohn Marino
473*e4b17023SJohn Marino for (cbp = &plugin_callbacks[event]; (callback = *cbp); cbp = &callback->next)
474*e4b17023SJohn Marino if (strcmp (callback->plugin_name, plugin_name) == 0)
475*e4b17023SJohn Marino {
476*e4b17023SJohn Marino *cbp = callback->next;
477*e4b17023SJohn Marino return PLUGEVT_SUCCESS;
478*e4b17023SJohn Marino }
479*e4b17023SJohn Marino return PLUGEVT_NO_CALLBACK;
480*e4b17023SJohn Marino }
481*e4b17023SJohn Marino
482*e4b17023SJohn Marino /* Invoke all plugin callbacks registered with the specified event,
483*e4b17023SJohn Marino called from invoke_plugin_callbacks(). */
484*e4b17023SJohn Marino
485*e4b17023SJohn Marino int
invoke_plugin_callbacks_full(int event,void * gcc_data)486*e4b17023SJohn Marino invoke_plugin_callbacks_full (int event, void *gcc_data)
487*e4b17023SJohn Marino {
488*e4b17023SJohn Marino int retval = PLUGEVT_SUCCESS;
489*e4b17023SJohn Marino
490*e4b17023SJohn Marino timevar_push (TV_PLUGIN_RUN);
491*e4b17023SJohn Marino
492*e4b17023SJohn Marino switch (event)
493*e4b17023SJohn Marino {
494*e4b17023SJohn Marino case PLUGIN_EVENT_FIRST_DYNAMIC:
495*e4b17023SJohn Marino default:
496*e4b17023SJohn Marino gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC);
497*e4b17023SJohn Marino gcc_assert (event < event_last);
498*e4b17023SJohn Marino /* Fall through. */
499*e4b17023SJohn Marino case PLUGIN_FINISH_TYPE:
500*e4b17023SJohn Marino case PLUGIN_FINISH_DECL:
501*e4b17023SJohn Marino case PLUGIN_START_UNIT:
502*e4b17023SJohn Marino case PLUGIN_FINISH_UNIT:
503*e4b17023SJohn Marino case PLUGIN_PRE_GENERICIZE:
504*e4b17023SJohn Marino case PLUGIN_ATTRIBUTES:
505*e4b17023SJohn Marino case PLUGIN_PRAGMAS:
506*e4b17023SJohn Marino case PLUGIN_FINISH:
507*e4b17023SJohn Marino case PLUGIN_GGC_START:
508*e4b17023SJohn Marino case PLUGIN_GGC_MARKING:
509*e4b17023SJohn Marino case PLUGIN_GGC_END:
510*e4b17023SJohn Marino case PLUGIN_ALL_PASSES_START:
511*e4b17023SJohn Marino case PLUGIN_ALL_PASSES_END:
512*e4b17023SJohn Marino case PLUGIN_ALL_IPA_PASSES_START:
513*e4b17023SJohn Marino case PLUGIN_ALL_IPA_PASSES_END:
514*e4b17023SJohn Marino case PLUGIN_OVERRIDE_GATE:
515*e4b17023SJohn Marino case PLUGIN_PASS_EXECUTION:
516*e4b17023SJohn Marino case PLUGIN_EARLY_GIMPLE_PASSES_START:
517*e4b17023SJohn Marino case PLUGIN_EARLY_GIMPLE_PASSES_END:
518*e4b17023SJohn Marino case PLUGIN_NEW_PASS:
519*e4b17023SJohn Marino {
520*e4b17023SJohn Marino /* Iterate over every callback registered with this event and
521*e4b17023SJohn Marino call it. */
522*e4b17023SJohn Marino struct callback_info *callback = plugin_callbacks[event];
523*e4b17023SJohn Marino
524*e4b17023SJohn Marino if (!callback)
525*e4b17023SJohn Marino retval = PLUGEVT_NO_CALLBACK;
526*e4b17023SJohn Marino for ( ; callback; callback = callback->next)
527*e4b17023SJohn Marino (*callback->func) (gcc_data, callback->user_data);
528*e4b17023SJohn Marino }
529*e4b17023SJohn Marino break;
530*e4b17023SJohn Marino
531*e4b17023SJohn Marino case PLUGIN_PASS_MANAGER_SETUP:
532*e4b17023SJohn Marino case PLUGIN_REGISTER_GGC_ROOTS:
533*e4b17023SJohn Marino case PLUGIN_REGISTER_GGC_CACHES:
534*e4b17023SJohn Marino gcc_assert (false);
535*e4b17023SJohn Marino }
536*e4b17023SJohn Marino
537*e4b17023SJohn Marino timevar_pop (TV_PLUGIN_RUN);
538*e4b17023SJohn Marino return retval;
539*e4b17023SJohn Marino }
540*e4b17023SJohn Marino
541*e4b17023SJohn Marino #ifdef ENABLE_PLUGIN
542*e4b17023SJohn Marino /* We need a union to cast dlsym return value to a function pointer
543*e4b17023SJohn Marino as ISO C forbids assignment between function pointer and 'void *'.
544*e4b17023SJohn Marino Use explicit union instead of __extension__(<union_cast>) for
545*e4b17023SJohn Marino portability. */
546*e4b17023SJohn Marino #define PTR_UNION_TYPE(TOTYPE) union { void *_q; TOTYPE _nq; }
547*e4b17023SJohn Marino #define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
548*e4b17023SJohn Marino #define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
549*e4b17023SJohn Marino
550*e4b17023SJohn Marino /* Try to initialize PLUGIN. Return true if successful. */
551*e4b17023SJohn Marino
552*e4b17023SJohn Marino static bool
try_init_one_plugin(struct plugin_name_args * plugin)553*e4b17023SJohn Marino try_init_one_plugin (struct plugin_name_args *plugin)
554*e4b17023SJohn Marino {
555*e4b17023SJohn Marino void *dl_handle;
556*e4b17023SJohn Marino plugin_init_func plugin_init;
557*e4b17023SJohn Marino const char *err;
558*e4b17023SJohn Marino PTR_UNION_TYPE (plugin_init_func) plugin_init_union;
559*e4b17023SJohn Marino
560*e4b17023SJohn Marino /* We use RTLD_NOW to accelerate binding and detect any mismatch
561*e4b17023SJohn Marino between the API expected by the plugin and the GCC API; we use
562*e4b17023SJohn Marino RTLD_GLOBAL which is useful to plugins which themselves call
563*e4b17023SJohn Marino dlopen. */
564*e4b17023SJohn Marino dl_handle = dlopen (plugin->full_name, RTLD_NOW | RTLD_GLOBAL);
565*e4b17023SJohn Marino if (!dl_handle)
566*e4b17023SJohn Marino {
567*e4b17023SJohn Marino error ("cannot load plugin %s\n%s", plugin->full_name, dlerror ());
568*e4b17023SJohn Marino return false;
569*e4b17023SJohn Marino }
570*e4b17023SJohn Marino
571*e4b17023SJohn Marino /* Clear any existing error. */
572*e4b17023SJohn Marino dlerror ();
573*e4b17023SJohn Marino
574*e4b17023SJohn Marino /* Check the plugin license. */
575*e4b17023SJohn Marino if (dlsym (dl_handle, str_license) == NULL)
576*e4b17023SJohn Marino fatal_error ("plugin %s is not licensed under a GPL-compatible license\n"
577*e4b17023SJohn Marino "%s", plugin->full_name, dlerror ());
578*e4b17023SJohn Marino
579*e4b17023SJohn Marino PTR_UNION_AS_VOID_PTR (plugin_init_union) =
580*e4b17023SJohn Marino dlsym (dl_handle, str_plugin_init_func_name);
581*e4b17023SJohn Marino plugin_init = PTR_UNION_AS_CAST_PTR (plugin_init_union);
582*e4b17023SJohn Marino
583*e4b17023SJohn Marino if ((err = dlerror ()) != NULL)
584*e4b17023SJohn Marino {
585*e4b17023SJohn Marino error ("cannot find %s in plugin %s\n%s", str_plugin_init_func_name,
586*e4b17023SJohn Marino plugin->full_name, err);
587*e4b17023SJohn Marino return false;
588*e4b17023SJohn Marino }
589*e4b17023SJohn Marino
590*e4b17023SJohn Marino /* Call the plugin-provided initialization routine with the arguments. */
591*e4b17023SJohn Marino if ((*plugin_init) (plugin, &gcc_version))
592*e4b17023SJohn Marino {
593*e4b17023SJohn Marino error ("fail to initialize plugin %s", plugin->full_name);
594*e4b17023SJohn Marino return false;
595*e4b17023SJohn Marino }
596*e4b17023SJohn Marino
597*e4b17023SJohn Marino return true;
598*e4b17023SJohn Marino }
599*e4b17023SJohn Marino
600*e4b17023SJohn Marino
601*e4b17023SJohn Marino /* Routine to dlopen and initialize one plugin. This function is passed to
602*e4b17023SJohn Marino (and called by) the hash table traverse routine. Return 1 for the
603*e4b17023SJohn Marino htab_traverse to continue scan, 0 to stop.
604*e4b17023SJohn Marino
605*e4b17023SJohn Marino SLOT - slot of the hash table element
606*e4b17023SJohn Marino INFO - auxiliary pointer handed to hash table traverse routine
607*e4b17023SJohn Marino (unused in this function) */
608*e4b17023SJohn Marino
609*e4b17023SJohn Marino static int
init_one_plugin(void ** slot,void * ARG_UNUSED (info))610*e4b17023SJohn Marino init_one_plugin (void **slot, void * ARG_UNUSED (info))
611*e4b17023SJohn Marino {
612*e4b17023SJohn Marino struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
613*e4b17023SJohn Marino bool ok = try_init_one_plugin (plugin);
614*e4b17023SJohn Marino if (!ok)
615*e4b17023SJohn Marino {
616*e4b17023SJohn Marino htab_remove_elt (plugin_name_args_tab, plugin->base_name);
617*e4b17023SJohn Marino XDELETE (plugin);
618*e4b17023SJohn Marino }
619*e4b17023SJohn Marino return 1;
620*e4b17023SJohn Marino }
621*e4b17023SJohn Marino
622*e4b17023SJohn Marino #endif /* ENABLE_PLUGIN */
623*e4b17023SJohn Marino
624*e4b17023SJohn Marino /* Main plugin initialization function. Called from compile_file() in
625*e4b17023SJohn Marino toplev.c. */
626*e4b17023SJohn Marino
627*e4b17023SJohn Marino void
initialize_plugins(void)628*e4b17023SJohn Marino initialize_plugins (void)
629*e4b17023SJohn Marino {
630*e4b17023SJohn Marino /* If no plugin was specified in the command-line, simply return. */
631*e4b17023SJohn Marino if (!plugin_name_args_tab)
632*e4b17023SJohn Marino return;
633*e4b17023SJohn Marino
634*e4b17023SJohn Marino timevar_push (TV_PLUGIN_INIT);
635*e4b17023SJohn Marino
636*e4b17023SJohn Marino #ifdef ENABLE_PLUGIN
637*e4b17023SJohn Marino /* Traverse and initialize each plugin specified in the command-line. */
638*e4b17023SJohn Marino htab_traverse_noresize (plugin_name_args_tab, init_one_plugin, NULL);
639*e4b17023SJohn Marino #endif
640*e4b17023SJohn Marino
641*e4b17023SJohn Marino timevar_pop (TV_PLUGIN_INIT);
642*e4b17023SJohn Marino }
643*e4b17023SJohn Marino
644*e4b17023SJohn Marino /* Release memory used by one plugin. */
645*e4b17023SJohn Marino
646*e4b17023SJohn Marino static int
finalize_one_plugin(void ** slot,void * ARG_UNUSED (info))647*e4b17023SJohn Marino finalize_one_plugin (void **slot, void * ARG_UNUSED (info))
648*e4b17023SJohn Marino {
649*e4b17023SJohn Marino struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
650*e4b17023SJohn Marino XDELETE (plugin);
651*e4b17023SJohn Marino return 1;
652*e4b17023SJohn Marino }
653*e4b17023SJohn Marino
654*e4b17023SJohn Marino /* Free memory allocated by the plugin system. */
655*e4b17023SJohn Marino
656*e4b17023SJohn Marino void
finalize_plugins(void)657*e4b17023SJohn Marino finalize_plugins (void)
658*e4b17023SJohn Marino {
659*e4b17023SJohn Marino if (!plugin_name_args_tab)
660*e4b17023SJohn Marino return;
661*e4b17023SJohn Marino
662*e4b17023SJohn Marino /* We can now delete the plugin_name_args object as it will no longer
663*e4b17023SJohn Marino be used. Note that base_name and argv fields (both of which were also
664*e4b17023SJohn Marino dynamically allocated) are not freed as they could still be used by
665*e4b17023SJohn Marino the plugin code. */
666*e4b17023SJohn Marino
667*e4b17023SJohn Marino htab_traverse_noresize (plugin_name_args_tab, finalize_one_plugin, NULL);
668*e4b17023SJohn Marino
669*e4b17023SJohn Marino /* PLUGIN_NAME_ARGS_TAB is no longer needed, just delete it. */
670*e4b17023SJohn Marino htab_delete (plugin_name_args_tab);
671*e4b17023SJohn Marino plugin_name_args_tab = NULL;
672*e4b17023SJohn Marino }
673*e4b17023SJohn Marino
674*e4b17023SJohn Marino /* Used to pass options to htab_traverse callbacks. */
675*e4b17023SJohn Marino
676*e4b17023SJohn Marino struct print_options
677*e4b17023SJohn Marino {
678*e4b17023SJohn Marino FILE *file;
679*e4b17023SJohn Marino const char *indent;
680*e4b17023SJohn Marino };
681*e4b17023SJohn Marino
682*e4b17023SJohn Marino /* Print the version of one plugin. */
683*e4b17023SJohn Marino
684*e4b17023SJohn Marino static int
print_version_one_plugin(void ** slot,void * data)685*e4b17023SJohn Marino print_version_one_plugin (void **slot, void *data)
686*e4b17023SJohn Marino {
687*e4b17023SJohn Marino struct print_options *opt = (struct print_options *) data;
688*e4b17023SJohn Marino struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
689*e4b17023SJohn Marino const char *version = plugin->version ? plugin->version : "Unknown version.";
690*e4b17023SJohn Marino
691*e4b17023SJohn Marino fprintf (opt->file, " %s%s: %s\n", opt->indent, plugin->base_name, version);
692*e4b17023SJohn Marino return 1;
693*e4b17023SJohn Marino }
694*e4b17023SJohn Marino
695*e4b17023SJohn Marino /* Print the version of each plugin. */
696*e4b17023SJohn Marino
697*e4b17023SJohn Marino void
print_plugins_versions(FILE * file,const char * indent)698*e4b17023SJohn Marino print_plugins_versions (FILE *file, const char *indent)
699*e4b17023SJohn Marino {
700*e4b17023SJohn Marino struct print_options opt;
701*e4b17023SJohn Marino opt.file = file;
702*e4b17023SJohn Marino opt.indent = indent;
703*e4b17023SJohn Marino if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
704*e4b17023SJohn Marino return;
705*e4b17023SJohn Marino
706*e4b17023SJohn Marino fprintf (file, "%sVersions of loaded plugins:\n", indent);
707*e4b17023SJohn Marino htab_traverse_noresize (plugin_name_args_tab, print_version_one_plugin, &opt);
708*e4b17023SJohn Marino }
709*e4b17023SJohn Marino
710*e4b17023SJohn Marino /* Print help for one plugin. SLOT is the hash table slot. DATA is the
711*e4b17023SJohn Marino argument to htab_traverse_noresize. */
712*e4b17023SJohn Marino
713*e4b17023SJohn Marino static int
print_help_one_plugin(void ** slot,void * data)714*e4b17023SJohn Marino print_help_one_plugin (void **slot, void *data)
715*e4b17023SJohn Marino {
716*e4b17023SJohn Marino struct print_options *opt = (struct print_options *) data;
717*e4b17023SJohn Marino struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
718*e4b17023SJohn Marino const char *help = plugin->help ? plugin->help : "No help available .";
719*e4b17023SJohn Marino
720*e4b17023SJohn Marino char *dup = xstrdup (help);
721*e4b17023SJohn Marino char *p, *nl;
722*e4b17023SJohn Marino fprintf (opt->file, " %s%s:\n", opt->indent, plugin->base_name);
723*e4b17023SJohn Marino
724*e4b17023SJohn Marino for (p = nl = dup; nl; p = nl)
725*e4b17023SJohn Marino {
726*e4b17023SJohn Marino nl = strchr (nl, '\n');
727*e4b17023SJohn Marino if (nl)
728*e4b17023SJohn Marino {
729*e4b17023SJohn Marino *nl = '\0';
730*e4b17023SJohn Marino nl++;
731*e4b17023SJohn Marino }
732*e4b17023SJohn Marino fprintf (opt->file, " %s %s\n", opt->indent, p);
733*e4b17023SJohn Marino }
734*e4b17023SJohn Marino
735*e4b17023SJohn Marino free (dup);
736*e4b17023SJohn Marino return 1;
737*e4b17023SJohn Marino }
738*e4b17023SJohn Marino
739*e4b17023SJohn Marino /* Print help for each plugin. The output goes to FILE and every line starts
740*e4b17023SJohn Marino with INDENT. */
741*e4b17023SJohn Marino
742*e4b17023SJohn Marino void
print_plugins_help(FILE * file,const char * indent)743*e4b17023SJohn Marino print_plugins_help (FILE *file, const char *indent)
744*e4b17023SJohn Marino {
745*e4b17023SJohn Marino struct print_options opt;
746*e4b17023SJohn Marino opt.file = file;
747*e4b17023SJohn Marino opt.indent = indent;
748*e4b17023SJohn Marino if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
749*e4b17023SJohn Marino return;
750*e4b17023SJohn Marino
751*e4b17023SJohn Marino fprintf (file, "%sHelp for the loaded plugins:\n", indent);
752*e4b17023SJohn Marino htab_traverse_noresize (plugin_name_args_tab, print_help_one_plugin, &opt);
753*e4b17023SJohn Marino }
754*e4b17023SJohn Marino
755*e4b17023SJohn Marino
756*e4b17023SJohn Marino /* Return true if plugins have been loaded. */
757*e4b17023SJohn Marino
758*e4b17023SJohn Marino bool
plugins_active_p(void)759*e4b17023SJohn Marino plugins_active_p (void)
760*e4b17023SJohn Marino {
761*e4b17023SJohn Marino int event;
762*e4b17023SJohn Marino
763*e4b17023SJohn Marino for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
764*e4b17023SJohn Marino if (plugin_callbacks[event])
765*e4b17023SJohn Marino return true;
766*e4b17023SJohn Marino
767*e4b17023SJohn Marino return false;
768*e4b17023SJohn Marino }
769*e4b17023SJohn Marino
770*e4b17023SJohn Marino
771*e4b17023SJohn Marino /* Dump to FILE the names and associated events for all the active
772*e4b17023SJohn Marino plugins. */
773*e4b17023SJohn Marino
774*e4b17023SJohn Marino DEBUG_FUNCTION void
dump_active_plugins(FILE * file)775*e4b17023SJohn Marino dump_active_plugins (FILE *file)
776*e4b17023SJohn Marino {
777*e4b17023SJohn Marino int event;
778*e4b17023SJohn Marino
779*e4b17023SJohn Marino if (!plugins_active_p ())
780*e4b17023SJohn Marino return;
781*e4b17023SJohn Marino
782*e4b17023SJohn Marino fprintf (file, FMT_FOR_PLUGIN_EVENT " | %s\n", _("Event"), _("Plugins"));
783*e4b17023SJohn Marino for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
784*e4b17023SJohn Marino if (plugin_callbacks[event])
785*e4b17023SJohn Marino {
786*e4b17023SJohn Marino struct callback_info *ci;
787*e4b17023SJohn Marino
788*e4b17023SJohn Marino fprintf (file, FMT_FOR_PLUGIN_EVENT " |", plugin_event_name[event]);
789*e4b17023SJohn Marino
790*e4b17023SJohn Marino for (ci = plugin_callbacks[event]; ci; ci = ci->next)
791*e4b17023SJohn Marino fprintf (file, " %s", ci->plugin_name);
792*e4b17023SJohn Marino
793*e4b17023SJohn Marino putc('\n', file);
794*e4b17023SJohn Marino }
795*e4b17023SJohn Marino }
796*e4b17023SJohn Marino
797*e4b17023SJohn Marino
798*e4b17023SJohn Marino /* Dump active plugins to stderr. */
799*e4b17023SJohn Marino
800*e4b17023SJohn Marino DEBUG_FUNCTION void
debug_active_plugins(void)801*e4b17023SJohn Marino debug_active_plugins (void)
802*e4b17023SJohn Marino {
803*e4b17023SJohn Marino dump_active_plugins (stderr);
804*e4b17023SJohn Marino }
805*e4b17023SJohn Marino
806*e4b17023SJohn Marino /* Give a warning if plugins are present, before an ICE message asking
807*e4b17023SJohn Marino to submit a bug report. */
808*e4b17023SJohn Marino
809*e4b17023SJohn Marino void
warn_if_plugins(void)810*e4b17023SJohn Marino warn_if_plugins (void)
811*e4b17023SJohn Marino {
812*e4b17023SJohn Marino if (plugins_active_p ())
813*e4b17023SJohn Marino {
814*e4b17023SJohn Marino fnotice (stderr, "*** WARNING *** there are active plugins, do not report"
815*e4b17023SJohn Marino " this as a bug unless you can reproduce it without enabling"
816*e4b17023SJohn Marino " any plugins.\n");
817*e4b17023SJohn Marino dump_active_plugins (stderr);
818*e4b17023SJohn Marino }
819*e4b17023SJohn Marino
820*e4b17023SJohn Marino }
821*e4b17023SJohn Marino
822*e4b17023SJohn Marino /* Likewise, as a callback from the diagnostics code. */
823*e4b17023SJohn Marino
824*e4b17023SJohn Marino void
plugins_internal_error_function(diagnostic_context * context ATTRIBUTE_UNUSED,const char * msgid ATTRIBUTE_UNUSED,va_list * ap ATTRIBUTE_UNUSED)825*e4b17023SJohn Marino plugins_internal_error_function (diagnostic_context *context ATTRIBUTE_UNUSED,
826*e4b17023SJohn Marino const char *msgid ATTRIBUTE_UNUSED,
827*e4b17023SJohn Marino va_list *ap ATTRIBUTE_UNUSED)
828*e4b17023SJohn Marino {
829*e4b17023SJohn Marino warn_if_plugins ();
830*e4b17023SJohn Marino }
831*e4b17023SJohn Marino
832*e4b17023SJohn Marino /* The default version check. Compares every field in VERSION. */
833*e4b17023SJohn Marino
834*e4b17023SJohn Marino bool
plugin_default_version_check(struct plugin_gcc_version * gcc_version,struct plugin_gcc_version * plugin_version)835*e4b17023SJohn Marino plugin_default_version_check (struct plugin_gcc_version *gcc_version,
836*e4b17023SJohn Marino struct plugin_gcc_version *plugin_version)
837*e4b17023SJohn Marino {
838*e4b17023SJohn Marino if (!gcc_version || !plugin_version)
839*e4b17023SJohn Marino return false;
840*e4b17023SJohn Marino
841*e4b17023SJohn Marino if (strcmp (gcc_version->basever, plugin_version->basever))
842*e4b17023SJohn Marino return false;
843*e4b17023SJohn Marino if (strcmp (gcc_version->datestamp, plugin_version->datestamp))
844*e4b17023SJohn Marino return false;
845*e4b17023SJohn Marino if (strcmp (gcc_version->devphase, plugin_version->devphase))
846*e4b17023SJohn Marino return false;
847*e4b17023SJohn Marino if (strcmp (gcc_version->revision, plugin_version->revision))
848*e4b17023SJohn Marino return false;
849*e4b17023SJohn Marino if (strcmp (gcc_version->configuration_arguments,
850*e4b17023SJohn Marino plugin_version->configuration_arguments))
851*e4b17023SJohn Marino return false;
852*e4b17023SJohn Marino return true;
853*e4b17023SJohn Marino }
854*e4b17023SJohn Marino
855*e4b17023SJohn Marino
856*e4b17023SJohn Marino /* Return the current value of event_last, so that plugins which provide
857*e4b17023SJohn Marino additional functionality for events for the benefit of high-level plugins
858*e4b17023SJohn Marino know how many valid entries plugin_event_name holds. */
859*e4b17023SJohn Marino
860*e4b17023SJohn Marino int
get_event_last(void)861*e4b17023SJohn Marino get_event_last (void)
862*e4b17023SJohn Marino {
863*e4b17023SJohn Marino return event_last;
864*e4b17023SJohn Marino }
865*e4b17023SJohn Marino
866*e4b17023SJohn Marino
867*e4b17023SJohn Marino /* Retrieve the default plugin directory. The gcc driver should have passed
868*e4b17023SJohn Marino it as -iplugindir <dir> to the cc1 program, and it is queriable thru the
869*e4b17023SJohn Marino -print-file-name=plugin option to gcc. */
870*e4b17023SJohn Marino const char*
default_plugin_dir_name(void)871*e4b17023SJohn Marino default_plugin_dir_name (void)
872*e4b17023SJohn Marino {
873*e4b17023SJohn Marino if (!plugindir_string)
874*e4b17023SJohn Marino fatal_error ("-iplugindir <dir> option not passed from the gcc driver");
875*e4b17023SJohn Marino return plugindir_string;
876*e4b17023SJohn Marino }
877