OSDN Git Service

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