OSDN Git Service

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