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