OSDN Git Service

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