1 /* Support for GCC plugin mechanism.
2 Copyright (C) 2009 Free Software Foundation, Inc.
4 This file is part of GCC.
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)
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.
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/>. */
20 /* This file contains the support for GCC plugin mechanism based on the
21 APIs described in doc/plugin.texi. */
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
34 #include "coretypes.h"
37 #include "tree-pass.h"
44 #include "plugin-version.h"
47 #include "highlev-plugin-internal.h"
49 /* Event names as strings. Keep in sync with enum plugin_event. */
50 static const char *plugin_event_name_init
[] =
52 "PLUGIN_PASS_MANAGER_SETUP",
55 "PLUGIN_CXX_CP_PRE_GENERICIZE",
61 "PLUGIN_REGISTER_GGC_ROOTS",
62 "PLUGIN_REGISTER_GGC_CACHES",
66 "unroll_parameter_handler",
68 "all_passes_execution",
70 "all_ipa_passes_start",
71 "all_ipa_passes_execution",
75 "early_gimple_passes_start",
76 "early_gimple_passes_end",
80 const char **plugin_event_name
= plugin_event_name_init
;
82 /* A hash table to map event names the the position of the names in the
84 static htab_t event_tab
;
86 /* Keep track of the limit of allocated events and space ready for
88 int event_last
= PLUGIN_EVENT_LAST
;
89 static int event_horizon
= PLUGIN_EVENT_LAST
;
91 /* Hash table for the plugin_name_args objects created during command-line
93 static htab_t plugin_name_args_tab
= NULL
;
95 /* List node for keeping track of plugin-registered callback. */
98 const char *plugin_name
; /* Name of plugin that registers the callback. */
99 plugin_callback_func func
; /* Callback to be called. */
100 void *user_data
; /* plugin-specified data. */
101 struct callback_info
*next
;
104 /* An array of lists of 'callback_info' objects indexed by the event id. */
105 static struct callback_info
*plugin_callbacks_init
[PLUGIN_EVENT_LAST
];
106 static struct callback_info
**plugin_callbacks
= plugin_callbacks_init
;
110 /* Each plugin should define an initialization function with exactly
112 static const char *str_plugin_init_func_name
= "plugin_init";
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";
119 /* Helper function for the hash table that compares the base_name of the
120 existing entry (S1) with the given string (S2). */
123 htab_str_eq (const void *s1
, const void *s2
)
125 const struct plugin_name_args
*plugin
= (const struct plugin_name_args
*) s1
;
126 return !strcmp (plugin
->base_name
, (const char *) s2
);
130 /* Given a plugin's full-path name FULL_NAME, e.g. /pass/to/NAME.so,
134 get_plugin_base_name (const char *full_name
)
136 /* First get the base name part of the full-path name, i.e. NAME.so. */
137 char *base_name
= xstrdup (lbasename (full_name
));
139 /* Then get rid of '.so' part of the name. */
140 strip_off_ending (base_name
, strlen (base_name
));
146 /* Create a plugin_name_args object for the give plugin and insert it to
147 the hash table. This function is called when -fplugin=/path/to/NAME.so
148 option is processed. */
151 add_new_plugin (const char* plugin_name
)
153 struct plugin_name_args
*plugin
;
155 char *base_name
= get_plugin_base_name (plugin_name
);
157 /* If this is the first -fplugin= option we encounter, create
158 'plugin_name_args_tab' hash table. */
159 if (!plugin_name_args_tab
)
160 plugin_name_args_tab
= htab_create (10, htab_hash_string
, htab_str_eq
,
163 slot
= htab_find_slot (plugin_name_args_tab
, base_name
, INSERT
);
165 /* If the same plugin (name) has been specified earlier, either emit an
166 error or a warning message depending on if they have identical full
170 plugin
= (struct plugin_name_args
*) *slot
;
171 if (strcmp (plugin
->full_name
, plugin_name
))
172 error ("Plugin %s was specified with different paths:\n%s\n%s",
173 plugin
->base_name
, plugin
->full_name
, plugin_name
);
177 plugin
= XCNEW (struct plugin_name_args
);
178 plugin
->base_name
= base_name
;
179 plugin
->full_name
= plugin_name
;
185 /* Parse the -fplugin-arg-<name>-<key>[=<value>] option and create a
186 'plugin_argument' object for the parsed key-value pair. ARG is
187 the <name>-<key>[=<value>] part of the option. */
190 parse_plugin_arg_opt (const char *arg
)
192 size_t len
= 0, name_len
= 0, key_len
= 0, value_len
= 0;
193 const char *ptr
, *name_start
= arg
, *key_start
= NULL
, *value_start
= NULL
;
194 char *name
, *key
, *value
;
196 bool name_parsed
= false, key_parsed
= false;
198 /* Iterate over the ARG string and identify the starting character position
199 of 'name', 'key', and 'value' and their lengths. */
200 for (ptr
= arg
; *ptr
; ++ptr
)
202 /* Only the first '-' encountered is considered a separator between
203 'name' and 'key'. All the subsequent '-'s are considered part of
204 'key'. For example, given -fplugin-arg-foo-bar-primary-key=value,
205 the plugin name is 'foo' and the key is 'bar-primary-key'. */
206 if (*ptr
== '-' && !name_parsed
)
214 else if (*ptr
== '=')
218 error ("Malformed option -fplugin-arg-%s (multiple '=' signs)",
224 value_start
= ptr
+ 1;
234 error ("Malformed option -fplugin-arg-%s (missing -<key>[=<value>])",
239 /* If the option doesn't contain the 'value' part, LEN is the KEY_LEN.
240 Otherwise, it is the VALUE_LEN. */
246 name
= XNEWVEC (char, name_len
+ 1);
247 strncpy (name
, name_start
, name_len
);
248 name
[name_len
] = '\0';
250 /* Check if the named plugin has already been specified earlier in the
252 if (plugin_name_args_tab
253 && ((slot
= htab_find_slot (plugin_name_args_tab
, name
, NO_INSERT
))
256 struct plugin_name_args
*plugin
= (struct plugin_name_args
*) *slot
;
258 key
= XNEWVEC (char, key_len
+ 1);
259 strncpy (key
, key_start
, key_len
);
263 value
= XNEWVEC (char, value_len
+ 1);
264 strncpy (value
, value_start
, value_len
);
265 value
[value_len
] = '\0';
270 /* Create a plugin_argument object for the parsed key-value pair.
271 If there are already arguments for this plugin, we will need to
272 adjust the argument array size by creating a new array and deleting
273 the old one. If the performance ever becomes an issue, we can
274 change the code by pre-allocating a larger array first. */
275 if (plugin
->argc
> 0)
277 struct plugin_argument
*args
= XNEWVEC (struct plugin_argument
,
279 memcpy (args
, plugin
->argv
,
280 sizeof (struct plugin_argument
) * plugin
->argc
);
281 XDELETEVEC (plugin
->argv
);
287 gcc_assert (plugin
->argv
== NULL
);
288 plugin
->argv
= XNEWVEC (struct plugin_argument
, 1);
292 plugin
->argv
[plugin
->argc
- 1].key
= key
;
293 plugin
->argv
[plugin
->argc
- 1].value
= value
;
296 error ("Plugin %s should be specified before -fplugin-arg-%s "
297 "in the command line", name
, arg
);
299 /* We don't need the plugin's name anymore. Just release it. */
303 /* Register additional plugin information. NAME is the name passed to
304 plugin_init. INFO is the information that should be registered. */
307 register_plugin_info (const char* name
, struct plugin_info
*info
)
309 void **slot
= htab_find_slot (plugin_name_args_tab
, name
, NO_INSERT
);
310 struct plugin_name_args
*plugin
= (struct plugin_name_args
*) *slot
;
311 plugin
->version
= info
->version
;
312 plugin
->help
= info
->help
;
315 /* Helper function for the event hash table that compares the name of an
316 existing entry (E1) with the given string (S2). */
319 htab_event_eq (const void *e1
, const void *s2
)
321 const char *s1
= *(const char * const *) e1
;
322 return !strcmp (s1
, (const char *) s2
);
325 /* Look up the event id for NAME. If the name is not found, return -1
326 if INSERT is NO_INSERT. */
328 get_named_event_id (const char *name
, enum insert_option insert
)
336 event_tab
= htab_create (150, htab_hash_string
, htab_event_eq
, NULL
);
337 for (i
= 0; i
< PLUGIN_EVENT_LAST
; i
++)
339 slot
= htab_find_slot (event_tab
, plugin_event_name
[i
], INSERT
);
340 gcc_assert (*slot
== HTAB_EMPTY_ENTRY
);
341 *slot
= &plugin_event_name
[i
];
344 slot
= htab_find_slot (event_tab
, name
, insert
);
347 if (*slot
!= HTAB_EMPTY_ENTRY
)
348 return (const char **) *slot
- &plugin_event_name
[0];
350 if (event_last
>= event_horizon
)
352 event_horizon
= event_last
* 2;
353 if (plugin_event_name
== plugin_event_name_init
)
355 plugin_event_name
= XNEWVEC (const char *, event_horizon
);
356 memcpy (plugin_event_name
, plugin_event_name_init
,
357 sizeof plugin_event_name_init
);
358 plugin_callbacks
= XNEWVEC (struct callback_info
*, event_horizon
);
359 memcpy (plugin_callbacks
, plugin_callbacks_init
,
360 sizeof plugin_callbacks_init
);
365 = XRESIZEVEC (const char *, plugin_event_name
, event_horizon
);
366 plugin_callbacks
= XRESIZEVEC (struct callback_info
*,
367 plugin_callbacks
, event_horizon
);
369 /* All the pointers in the hash table will need to be updated. */
370 htab_delete (event_tab
);
374 *slot
= &plugin_event_name
[event_last
];
375 plugin_event_name
[event_last
] = name
;
379 /* Called from the plugin's initialization code. Register a single callback.
380 This function can be called multiple times.
382 PLUGIN_NAME - display name for this plugin
383 EVENT - which event the callback is for
384 CALLBACK - the callback to be called at the event
385 USER_DATA - plugin-provided data */
388 register_callback (const char *plugin_name
,
390 plugin_callback_func callback
,
395 case PLUGIN_PASS_MANAGER_SETUP
:
396 gcc_assert (!callback
);
397 register_pass ((struct register_pass_info
*) user_data
);
400 gcc_assert (!callback
);
401 register_plugin_info (plugin_name
, (struct plugin_info
*) user_data
);
403 case PLUGIN_REGISTER_GGC_ROOTS
:
404 gcc_assert (!callback
);
405 ggc_register_root_tab ((const struct ggc_root_tab
*) user_data
);
407 case PLUGIN_REGISTER_GGC_CACHES
:
408 gcc_assert (!callback
);
409 ggc_register_cache_tab ((const struct ggc_cache_tab
*) user_data
);
411 case PLUGIN_EVENT_LAST
:
413 if (event
< PLUGIN_FIRST_EXPERIMENTAL
|| event
>= event_last
)
415 error ("Unknown callback event registered by plugin %s",
420 case PLUGIN_FINISH_TYPE
:
421 case PLUGIN_START_UNIT
:
422 case PLUGIN_FINISH_UNIT
:
423 case PLUGIN_CXX_CP_PRE_GENERICIZE
:
424 case PLUGIN_GGC_START
:
425 case PLUGIN_GGC_MARKING
:
427 case PLUGIN_ATTRIBUTES
:
431 struct callback_info
*new_callback
;
434 error ("Plugin %s registered a null callback function "
435 "for event %s", plugin_name
, plugin_event_name
[event
]);
438 new_callback
= XNEW (struct callback_info
);
439 new_callback
->plugin_name
= plugin_name
;
440 new_callback
->func
= callback
;
441 new_callback
->user_data
= user_data
;
442 new_callback
->next
= plugin_callbacks
[event
];
443 plugin_callbacks
[event
] = new_callback
;
450 unregister_callback (const char *plugin_name
, int event
)
452 struct callback_info
*callback
, **cbp
;
454 if (event
>= event_last
)
455 return PLUGEVT_NO_SUCH_EVENT
;
457 for (cbp
= &plugin_callbacks
[event
]; callback
= *cbp
; cbp
= &callback
->next
)
458 if (strcmp (callback
->plugin_name
, plugin_name
) == 0)
460 *cbp
= callback
->next
;
461 return PLUGEVT_SUCCESS
;
463 return PLUGEVT_NO_CALLBACK
;
466 /* Called from inside GCC. Invoke all plug-in callbacks registered with
469 EVENT - the event identifier
470 GCC_DATA - event-specific data provided by the compiler */
473 invoke_plugin_callbacks (int event
, void *gcc_data
)
475 int retval
= PLUGEVT_SUCCESS
;
477 timevar_push (TV_PLUGIN_RUN
);
481 case PLUGIN_EVENT_LAST
:
483 gcc_assert (event
>= PLUGIN_FIRST_EXPERIMENTAL
);
484 gcc_assert (event
< event_last
);
486 case PLUGIN_FINISH_TYPE
:
487 case PLUGIN_START_UNIT
:
488 case PLUGIN_FINISH_UNIT
:
489 case PLUGIN_CXX_CP_PRE_GENERICIZE
:
490 case PLUGIN_ATTRIBUTES
:
493 case PLUGIN_GGC_START
:
494 case PLUGIN_GGC_MARKING
:
497 /* Iterate over every callback registered with this event and
499 struct callback_info
*callback
= plugin_callbacks
[event
];
502 retval
= PLUGEVT_NO_CALLBACK
;
503 for ( ; callback
; callback
= callback
->next
)
504 (*callback
->func
) (gcc_data
, callback
->user_data
);
508 case PLUGIN_PASS_MANAGER_SETUP
:
509 case PLUGIN_REGISTER_GGC_ROOTS
:
510 case PLUGIN_REGISTER_GGC_CACHES
:
514 timevar_pop (TV_PLUGIN_RUN
);
519 invoke_plugin_va_callbacks (int event
, ...)
524 va_start (va
, event
);
525 retval
= invoke_plugin_callbacks (event
, &va
);
531 /* We need a union to cast dlsym return value to a function pointer
532 as ISO C forbids assignment between function pointer and 'void *'.
533 Use explicit union instead of __extension__(<union_cast>) for
535 #define PTR_UNION_TYPE(TOTYPE) union { void *_q; TOTYPE _nq; }
536 #define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
537 #define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
539 /* Try to initialize PLUGIN. Return true if successful. */
542 try_init_one_plugin (struct plugin_name_args
*plugin
)
545 plugin_init_func plugin_init
;
547 PTR_UNION_TYPE (plugin_init_func
) plugin_init_union
;
549 /* We use RTLD_NOW to accelerate binding and detect any mismatch
550 between the API expected by the plugin and the GCC API; we use
551 RTLD_GLOBAL which is useful to plugins which themselves call
553 dl_handle
= dlopen (plugin
->full_name
, RTLD_NOW
| RTLD_GLOBAL
);
556 error ("Cannot load plugin %s\n%s", plugin
->full_name
, dlerror ());
560 /* Clear any existing error. */
563 /* Check the plugin license. */
564 if (dlsym (dl_handle
, str_license
) == NULL
)
565 fatal_error ("plugin %s is not licensed under a GPL-compatible license\n"
566 "%s", plugin
->full_name
, dlerror ());
568 PTR_UNION_AS_VOID_PTR (plugin_init_union
) =
569 dlsym (dl_handle
, str_plugin_init_func_name
);
570 plugin_init
= PTR_UNION_AS_CAST_PTR (plugin_init_union
);
572 if ((err
= dlerror ()) != NULL
)
574 error ("Cannot find %s in plugin %s\n%s", str_plugin_init_func_name
,
575 plugin
->full_name
, err
);
579 /* Call the plugin-provided initialization routine with the arguments. */
580 if ((*plugin_init
) (plugin
, &gcc_version
))
582 error ("Fail to initialize plugin %s", plugin
->full_name
);
590 /* Routine to dlopen and initialize one plugin. This function is passed to
591 (and called by) the hash table traverse routine. Return 1 for the
592 htab_traverse to continue scan, 0 to stop.
594 SLOT - slot of the hash table element
595 INFO - auxiliary pointer handed to hash table traverse routine
596 (unused in this function) */
599 init_one_plugin (void **slot
, void * ARG_UNUSED (info
))
601 struct plugin_name_args
*plugin
= (struct plugin_name_args
*) *slot
;
602 bool ok
= try_init_one_plugin (plugin
);
605 htab_remove_elt (plugin_name_args_tab
, plugin
->base_name
);
611 #endif /* ENABLE_PLUGIN */
613 /* Main plugin initialization function. Called from compile_file() in
617 initialize_plugins (void)
619 /* Loads ICI plugin */
622 /* If no plugin was specified in the command-line, simply return. */
623 if (!plugin_name_args_tab
)
626 timevar_push (TV_PLUGIN_INIT
);
629 /* Traverse and initialize each plugin specified in the command-line. */
630 htab_traverse_noresize (plugin_name_args_tab
, init_one_plugin
, NULL
);
633 timevar_pop (TV_PLUGIN_INIT
);
636 /* Release memory used by one plugin. */
639 finalize_one_plugin (void **slot
, void * ARG_UNUSED (info
))
641 struct plugin_name_args
*plugin
= (struct plugin_name_args
*) *slot
;
646 /* Free memory allocated by the plugin system. */
649 finalize_plugins (void)
651 if (!plugin_name_args_tab
)
654 /* We can now delete the plugin_name_args object as it will no longer
655 be used. Note that base_name and argv fields (both of which were also
656 dynamically allocated) are not freed as they could still be used by
659 htab_traverse_noresize (plugin_name_args_tab
, finalize_one_plugin
, NULL
);
661 /* PLUGIN_NAME_ARGS_TAB is no longer needed, just delete it. */
662 htab_delete (plugin_name_args_tab
);
663 plugin_name_args_tab
= NULL
;
666 /* Used to pass options to htab_traverse callbacks. */
674 /* Print the version of one plugin. */
677 print_version_one_plugin (void **slot
, void *data
)
679 struct print_options
*opt
= (struct print_options
*) data
;
680 struct plugin_name_args
*plugin
= (struct plugin_name_args
*) *slot
;
681 const char *version
= plugin
->version
? plugin
->version
: "Unknown version.";
683 fprintf (opt
->file
, " %s%s: %s\n", opt
->indent
, plugin
->base_name
, version
);
687 /* Print the version of each plugin. */
690 print_plugins_versions (FILE *file
, const char *indent
)
692 struct print_options opt
;
695 if (!plugin_name_args_tab
|| htab_elements (plugin_name_args_tab
) == 0)
698 fprintf (file
, "%sVersions of loaded plugins:\n", indent
);
699 htab_traverse_noresize (plugin_name_args_tab
, print_version_one_plugin
, &opt
);
702 /* Print help for one plugin. SLOT is the hash table slot. DATA is the
703 argument to htab_traverse_noresize. */
706 print_help_one_plugin (void **slot
, void *data
)
708 struct print_options
*opt
= (struct print_options
*) data
;
709 struct plugin_name_args
*plugin
= (struct plugin_name_args
*) *slot
;
710 const char *help
= plugin
->help
? plugin
->help
: "No help available .";
712 char *dup
= xstrdup (help
);
714 fprintf (opt
->file
, " %s%s:\n", opt
->indent
, plugin
->base_name
);
716 for (p
= nl
= dup
; nl
; p
= nl
)
718 nl
= strchr (nl
, '\n');
724 fprintf (opt
->file
, " %s %s\n", opt
->indent
, p
);
731 /* Print help for each plugin. The output goes to FILE and every line starts
735 print_plugins_help (FILE *file
, const char *indent
)
737 struct print_options opt
;
740 if (!plugin_name_args_tab
|| htab_elements (plugin_name_args_tab
) == 0)
743 fprintf (file
, "%sHelp for the loaded plugins:\n", indent
);
744 htab_traverse_noresize (plugin_name_args_tab
, print_help_one_plugin
, &opt
);
748 /* Return true if plugins have been loaded. */
751 plugins_active_p (void)
755 for (event
= PLUGIN_PASS_MANAGER_SETUP
; event
< event_last
; event
++)
756 if (plugin_callbacks
[event
])
763 /* Dump to FILE the names and associated events for all the active
767 dump_active_plugins (FILE *file
)
771 if (!plugins_active_p ())
774 fprintf (stderr
, "Event\t\t\tPlugins\n");
775 for (event
= PLUGIN_PASS_MANAGER_SETUP
; event
< event_last
; event
++)
776 if (plugin_callbacks
[event
])
778 struct callback_info
*ci
;
780 fprintf (file
, "%s\t", plugin_event_name
[event
]);
782 for (ci
= plugin_callbacks
[event
]; ci
; ci
= ci
->next
)
783 fprintf (file
, "%s ", ci
->plugin_name
);
785 fprintf (file
, "\n");
790 /* Dump active plugins to stderr. */
793 debug_active_plugins (void)
795 dump_active_plugins (stderr
);
798 /* The default version check. Compares every field in VERSION. */
801 plugin_default_version_check (struct plugin_gcc_version
*gcc_version
,
802 struct plugin_gcc_version
*plugin_version
)
804 if (!gcc_version
|| !plugin_version
)
807 if (strcmp (gcc_version
->basever
, plugin_version
->basever
))
809 if (strcmp (gcc_version
->datestamp
, plugin_version
->datestamp
))
811 if (strcmp (gcc_version
->devphase
, plugin_version
->devphase
))
813 if (strcmp (gcc_version
->revision
, plugin_version
->revision
))
815 if (strcmp (gcc_version
->configuration_arguments
,
816 plugin_version
->configuration_arguments
))