OSDN Git Service

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