OSDN Git Service

* common/config/i386/i386-common.c (ix86_option_optimization_table):
[pf3gnuchains/gcc-fork.git] / gcc / plugin.c
1 /* Support for GCC plugin mechanism.
2    Copyright (C) 2009, 2010, 2011 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           ("inaccessible 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_FINISH_DECL:
424       case PLUGIN_START_UNIT:
425       case PLUGIN_FINISH_UNIT:
426       case PLUGIN_PRE_GENERICIZE:
427       case PLUGIN_GGC_START:
428       case PLUGIN_GGC_MARKING:
429       case PLUGIN_GGC_END:
430       case PLUGIN_ATTRIBUTES:
431       case PLUGIN_PRAGMAS:
432       case PLUGIN_FINISH:
433       case PLUGIN_ALL_PASSES_START:
434       case PLUGIN_ALL_PASSES_END:
435       case PLUGIN_ALL_IPA_PASSES_START:
436       case PLUGIN_ALL_IPA_PASSES_END:
437       case PLUGIN_OVERRIDE_GATE:
438       case PLUGIN_PASS_EXECUTION:
439       case PLUGIN_EARLY_GIMPLE_PASSES_START:
440       case PLUGIN_EARLY_GIMPLE_PASSES_END:
441       case PLUGIN_NEW_PASS:
442         {
443           struct callback_info *new_callback;
444           if (!callback)
445             {
446               error ("plugin %s registered a null callback function "
447                      "for event %s", plugin_name, plugin_event_name[event]);
448               return;
449             }
450           new_callback = XNEW (struct callback_info);
451           new_callback->plugin_name = plugin_name;
452           new_callback->func = callback;
453           new_callback->user_data = user_data;
454           new_callback->next = plugin_callbacks[event];
455           plugin_callbacks[event] = new_callback;
456         }
457         break;
458     }
459 }
460
461 /* Remove a callback for EVENT which has been registered with for a plugin
462    PLUGIN_NAME.  Return PLUGEVT_SUCCESS if a matching callback was
463    found & removed, PLUGEVT_NO_CALLBACK if the event does not have a matching
464    callback, and PLUGEVT_NO_SUCH_EVENT if EVENT is invalid.  */
465 int
466 unregister_callback (const char *plugin_name, int event)
467 {
468   struct callback_info *callback, **cbp;
469
470   if (event >= event_last)
471     return PLUGEVT_NO_SUCH_EVENT;
472
473   for (cbp = &plugin_callbacks[event]; (callback = *cbp); cbp = &callback->next)
474     if (strcmp (callback->plugin_name, plugin_name) == 0)
475       {
476         *cbp = callback->next;
477         return PLUGEVT_SUCCESS;
478       }
479   return PLUGEVT_NO_CALLBACK;
480 }
481
482 /* Invoke all plugin callbacks registered with the specified event,
483    called from invoke_plugin_callbacks().  */
484
485 int
486 invoke_plugin_callbacks_full (int event, void *gcc_data)
487 {
488   int retval = PLUGEVT_SUCCESS;
489
490   timevar_push (TV_PLUGIN_RUN);
491
492   switch (event)
493     {
494       case PLUGIN_EVENT_FIRST_DYNAMIC:
495       default:
496         gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC);
497         gcc_assert (event < event_last);
498       /* Fall through.  */
499       case PLUGIN_FINISH_TYPE:
500       case PLUGIN_FINISH_DECL:
501       case PLUGIN_START_UNIT:
502       case PLUGIN_FINISH_UNIT:
503       case PLUGIN_PRE_GENERICIZE:
504       case PLUGIN_ATTRIBUTES:
505       case PLUGIN_PRAGMAS:
506       case PLUGIN_FINISH:
507       case PLUGIN_GGC_START:
508       case PLUGIN_GGC_MARKING:
509       case PLUGIN_GGC_END:
510       case PLUGIN_ALL_PASSES_START:
511       case PLUGIN_ALL_PASSES_END:
512       case PLUGIN_ALL_IPA_PASSES_START:
513       case PLUGIN_ALL_IPA_PASSES_END:
514       case PLUGIN_OVERRIDE_GATE:
515       case PLUGIN_PASS_EXECUTION:
516       case PLUGIN_EARLY_GIMPLE_PASSES_START:
517       case PLUGIN_EARLY_GIMPLE_PASSES_END:
518       case PLUGIN_NEW_PASS:
519         {
520           /* Iterate over every callback registered with this event and
521              call it.  */
522           struct callback_info *callback = plugin_callbacks[event];
523
524           if (!callback)
525             retval = PLUGEVT_NO_CALLBACK;
526           for ( ; callback; callback = callback->next)
527             (*callback->func) (gcc_data, callback->user_data);
528         }
529         break;
530
531       case PLUGIN_PASS_MANAGER_SETUP:
532       case PLUGIN_REGISTER_GGC_ROOTS:
533       case PLUGIN_REGISTER_GGC_CACHES:
534         gcc_assert (false);
535     }
536
537   timevar_pop (TV_PLUGIN_RUN);
538   return retval;
539 }
540
541 #ifdef ENABLE_PLUGIN
542 /* We need a union to cast dlsym return value to a function pointer
543    as ISO C forbids assignment between function pointer and 'void *'.
544    Use explicit union instead of __extension__(<union_cast>) for
545    portability.  */
546 #define PTR_UNION_TYPE(TOTYPE) union { void *_q; TOTYPE _nq; }
547 #define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
548 #define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
549
550 /* Try to initialize PLUGIN. Return true if successful. */
551
552 static bool
553 try_init_one_plugin (struct plugin_name_args *plugin)
554 {
555   void *dl_handle;
556   plugin_init_func plugin_init;
557   const char *err;
558   PTR_UNION_TYPE (plugin_init_func) plugin_init_union;
559
560   /* We use RTLD_NOW to accelerate binding and detect any mismatch
561      between the API expected by the plugin and the GCC API; we use
562      RTLD_GLOBAL which is useful to plugins which themselves call
563      dlopen.  */
564   dl_handle = dlopen (plugin->full_name, RTLD_NOW | RTLD_GLOBAL);
565   if (!dl_handle)
566     {
567       error ("cannot load plugin %s\n%s", plugin->full_name, dlerror ());
568       return false;
569     }
570
571   /* Clear any existing error.  */
572   dlerror ();
573
574   /* Check the plugin license.  */
575   if (dlsym (dl_handle, str_license) == NULL)
576     fatal_error ("plugin %s is not licensed under a GPL-compatible license\n"
577                  "%s", plugin->full_name, dlerror ());
578
579   PTR_UNION_AS_VOID_PTR (plugin_init_union) =
580       dlsym (dl_handle, str_plugin_init_func_name);
581   plugin_init = PTR_UNION_AS_CAST_PTR (plugin_init_union);
582
583   if ((err = dlerror ()) != NULL)
584     {
585       error ("cannot find %s in plugin %s\n%s", str_plugin_init_func_name,
586              plugin->full_name, err);
587       return false;
588     }
589
590   /* Call the plugin-provided initialization routine with the arguments.  */
591   if ((*plugin_init) (plugin, &gcc_version))
592     {
593       error ("fail to initialize plugin %s", plugin->full_name);
594       return false;
595     }
596
597   return true;
598 }
599
600
601 /* Routine to dlopen and initialize one plugin. This function is passed to
602    (and called by) the hash table traverse routine. Return 1 for the
603    htab_traverse to continue scan, 0 to stop.
604
605    SLOT - slot of the hash table element
606    INFO - auxiliary pointer handed to hash table traverse routine
607           (unused in this function)  */
608
609 static int
610 init_one_plugin (void **slot, void * ARG_UNUSED (info))
611 {
612   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
613   bool ok = try_init_one_plugin (plugin);
614   if (!ok)
615     {
616       htab_remove_elt (plugin_name_args_tab, plugin->base_name);
617       XDELETE (plugin);
618     }
619   return 1;
620 }
621
622 #endif  /* ENABLE_PLUGIN  */
623
624 /* Main plugin initialization function.  Called from compile_file() in
625    toplev.c.  */
626
627 void
628 initialize_plugins (void)
629 {
630   /* If no plugin was specified in the command-line, simply return.  */
631   if (!plugin_name_args_tab)
632     return;
633
634   timevar_push (TV_PLUGIN_INIT);
635
636 #ifdef ENABLE_PLUGIN
637   /* Traverse and initialize each plugin specified in the command-line.  */
638   htab_traverse_noresize (plugin_name_args_tab, init_one_plugin, NULL);
639 #endif
640
641   timevar_pop (TV_PLUGIN_INIT);
642 }
643
644 /* Release memory used by one plugin. */
645
646 static int
647 finalize_one_plugin (void **slot, void * ARG_UNUSED (info))
648 {
649   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
650   XDELETE (plugin);
651   return 1;
652 }
653
654 /* Free memory allocated by the plugin system. */
655
656 void
657 finalize_plugins (void)
658 {
659   if (!plugin_name_args_tab)
660     return;
661
662   /* We can now delete the plugin_name_args object as it will no longer
663      be used. Note that base_name and argv fields (both of which were also
664      dynamically allocated) are not freed as they could still be used by
665      the plugin code.  */
666
667   htab_traverse_noresize (plugin_name_args_tab, finalize_one_plugin, NULL);
668
669   /* PLUGIN_NAME_ARGS_TAB is no longer needed, just delete it.  */
670   htab_delete (plugin_name_args_tab);
671   plugin_name_args_tab = NULL;
672 }
673
674 /* Used to pass options to htab_traverse callbacks. */
675
676 struct print_options
677 {
678   FILE *file;
679   const char *indent;
680 };
681
682 /* Print the version of one plugin. */
683
684 static int
685 print_version_one_plugin (void **slot, void *data)
686 {
687   struct print_options *opt = (struct print_options *) data;
688   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
689   const char *version = plugin->version ? plugin->version : "Unknown version.";
690
691   fprintf (opt->file, " %s%s: %s\n", opt->indent, plugin->base_name, version);
692   return 1;
693 }
694
695 /* Print the version of each plugin. */
696
697 void
698 print_plugins_versions (FILE *file, const char *indent)
699 {
700   struct print_options opt;
701   opt.file = file;
702   opt.indent = indent;
703   if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
704     return;
705
706   fprintf (file, "%sVersions of loaded plugins:\n", indent);
707   htab_traverse_noresize (plugin_name_args_tab, print_version_one_plugin, &opt);
708 }
709
710 /* Print help for one plugin. SLOT is the hash table slot. DATA is the
711    argument to htab_traverse_noresize. */
712
713 static int
714 print_help_one_plugin (void **slot, void *data)
715 {
716   struct print_options *opt = (struct print_options *) data;
717   struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
718   const char *help = plugin->help ? plugin->help : "No help available .";
719
720   char *dup = xstrdup (help);
721   char *p, *nl;
722   fprintf (opt->file, " %s%s:\n", opt->indent, plugin->base_name);
723
724   for (p = nl = dup; nl; p = nl)
725     {
726       nl = strchr (nl, '\n');
727       if (nl)
728         {
729           *nl = '\0';
730           nl++;
731         }
732       fprintf (opt->file, "   %s %s\n", opt->indent, p);
733     }
734
735   free (dup);
736   return 1;
737 }
738
739 /* Print help for each plugin. The output goes to FILE and every line starts
740    with INDENT. */
741
742 void
743 print_plugins_help (FILE *file, const char *indent)
744 {
745   struct print_options opt;
746   opt.file = file;
747   opt.indent = indent;
748   if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
749     return;
750
751   fprintf (file, "%sHelp for the loaded plugins:\n", indent);
752   htab_traverse_noresize (plugin_name_args_tab, print_help_one_plugin, &opt);
753 }
754
755
756 /* Return true if plugins have been loaded.  */
757
758 bool
759 plugins_active_p (void)
760 {
761   int event;
762
763   for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
764     if (plugin_callbacks[event])
765       return true;
766
767   return false;
768 }
769
770
771 /* Dump to FILE the names and associated events for all the active
772    plugins.  */
773
774 DEBUG_FUNCTION void
775 dump_active_plugins (FILE *file)
776 {
777   int event;
778
779   if (!plugins_active_p ())
780     return;
781
782   fprintf (file, FMT_FOR_PLUGIN_EVENT " | %s\n", _("Event"), _("Plugins"));
783   for (event = PLUGIN_PASS_MANAGER_SETUP; event < event_last; event++)
784     if (plugin_callbacks[event])
785       {
786         struct callback_info *ci;
787
788         fprintf (file, FMT_FOR_PLUGIN_EVENT " |", plugin_event_name[event]);
789
790         for (ci = plugin_callbacks[event]; ci; ci = ci->next)
791           fprintf (file, " %s", ci->plugin_name);
792
793         putc('\n', file);
794       }
795 }
796
797
798 /* Dump active plugins to stderr.  */
799
800 DEBUG_FUNCTION void
801 debug_active_plugins (void)
802 {
803   dump_active_plugins (stderr);
804 }
805
806 /* Give a warning if plugins are present, before an ICE message asking
807    to submit a bug report.  */
808
809 void
810 warn_if_plugins (void)
811 {
812   if (plugins_active_p ())
813     {
814       fnotice (stderr, "*** WARNING *** there are active plugins, do not report"
815                " this as a bug unless you can reproduce it without enabling"
816                " any plugins.\n");
817       dump_active_plugins (stderr);
818     }
819
820 }
821
822 /* Likewise, as a callback from the diagnostics code.  */
823
824 void
825 plugins_internal_error_function (diagnostic_context *context ATTRIBUTE_UNUSED,
826                                  const char *msgid ATTRIBUTE_UNUSED,
827                                  va_list *ap ATTRIBUTE_UNUSED)
828 {
829   warn_if_plugins ();
830 }
831
832 /* The default version check. Compares every field in VERSION. */
833
834 bool
835 plugin_default_version_check (struct plugin_gcc_version *gcc_version,
836                               struct plugin_gcc_version *plugin_version)
837 {
838   if (!gcc_version || !plugin_version)
839     return false;
840
841   if (strcmp (gcc_version->basever, plugin_version->basever))
842     return false;
843   if (strcmp (gcc_version->datestamp, plugin_version->datestamp))
844     return false;
845   if (strcmp (gcc_version->devphase, plugin_version->devphase))
846     return false;
847   if (strcmp (gcc_version->revision, plugin_version->revision))
848     return false;
849   if (strcmp (gcc_version->configuration_arguments,
850               plugin_version->configuration_arguments))
851     return false;
852   return true;
853 }
854
855
856 /* Return the current value of event_last, so that plugins which provide
857    additional functionality for events for the benefit of high-level plugins
858    know how many valid entries plugin_event_name holds.  */
859
860 int
861 get_event_last (void)
862 {
863   return event_last;
864 }
865
866
867 /* Retrieve the default plugin directory.  The gcc driver should have passed
868    it as -iplugindir <dir> to the cc1 program, and it is queriable thru the
869    -print-file-name=plugin option to gcc.  */
870 const char*
871 default_plugin_dir_name (void)
872 {
873   if (!plugindir_string)
874     fatal_error ("-iplugindir <dir> option not passed from the gcc driver");
875   return plugindir_string;
876 }