plugins.texi (Plugin callbacks): added PLUGIN_PRAGMAS.
[gcc.git] / gcc / plugin.c
1 /* Support for GCC plugin mechanism.
2 Copyright (C) 2009 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 /* Event names as strings. Keep in sync with enum plugin_event. */
48 const char *plugin_event_name[] =
49 {
50 "PLUGIN_PASS_MANAGER_SETUP",
51 "PLUGIN_FINISH_TYPE",
52 "PLUGIN_FINISH_UNIT",
53 "PLUGIN_CXX_CP_PRE_GENERICIZE",
54 "PLUGIN_FINISH",
55 "PLUGIN_INFO",
56 "PLUGIN_GGC_START",
57 "PLUGIN_GGC_MARKING",
58 "PLUGIN_GGC_END",
59 "PLUGIN_REGISTER_GGC_ROOTS",
60 "PLUGIN_REGISTER_GGC_CACHES",
61 "PLUGIN_ATTRIBUTES",
62 "PLUGIN_START_UNIT",
63 "PLUGIN_PRAGMAS",
64 "PLUGIN_EVENT_LAST"
65 };
66
67 /* Hash table for the plugin_name_args objects created during command-line
68 parsing. */
69 static htab_t plugin_name_args_tab = NULL;
70
71 /* List node for keeping track of plugin-registered callback. */
72 struct callback_info
73 {
74 const char *plugin_name; /* Name of plugin that registers the callback. */
75 plugin_callback_func func; /* Callback to be called. */
76 void *user_data; /* plugin-specified data. */
77 struct callback_info *next;
78 };
79
80 /* An array of lists of 'callback_info' objects indexed by the event id. */
81 static struct callback_info *plugin_callbacks[PLUGIN_EVENT_LAST] = { NULL };
82
83
84 #ifdef ENABLE_PLUGIN
85 /* Each plugin should define an initialization function with exactly
86 this name. */
87 static const char *str_plugin_init_func_name = "plugin_init";
88
89 /* Each plugin should define this symbol to assert that it is
90 distributed under a GPL-compatible license. */
91 static const char *str_license = "plugin_is_GPL_compatible";
92 #endif
93
94 /* Helper function for the hash table that compares the base_name of the
95 existing entry (S1) with the given string (S2). */
96
97 static int
98 htab_str_eq (const void *s1, const void *s2)
99 {
100 const struct plugin_name_args *plugin = (const struct plugin_name_args *) s1;
101 return !strcmp (plugin->base_name, (const char *) s2);
102 }
103
104
105 /* Given a plugin's full-path name FULL_NAME, e.g. /pass/to/NAME.so,
106 return NAME. */
107
108 static char *
109 get_plugin_base_name (const char *full_name)
110 {
111 /* First get the base name part of the full-path name, i.e. NAME.so. */
112 char *base_name = xstrdup (lbasename (full_name));
113
114 /* Then get rid of '.so' part of the name. */
115 strip_off_ending (base_name, strlen (base_name));
116
117 return base_name;
118 }
119
120
121 /* Create a plugin_name_args object for the give plugin and insert it to
122 the hash table. This function is called when -fplugin=/path/to/NAME.so
123 option is processed. */
124
125 void
126 add_new_plugin (const char* plugin_name)
127 {
128 struct plugin_name_args *plugin;
129 void **slot;
130 char *base_name = get_plugin_base_name (plugin_name);
131
132 /* If this is the first -fplugin= option we encounter, create
133 'plugin_name_args_tab' hash table. */
134 if (!plugin_name_args_tab)
135 plugin_name_args_tab = htab_create (10, htab_hash_string, htab_str_eq,
136 NULL);
137
138 slot = htab_find_slot (plugin_name_args_tab, base_name, INSERT);
139
140 /* If the same plugin (name) has been specified earlier, either emit an
141 error or a warning message depending on if they have identical full
142 (path) names. */
143 if (*slot)
144 {
145 plugin = (struct plugin_name_args *) *slot;
146 if (strcmp (plugin->full_name, plugin_name))
147 error ("Plugin %s was specified with different paths:\n%s\n%s",
148 plugin->base_name, plugin->full_name, plugin_name);
149 return;
150 }
151
152 plugin = XCNEW (struct plugin_name_args);
153 plugin->base_name = base_name;
154 plugin->full_name = plugin_name;
155
156 *slot = plugin;
157 }
158
159
160 /* Parse the -fplugin-arg-<name>-<key>[=<value>] option and create a
161 'plugin_argument' object for the parsed key-value pair. ARG is
162 the <name>-<key>[=<value>] part of the option. */
163
164 void
165 parse_plugin_arg_opt (const char *arg)
166 {
167 size_t len = 0, name_len = 0, key_len = 0, value_len = 0;
168 const char *ptr, *name_start = arg, *key_start = NULL, *value_start = NULL;
169 char *name, *key, *value;
170 void **slot;
171 bool name_parsed = false, key_parsed = false;
172
173 /* Iterate over the ARG string and identify the starting character position
174 of 'name', 'key', and 'value' and their lengths. */
175 for (ptr = arg; *ptr; ++ptr)
176 {
177 /* Only the first '-' encountered is considered a separator between
178 'name' and 'key'. All the subsequent '-'s are considered part of
179 'key'. For example, given -fplugin-arg-foo-bar-primary-key=value,
180 the plugin name is 'foo' and the key is 'bar-primary-key'. */
181 if (*ptr == '-' && !name_parsed)
182 {
183 name_len = len;
184 len = 0;
185 key_start = ptr + 1;
186 name_parsed = true;
187 continue;
188 }
189 else if (*ptr == '=')
190 {
191 if (key_parsed)
192 {
193 error ("Malformed option -fplugin-arg-%s (multiple '=' signs)",
194 arg);
195 return;
196 }
197 key_len = len;
198 len = 0;
199 value_start = ptr + 1;
200 key_parsed = true;
201 continue;
202 }
203 else
204 ++len;
205 }
206
207 if (!key_start)
208 {
209 error ("Malformed option -fplugin-arg-%s (missing -<key>[=<value>])",
210 arg);
211 return;
212 }
213
214 /* If the option doesn't contain the 'value' part, LEN is the KEY_LEN.
215 Otherwise, it is the VALUE_LEN. */
216 if (!value_start)
217 key_len = len;
218 else
219 value_len = len;
220
221 name = XNEWVEC (char, name_len + 1);
222 strncpy (name, name_start, name_len);
223 name[name_len] = '\0';
224
225 /* Check if the named plugin has already been specified earlier in the
226 command-line. */
227 if (plugin_name_args_tab
228 && ((slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT))
229 != NULL))
230 {
231 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
232
233 key = XNEWVEC (char, key_len + 1);
234 strncpy (key, key_start, key_len);
235 key[key_len] = '\0';
236 if (value_start)
237 {
238 value = XNEWVEC (char, value_len + 1);
239 strncpy (value, value_start, value_len);
240 value[value_len] = '\0';
241 }
242 else
243 value = NULL;
244
245 /* Create a plugin_argument object for the parsed key-value pair.
246 If there are already arguments for this plugin, we will need to
247 adjust the argument array size by creating a new array and deleting
248 the old one. If the performance ever becomes an issue, we can
249 change the code by pre-allocating a larger array first. */
250 if (plugin->argc > 0)
251 {
252 struct plugin_argument *args = XNEWVEC (struct plugin_argument,
253 plugin->argc + 1);
254 memcpy (args, plugin->argv,
255 sizeof (struct plugin_argument) * plugin->argc);
256 XDELETEVEC (plugin->argv);
257 plugin->argv = args;
258 ++plugin->argc;
259 }
260 else
261 {
262 gcc_assert (plugin->argv == NULL);
263 plugin->argv = XNEWVEC (struct plugin_argument, 1);
264 plugin->argc = 1;
265 }
266
267 plugin->argv[plugin->argc - 1].key = key;
268 plugin->argv[plugin->argc - 1].value = value;
269 }
270 else
271 error ("Plugin %s should be specified before -fplugin-arg-%s "
272 "in the command line", name, arg);
273
274 /* We don't need the plugin's name anymore. Just release it. */
275 XDELETEVEC (name);
276 }
277
278 /* Register additional plugin information. NAME is the name passed to
279 plugin_init. INFO is the information that should be registered. */
280
281 static void
282 register_plugin_info (const char* name, struct plugin_info *info)
283 {
284 void **slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT);
285 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
286 plugin->version = info->version;
287 plugin->help = info->help;
288 }
289
290 /* Called from the plugin's initialization code. Register a single callback.
291 This function can be called multiple times.
292
293 PLUGIN_NAME - display name for this plugin
294 EVENT - which event the callback is for
295 CALLBACK - the callback to be called at the event
296 USER_DATA - plugin-provided data */
297
298 void
299 register_callback (const char *plugin_name,
300 enum plugin_event event,
301 plugin_callback_func callback,
302 void *user_data)
303 {
304 switch (event)
305 {
306 case PLUGIN_PASS_MANAGER_SETUP:
307 gcc_assert (!callback);
308 register_pass ((struct register_pass_info *) user_data);
309 break;
310 case PLUGIN_INFO:
311 gcc_assert (!callback);
312 register_plugin_info (plugin_name, (struct plugin_info *) user_data);
313 break;
314 case PLUGIN_REGISTER_GGC_ROOTS:
315 gcc_assert (!callback);
316 ggc_register_root_tab ((const struct ggc_root_tab*) user_data);
317 break;
318 case PLUGIN_REGISTER_GGC_CACHES:
319 gcc_assert (!callback);
320 ggc_register_cache_tab ((const struct ggc_cache_tab*) user_data);
321 break;
322 case PLUGIN_FINISH_TYPE:
323 case PLUGIN_START_UNIT:
324 case PLUGIN_FINISH_UNIT:
325 case PLUGIN_CXX_CP_PRE_GENERICIZE:
326 case PLUGIN_GGC_START:
327 case PLUGIN_GGC_MARKING:
328 case PLUGIN_GGC_END:
329 case PLUGIN_ATTRIBUTES:
330 case PLUGIN_PRAGMAS:
331 case PLUGIN_FINISH:
332 {
333 struct callback_info *new_callback;
334 if (!callback)
335 {
336 error ("Plugin %s registered a null callback function "
337 "for event %s", plugin_name, plugin_event_name[event]);
338 return;
339 }
340 new_callback = XNEW (struct callback_info);
341 new_callback->plugin_name = plugin_name;
342 new_callback->func = callback;
343 new_callback->user_data = user_data;
344 new_callback->next = plugin_callbacks[event];
345 plugin_callbacks[event] = new_callback;
346 }
347 break;
348 case PLUGIN_EVENT_LAST:
349 default:
350 error ("Unknown callback event registered by plugin %s",
351 plugin_name);
352 }
353 }
354
355
356 /* Called from inside GCC. Invoke all plug-in callbacks registered with
357 the specified event.
358
359 EVENT - the event identifier
360 GCC_DATA - event-specific data provided by the compiler */
361
362 void
363 invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
364 {
365 timevar_push (TV_PLUGIN_RUN);
366
367 switch (event)
368 {
369 case PLUGIN_FINISH_TYPE:
370 case PLUGIN_START_UNIT:
371 case PLUGIN_FINISH_UNIT:
372 case PLUGIN_CXX_CP_PRE_GENERICIZE:
373 case PLUGIN_ATTRIBUTES:
374 case PLUGIN_PRAGMAS:
375 case PLUGIN_FINISH:
376 case PLUGIN_GGC_START:
377 case PLUGIN_GGC_MARKING:
378 case PLUGIN_GGC_END:
379 {
380 /* Iterate over every callback registered with this event and
381 call it. */
382 struct callback_info *callback = plugin_callbacks[event];
383 for ( ; callback; callback = callback->next)
384 (*callback->func) (gcc_data, callback->user_data);
385 }
386 break;
387
388 case PLUGIN_PASS_MANAGER_SETUP:
389 case PLUGIN_EVENT_LAST:
390 case PLUGIN_REGISTER_GGC_ROOTS:
391 case PLUGIN_REGISTER_GGC_CACHES:
392 default:
393 gcc_assert (false);
394 }
395
396 timevar_pop (TV_PLUGIN_RUN);
397 }
398
399 #ifdef ENABLE_PLUGIN
400 /* We need a union to cast dlsym return value to a function pointer
401 as ISO C forbids assignment between function pointer and 'void *'.
402 Use explicit union instead of __extension__(<union_cast>) for
403 portability. */
404 #define PTR_UNION_TYPE(TOTYPE) union { void *_q; TOTYPE _nq; }
405 #define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
406 #define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
407
408 /* Try to initialize PLUGIN. Return true if successful. */
409
410 static bool
411 try_init_one_plugin (struct plugin_name_args *plugin)
412 {
413 void *dl_handle;
414 plugin_init_func plugin_init;
415 const char *err;
416 PTR_UNION_TYPE (plugin_init_func) plugin_init_union;
417
418 /* We use RTLD_NOW to accelerate binding and detect any mismatch
419 between the API expected by the plugin and the GCC API; we use
420 RTLD_GLOBAL which is useful to plugins which themselves call
421 dlopen. */
422 dl_handle = dlopen (plugin->full_name, RTLD_NOW | RTLD_GLOBAL);
423 if (!dl_handle)
424 {
425 error ("Cannot load plugin %s\n%s", plugin->full_name, dlerror ());
426 return false;
427 }
428
429 /* Clear any existing error. */
430 dlerror ();
431
432 /* Check the plugin license. */
433 if (dlsym (dl_handle, str_license) == NULL)
434 fatal_error ("plugin %s is not licensed under a GPL-compatible license\n"
435 "%s", plugin->full_name, dlerror ());
436
437 PTR_UNION_AS_VOID_PTR (plugin_init_union) =
438 dlsym (dl_handle, str_plugin_init_func_name);
439 plugin_init = PTR_UNION_AS_CAST_PTR (plugin_init_union);
440
441 if ((err = dlerror ()) != NULL)
442 {
443 error ("Cannot find %s in plugin %s\n%s", str_plugin_init_func_name,
444 plugin->full_name, err);
445 return false;
446 }
447
448 /* Call the plugin-provided initialization routine with the arguments. */
449 if ((*plugin_init) (plugin, &gcc_version))
450 {
451 error ("Fail to initialize plugin %s", plugin->full_name);
452 return false;
453 }
454
455 return true;
456 }
457
458
459 /* Routine to dlopen and initialize one plugin. This function is passed to
460 (and called by) the hash table traverse routine. Return 1 for the
461 htab_traverse to continue scan, 0 to stop.
462
463 SLOT - slot of the hash table element
464 INFO - auxiliary pointer handed to hash table traverse routine
465 (unused in this function) */
466
467 static int
468 init_one_plugin (void **slot, void * ARG_UNUSED (info))
469 {
470 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
471 bool ok = try_init_one_plugin (plugin);
472 if (!ok)
473 {
474 htab_remove_elt (plugin_name_args_tab, plugin->base_name);
475 XDELETE (plugin);
476 }
477 return 1;
478 }
479
480 #endif /* ENABLE_PLUGIN */
481
482 /* Main plugin initialization function. Called from compile_file() in
483 toplev.c. */
484
485 void
486 initialize_plugins (void)
487 {
488 /* If no plugin was specified in the command-line, simply return. */
489 if (!plugin_name_args_tab)
490 return;
491
492 timevar_push (TV_PLUGIN_INIT);
493
494 #ifdef ENABLE_PLUGIN
495 /* Traverse and initialize each plugin specified in the command-line. */
496 htab_traverse_noresize (plugin_name_args_tab, init_one_plugin, NULL);
497 #endif
498
499 timevar_pop (TV_PLUGIN_INIT);
500 }
501
502 /* Release memory used by one plugin. */
503
504 static int
505 finalize_one_plugin (void **slot, void * ARG_UNUSED (info))
506 {
507 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
508 XDELETE (plugin);
509 return 1;
510 }
511
512 /* Free memory allocated by the plugin system. */
513
514 void
515 finalize_plugins (void)
516 {
517 if (!plugin_name_args_tab)
518 return;
519
520 /* We can now delete the plugin_name_args object as it will no longer
521 be used. Note that base_name and argv fields (both of which were also
522 dynamically allocated) are not freed as they could still be used by
523 the plugin code. */
524
525 htab_traverse_noresize (plugin_name_args_tab, finalize_one_plugin, NULL);
526
527 /* PLUGIN_NAME_ARGS_TAB is no longer needed, just delete it. */
528 htab_delete (plugin_name_args_tab);
529 plugin_name_args_tab = NULL;
530 }
531
532 /* Used to pass options to htab_traverse callbacks. */
533
534 struct print_options
535 {
536 FILE *file;
537 const char *indent;
538 };
539
540 /* Print the version of one plugin. */
541
542 static int
543 print_version_one_plugin (void **slot, void *data)
544 {
545 struct print_options *opt = (struct print_options *) data;
546 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
547 const char *version = plugin->version ? plugin->version : "Unknown version.";
548
549 fprintf (opt->file, " %s%s: %s\n", opt->indent, plugin->base_name, version);
550 return 1;
551 }
552
553 /* Print the version of each plugin. */
554
555 void
556 print_plugins_versions (FILE *file, const char *indent)
557 {
558 struct print_options opt;
559 opt.file = file;
560 opt.indent = indent;
561 if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
562 return;
563
564 fprintf (file, "%sVersions of loaded plugins:\n", indent);
565 htab_traverse_noresize (plugin_name_args_tab, print_version_one_plugin, &opt);
566 }
567
568 /* Print help for one plugin. SLOT is the hash table slot. DATA is the
569 argument to htab_traverse_noresize. */
570
571 static int
572 print_help_one_plugin (void **slot, void *data)
573 {
574 struct print_options *opt = (struct print_options *) data;
575 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
576 const char *help = plugin->help ? plugin->help : "No help available .";
577
578 char *dup = xstrdup (help);
579 char *p, *nl;
580 fprintf (opt->file, " %s%s:\n", opt->indent, plugin->base_name);
581
582 for (p = nl = dup; nl; p = nl)
583 {
584 nl = strchr (nl, '\n');
585 if (nl)
586 {
587 *nl = '\0';
588 nl++;
589 }
590 fprintf (opt->file, " %s %s\n", opt->indent, p);
591 }
592
593 free (dup);
594 return 1;
595 }
596
597 /* Print help for each plugin. The output goes to FILE and every line starts
598 with INDENT. */
599
600 void
601 print_plugins_help (FILE *file, const char *indent)
602 {
603 struct print_options opt;
604 opt.file = file;
605 opt.indent = indent;
606 if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
607 return;
608
609 fprintf (file, "%sHelp for the loaded plugins:\n", indent);
610 htab_traverse_noresize (plugin_name_args_tab, print_help_one_plugin, &opt);
611 }
612
613
614 /* Return true if plugins have been loaded. */
615
616 bool
617 plugins_active_p (void)
618 {
619 int event;
620
621 for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
622 if (plugin_callbacks[event])
623 return true;
624
625 return false;
626 }
627
628
629 /* Dump to FILE the names and associated events for all the active
630 plugins. */
631
632 void
633 dump_active_plugins (FILE *file)
634 {
635 int event;
636
637 if (!plugins_active_p ())
638 return;
639
640 fprintf (stderr, "Event\t\t\tPlugins\n");
641 for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
642 if (plugin_callbacks[event])
643 {
644 struct callback_info *ci;
645
646 fprintf (file, "%s\t", plugin_event_name[event]);
647
648 for (ci = plugin_callbacks[event]; ci; ci = ci->next)
649 fprintf (file, "%s ", ci->plugin_name);
650
651 fprintf (file, "\n");
652 }
653 }
654
655
656 /* Dump active plugins to stderr. */
657
658 void
659 debug_active_plugins (void)
660 {
661 dump_active_plugins (stderr);
662 }
663
664 /* The default version check. Compares every field in VERSION. */
665
666 bool
667 plugin_default_version_check (struct plugin_gcc_version *gcc_version,
668 struct plugin_gcc_version *plugin_version)
669 {
670 if (!gcc_version || !plugin_version)
671 return false;
672
673 if (strcmp (gcc_version->basever, plugin_version->basever))
674 return false;
675 if (strcmp (gcc_version->datestamp, plugin_version->datestamp))
676 return false;
677 if (strcmp (gcc_version->devphase, plugin_version->devphase))
678 return false;
679 if (strcmp (gcc_version->revision, plugin_version->revision))
680 return false;
681 if (strcmp (gcc_version->configuration_arguments,
682 plugin_version->configuration_arguments))
683 return false;
684 return true;
685 }