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