comparison gcc/plugin.c @ 16:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
comparison
equal deleted inserted replaced
15:561a7518be6b 16:04ced10e8804
1 /* Support for GCC plugin mechanism. 1 /* Support for GCC plugin mechanism.
2 Copyright (C) 2009, 2010 Free Software Foundation, Inc. 2 Copyright (C) 2009-2017 Free Software Foundation, Inc.
3 3
4 This file is part of GCC. 4 This file is part of GCC.
5 5
6 GCC is free software; you can redistribute it and/or modify 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 7 it under the terms of the GNU General Public License as published by
21 APIs described in doc/plugin.texi. */ 21 APIs described in doc/plugin.texi. */
22 22
23 #include "config.h" 23 #include "config.h"
24 #include "system.h" 24 #include "system.h"
25 #include "coretypes.h" 25 #include "coretypes.h"
26 #include "options.h"
27 #include "tree-pass.h"
26 #include "diagnostic-core.h" 28 #include "diagnostic-core.h"
27 #include "tree.h" 29 #include "flags.h"
28 #include "tree-pass.h"
29 #include "intl.h" 30 #include "intl.h"
30 #include "plugin.h" 31 #include "plugin.h"
31 #include "timevar.h"
32 #include "ggc.h"
33 32
34 #ifdef ENABLE_PLUGIN 33 #ifdef ENABLE_PLUGIN
35 #include "plugin-version.h" 34 #include "plugin-version.h"
36 #endif 35 #endif
37 36
49 /* A printf format large enough for the largest event above. */ 48 /* A printf format large enough for the largest event above. */
50 #define FMT_FOR_PLUGIN_EVENT "%-32s" 49 #define FMT_FOR_PLUGIN_EVENT "%-32s"
51 50
52 const char **plugin_event_name = plugin_event_name_init; 51 const char **plugin_event_name = plugin_event_name_init;
53 52
53 /* Event hashtable helpers. */
54
55 struct event_hasher : nofree_ptr_hash <const char *>
56 {
57 static inline hashval_t hash (const char **);
58 static inline bool equal (const char **, const char **);
59 };
60
61 /* Helper function for the event hash table that hashes the entry V. */
62
63 inline hashval_t
64 event_hasher::hash (const char **v)
65 {
66 return htab_hash_string (*v);
67 }
68
69 /* Helper function for the event hash table that compares the name of an
70 existing entry (S1) with the given string (S2). */
71
72 inline bool
73 event_hasher::equal (const char **s1, const char **s2)
74 {
75 return !strcmp (*s1, *s2);
76 }
77
54 /* A hash table to map event names to the position of the names in the 78 /* A hash table to map event names to the position of the names in the
55 plugin_event_name table. */ 79 plugin_event_name table. */
56 static htab_t event_tab; 80 static hash_table<event_hasher> *event_tab;
57 81
58 /* Keep track of the limit of allocated events and space ready for 82 /* Keep track of the limit of allocated events and space ready for
59 allocating events. */ 83 allocating events. */
60 static int event_last = PLUGIN_EVENT_FIRST_DYNAMIC; 84 static int event_last = PLUGIN_EVENT_FIRST_DYNAMIC;
61 static int event_horizon = PLUGIN_EVENT_FIRST_DYNAMIC; 85 static int event_horizon = PLUGIN_EVENT_FIRST_DYNAMIC;
87 111
88 /* Each plugin should define this symbol to assert that it is 112 /* Each plugin should define this symbol to assert that it is
89 distributed under a GPL-compatible license. */ 113 distributed under a GPL-compatible license. */
90 static const char *str_license = "plugin_is_GPL_compatible"; 114 static const char *str_license = "plugin_is_GPL_compatible";
91 #endif 115 #endif
116
117 /* Helper function for hashing the base_name of the plugin_name_args
118 structure to be inserted into the hash table. */
119
120 static hashval_t
121 htab_hash_plugin (const PTR p)
122 {
123 const struct plugin_name_args *plugin = (const struct plugin_name_args *) p;
124 return htab_hash_string (plugin->base_name);
125 }
92 126
93 /* Helper function for the hash table that compares the base_name of the 127 /* Helper function for the hash table that compares the base_name of the
94 existing entry (S1) with the given string (S2). */ 128 existing entry (S1) with the given string (S2). */
95 129
96 static int 130 static int
147 Windows or MacOS, this code has to be greatly improved. */ 181 Windows or MacOS, this code has to be greatly improved. */
148 plugin_name = concat (default_plugin_dir_name (), "/", 182 plugin_name = concat (default_plugin_dir_name (), "/",
149 plugin_name, ".so", NULL); 183 plugin_name, ".so", NULL);
150 if (access (plugin_name, R_OK)) 184 if (access (plugin_name, R_OK))
151 fatal_error 185 fatal_error
152 ("inacessible plugin file %s expanded from short plugin name %s: %m", 186 (input_location,
187 "inaccessible plugin file %s expanded from short plugin name %s: %m",
153 plugin_name, base_name); 188 plugin_name, base_name);
154 } 189 }
155 else 190 else
156 base_name = get_plugin_base_name (plugin_name); 191 base_name = get_plugin_base_name (plugin_name);
157 192
158 /* If this is the first -fplugin= option we encounter, create 193 /* If this is the first -fplugin= option we encounter, create
159 'plugin_name_args_tab' hash table. */ 194 'plugin_name_args_tab' hash table. */
160 if (!plugin_name_args_tab) 195 if (!plugin_name_args_tab)
161 plugin_name_args_tab = htab_create (10, htab_hash_string, htab_str_eq, 196 plugin_name_args_tab = htab_create (10, htab_hash_plugin, htab_str_eq,
162 NULL); 197 NULL);
163 198
164 slot = htab_find_slot (plugin_name_args_tab, base_name, INSERT); 199 slot = htab_find_slot_with_hash (plugin_name_args_tab, base_name,
200 htab_hash_string (base_name), INSERT);
165 201
166 /* If the same plugin (name) has been specified earlier, either emit an 202 /* If the same plugin (name) has been specified earlier, either emit an
167 error or a warning message depending on if they have identical full 203 error or a warning message depending on if they have identical full
168 (path) names. */ 204 (path) names. */
169 if (*slot) 205 if (*slot)
212 name_parsed = true; 248 name_parsed = true;
213 continue; 249 continue;
214 } 250 }
215 else if (*ptr == '=') 251 else if (*ptr == '=')
216 { 252 {
217 if (key_parsed) 253 if (!key_parsed)
218 { 254 {
219 error ("malformed option -fplugin-arg-%s (multiple '=' signs)", 255 key_len = len;
220 arg); 256 len = 0;
221 return; 257 value_start = ptr + 1;
222 } 258 key_parsed = true;
223 key_len = len; 259 }
224 len = 0;
225 value_start = ptr + 1;
226 key_parsed = true;
227 continue; 260 continue;
228 } 261 }
229 else 262 else
230 ++len; 263 ++len;
231 } 264 }
249 name[name_len] = '\0'; 282 name[name_len] = '\0';
250 283
251 /* Check if the named plugin has already been specified earlier in the 284 /* Check if the named plugin has already been specified earlier in the
252 command-line. */ 285 command-line. */
253 if (plugin_name_args_tab 286 if (plugin_name_args_tab
254 && ((slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT)) 287 && ((slot = htab_find_slot_with_hash (plugin_name_args_tab, name,
288 htab_hash_string (name), NO_INSERT))
255 != NULL)) 289 != NULL))
256 { 290 {
257 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot; 291 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
258 292
259 key = XNEWVEC (char, key_len + 1); 293 key = XNEWVEC (char, key_len + 1);
305 plugin_init. INFO is the information that should be registered. */ 339 plugin_init. INFO is the information that should be registered. */
306 340
307 static void 341 static void
308 register_plugin_info (const char* name, struct plugin_info *info) 342 register_plugin_info (const char* name, struct plugin_info *info)
309 { 343 {
310 void **slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT); 344 void **slot = htab_find_slot_with_hash (plugin_name_args_tab, name,
311 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot; 345 htab_hash_string (name), NO_INSERT);
346 struct plugin_name_args *plugin;
347
348 if (slot == NULL)
349 {
350 error ("unable to register info for plugin %qs - plugin name not found",
351 name);
352 return;
353 }
354 plugin = (struct plugin_name_args *) *slot;
312 plugin->version = info->version; 355 plugin->version = info->version;
313 plugin->help = info->help; 356 plugin->help = info->help;
314 } 357 }
315 358
316 /* Helper function for the event hash table that compares the name of an
317 existing entry (E1) with the given string (S2). */
318
319 static int
320 htab_event_eq (const void *e1, const void *s2)
321 {
322 const char *s1= *(const char * const *) e1;
323 return !strcmp (s1, (const char *) s2);
324 }
325
326 /* Look up the event id for NAME. If the name is not found, return -1 359 /* Look up the event id for NAME. If the name is not found, return -1
327 if INSERT is NO_INSERT. */ 360 if INSERT is NO_INSERT. */
328 361
329 int 362 int
330 get_named_event_id (const char *name, enum insert_option insert) 363 get_named_event_id (const char *name, enum insert_option insert)
331 { 364 {
332 void **slot; 365 const char ***slot;
333 366
334 if (!event_tab) 367 if (!event_tab)
335 { 368 {
336 int i; 369 int i;
337 370
338 event_tab = htab_create (150, htab_hash_string, htab_event_eq, NULL); 371 event_tab = new hash_table<event_hasher> (150);
339 for (i = 0; i < event_last; i++) 372 for (i = 0; i < event_last; i++)
340 { 373 {
341 slot = htab_find_slot (event_tab, plugin_event_name[i], INSERT); 374 slot = event_tab->find_slot (&plugin_event_name[i], INSERT);
342 gcc_assert (*slot == HTAB_EMPTY_ENTRY); 375 gcc_assert (*slot == HTAB_EMPTY_ENTRY);
343 *slot = &plugin_event_name[i]; 376 *slot = &plugin_event_name[i];
344 } 377 }
345 } 378 }
346 slot = htab_find_slot (event_tab, name, insert); 379 slot = event_tab->find_slot (&name, insert);
347 if (slot == NULL) 380 if (slot == NULL)
348 return -1; 381 return -1;
349 if (*slot != HTAB_EMPTY_ENTRY) 382 if (*slot != HTAB_EMPTY_ENTRY)
350 return (const char **) *slot - &plugin_event_name[0]; 383 return *slot - &plugin_event_name[0];
351 384
352 if (event_last >= event_horizon) 385 if (event_last >= event_horizon)
353 { 386 {
354 event_horizon = event_last * 2; 387 event_horizon = event_last * 2;
355 if (plugin_event_name == plugin_event_name_init) 388 if (plugin_event_name == plugin_event_name_init)
367 = XRESIZEVEC (const char *, plugin_event_name, event_horizon); 400 = XRESIZEVEC (const char *, plugin_event_name, event_horizon);
368 plugin_callbacks = XRESIZEVEC (struct callback_info *, 401 plugin_callbacks = XRESIZEVEC (struct callback_info *,
369 plugin_callbacks, event_horizon); 402 plugin_callbacks, event_horizon);
370 } 403 }
371 /* All the pointers in the hash table will need to be updated. */ 404 /* All the pointers in the hash table will need to be updated. */
372 htab_delete (event_tab); 405 delete event_tab;
373 event_tab = NULL; 406 event_tab = NULL;
374 } 407 }
375 else 408 else
376 *slot = &plugin_event_name[event_last]; 409 *slot = &plugin_event_name[event_last];
377 plugin_event_name[event_last] = name; 410 plugin_event_name[event_last] = name;
404 break; 437 break;
405 case PLUGIN_REGISTER_GGC_ROOTS: 438 case PLUGIN_REGISTER_GGC_ROOTS:
406 gcc_assert (!callback); 439 gcc_assert (!callback);
407 ggc_register_root_tab ((const struct ggc_root_tab*) user_data); 440 ggc_register_root_tab ((const struct ggc_root_tab*) user_data);
408 break; 441 break;
409 case PLUGIN_REGISTER_GGC_CACHES:
410 gcc_assert (!callback);
411 ggc_register_cache_tab ((const struct ggc_cache_tab*) user_data);
412 break;
413 case PLUGIN_EVENT_FIRST_DYNAMIC: 442 case PLUGIN_EVENT_FIRST_DYNAMIC:
414 default: 443 default:
415 if (event < PLUGIN_EVENT_FIRST_DYNAMIC || event >= event_last) 444 if (event < PLUGIN_EVENT_FIRST_DYNAMIC || event >= event_last)
416 { 445 {
417 error ("unknown callback event registered by plugin %s", 446 error ("unknown callback event registered by plugin %s",
418 plugin_name); 447 plugin_name);
419 return; 448 return;
420 } 449 }
421 /* Fall through. */ 450 /* Fall through. */
451 case PLUGIN_START_PARSE_FUNCTION:
452 case PLUGIN_FINISH_PARSE_FUNCTION:
422 case PLUGIN_FINISH_TYPE: 453 case PLUGIN_FINISH_TYPE:
454 case PLUGIN_FINISH_DECL:
423 case PLUGIN_START_UNIT: 455 case PLUGIN_START_UNIT:
424 case PLUGIN_FINISH_UNIT: 456 case PLUGIN_FINISH_UNIT:
425 case PLUGIN_PRE_GENERICIZE: 457 case PLUGIN_PRE_GENERICIZE:
426 case PLUGIN_GGC_START: 458 case PLUGIN_GGC_START:
427 case PLUGIN_GGC_MARKING: 459 case PLUGIN_GGC_MARKING:
436 case PLUGIN_OVERRIDE_GATE: 468 case PLUGIN_OVERRIDE_GATE:
437 case PLUGIN_PASS_EXECUTION: 469 case PLUGIN_PASS_EXECUTION:
438 case PLUGIN_EARLY_GIMPLE_PASSES_START: 470 case PLUGIN_EARLY_GIMPLE_PASSES_START:
439 case PLUGIN_EARLY_GIMPLE_PASSES_END: 471 case PLUGIN_EARLY_GIMPLE_PASSES_END:
440 case PLUGIN_NEW_PASS: 472 case PLUGIN_NEW_PASS:
473 case PLUGIN_INCLUDE_FILE:
441 { 474 {
442 struct callback_info *new_callback; 475 struct callback_info *new_callback;
443 if (!callback) 476 if (!callback)
444 { 477 {
445 error ("plugin %s registered a null callback function " 478 error ("plugin %s registered a null callback function "
493 case PLUGIN_EVENT_FIRST_DYNAMIC: 526 case PLUGIN_EVENT_FIRST_DYNAMIC:
494 default: 527 default:
495 gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC); 528 gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC);
496 gcc_assert (event < event_last); 529 gcc_assert (event < event_last);
497 /* Fall through. */ 530 /* Fall through. */
531 case PLUGIN_START_PARSE_FUNCTION:
532 case PLUGIN_FINISH_PARSE_FUNCTION:
498 case PLUGIN_FINISH_TYPE: 533 case PLUGIN_FINISH_TYPE:
534 case PLUGIN_FINISH_DECL:
499 case PLUGIN_START_UNIT: 535 case PLUGIN_START_UNIT:
500 case PLUGIN_FINISH_UNIT: 536 case PLUGIN_FINISH_UNIT:
501 case PLUGIN_PRE_GENERICIZE: 537 case PLUGIN_PRE_GENERICIZE:
502 case PLUGIN_ATTRIBUTES: 538 case PLUGIN_ATTRIBUTES:
503 case PLUGIN_PRAGMAS: 539 case PLUGIN_PRAGMAS:
512 case PLUGIN_OVERRIDE_GATE: 548 case PLUGIN_OVERRIDE_GATE:
513 case PLUGIN_PASS_EXECUTION: 549 case PLUGIN_PASS_EXECUTION:
514 case PLUGIN_EARLY_GIMPLE_PASSES_START: 550 case PLUGIN_EARLY_GIMPLE_PASSES_START:
515 case PLUGIN_EARLY_GIMPLE_PASSES_END: 551 case PLUGIN_EARLY_GIMPLE_PASSES_END:
516 case PLUGIN_NEW_PASS: 552 case PLUGIN_NEW_PASS:
553 case PLUGIN_INCLUDE_FILE:
517 { 554 {
518 /* Iterate over every callback registered with this event and 555 /* Iterate over every callback registered with this event and
519 call it. */ 556 call it. */
520 struct callback_info *callback = plugin_callbacks[event]; 557 struct callback_info *callback = plugin_callbacks[event];
521 558
526 } 563 }
527 break; 564 break;
528 565
529 case PLUGIN_PASS_MANAGER_SETUP: 566 case PLUGIN_PASS_MANAGER_SETUP:
530 case PLUGIN_REGISTER_GGC_ROOTS: 567 case PLUGIN_REGISTER_GGC_ROOTS:
531 case PLUGIN_REGISTER_GGC_CACHES:
532 gcc_assert (false); 568 gcc_assert (false);
533 } 569 }
534 570
535 timevar_pop (TV_PLUGIN_RUN); 571 timevar_pop (TV_PLUGIN_RUN);
536 return retval; 572 return retval;
569 /* Clear any existing error. */ 605 /* Clear any existing error. */
570 dlerror (); 606 dlerror ();
571 607
572 /* Check the plugin license. */ 608 /* Check the plugin license. */
573 if (dlsym (dl_handle, str_license) == NULL) 609 if (dlsym (dl_handle, str_license) == NULL)
574 fatal_error ("plugin %s is not licensed under a GPL-compatible license\n" 610 fatal_error (input_location,
611 "plugin %s is not licensed under a GPL-compatible license\n"
575 "%s", plugin->full_name, dlerror ()); 612 "%s", plugin->full_name, dlerror ());
576 613
577 PTR_UNION_AS_VOID_PTR (plugin_init_union) = 614 PTR_UNION_AS_VOID_PTR (plugin_init_union) =
578 dlsym (dl_handle, str_plugin_init_func_name); 615 dlsym (dl_handle, str_plugin_init_func_name);
579 plugin_init = PTR_UNION_AS_CAST_PTR (plugin_init_union); 616 plugin_init = PTR_UNION_AS_CAST_PTR (plugin_init_union);
580 617
581 if ((err = dlerror ()) != NULL) 618 if ((err = dlerror ()) != NULL)
582 { 619 {
620 dlclose(dl_handle);
583 error ("cannot find %s in plugin %s\n%s", str_plugin_init_func_name, 621 error ("cannot find %s in plugin %s\n%s", str_plugin_init_func_name,
584 plugin->full_name, err); 622 plugin->full_name, err);
585 return false; 623 return false;
586 } 624 }
587 625
588 /* Call the plugin-provided initialization routine with the arguments. */ 626 /* Call the plugin-provided initialization routine with the arguments. */
589 if ((*plugin_init) (plugin, &gcc_version)) 627 if ((*plugin_init) (plugin, &gcc_version))
590 { 628 {
629 dlclose(dl_handle);
591 error ("fail to initialize plugin %s", plugin->full_name); 630 error ("fail to initialize plugin %s", plugin->full_name);
592 return false; 631 return false;
593 } 632 }
594 633 /* leak dl_handle on purpose to ensure the plugin is loaded for the
634 entire run of the compiler. */
595 return true; 635 return true;
596 } 636 }
597 637
598 638
599 /* Routine to dlopen and initialize one plugin. This function is passed to 639 /* Routine to dlopen and initialize one plugin. This function is passed to
609 { 649 {
610 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot; 650 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
611 bool ok = try_init_one_plugin (plugin); 651 bool ok = try_init_one_plugin (plugin);
612 if (!ok) 652 if (!ok)
613 { 653 {
614 htab_remove_elt (plugin_name_args_tab, plugin->base_name); 654 htab_remove_elt_with_hash (plugin_name_args_tab, plugin->base_name,
655 htab_hash_string (plugin->base_name));
615 XDELETE (plugin); 656 XDELETE (plugin);
616 } 657 }
617 return 1; 658 return 1;
618 } 659 }
619 660
786 fprintf (file, FMT_FOR_PLUGIN_EVENT " |", plugin_event_name[event]); 827 fprintf (file, FMT_FOR_PLUGIN_EVENT " |", plugin_event_name[event]);
787 828
788 for (ci = plugin_callbacks[event]; ci; ci = ci->next) 829 for (ci = plugin_callbacks[event]; ci; ci = ci->next)
789 fprintf (file, " %s", ci->plugin_name); 830 fprintf (file, " %s", ci->plugin_name);
790 831
791 putc('\n', file); 832 putc ('\n', file);
792 } 833 }
793 } 834 }
794 835
795 836
796 /* Dump active plugins to stderr. */ 837 /* Dump active plugins to stderr. */
813 " this as a bug unless you can reproduce it without enabling" 854 " this as a bug unless you can reproduce it without enabling"
814 " any plugins.\n"); 855 " any plugins.\n");
815 dump_active_plugins (stderr); 856 dump_active_plugins (stderr);
816 } 857 }
817 858
818 }
819
820 /* Likewise, as a callback from the diagnostics code. */
821
822 void
823 plugins_internal_error_function (diagnostic_context *context ATTRIBUTE_UNUSED,
824 const char *msgid ATTRIBUTE_UNUSED,
825 va_list *ap ATTRIBUTE_UNUSED)
826 {
827 warn_if_plugins ();
828 } 859 }
829 860
830 /* The default version check. Compares every field in VERSION. */ 861 /* The default version check. Compares every field in VERSION. */
831 862
832 bool 863 bool
861 return event_last; 892 return event_last;
862 } 893 }
863 894
864 895
865 /* Retrieve the default plugin directory. The gcc driver should have passed 896 /* Retrieve the default plugin directory. The gcc driver should have passed
866 it as -iplugindir <dir> to the cc1 program, and it is queriable thru the 897 it as -iplugindir <dir> to the cc1 program, and it is queriable through the
867 -print-file-name=plugin option to gcc. */ 898 -print-file-name=plugin option to gcc. */
868 const char* 899 const char*
869 default_plugin_dir_name (void) 900 default_plugin_dir_name (void)
870 { 901 {
871 if (!plugindir_string) 902 if (!plugindir_string)
872 fatal_error ("-iplugindir <dir> option not passed from the gcc driver"); 903 fatal_error (input_location,
904 "-iplugindir <dir> option not passed from the gcc driver");
873 return plugindir_string; 905 return plugindir_string;
874 } 906 }