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