diff gcc/plugin.c @ 16:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
line wrap: on
line diff
--- a/gcc/plugin.c	Sun Aug 21 07:07:55 2011 +0900
+++ b/gcc/plugin.c	Fri Oct 27 22:46:09 2017 +0900
@@ -1,5 +1,5 @@
 /* Support for GCC plugin mechanism.
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -23,13 +23,12 @@
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "options.h"
+#include "tree-pass.h"
 #include "diagnostic-core.h"
-#include "tree.h"
-#include "tree-pass.h"
+#include "flags.h"
 #include "intl.h"
 #include "plugin.h"
-#include "timevar.h"
-#include "ggc.h"
 
 #ifdef ENABLE_PLUGIN
 #include "plugin-version.h"
@@ -51,9 +50,34 @@
 
 const char **plugin_event_name = plugin_event_name_init;
 
+/* Event hashtable helpers.  */
+
+struct event_hasher : nofree_ptr_hash <const char *>
+{
+  static inline hashval_t hash (const char **);
+  static inline bool equal (const char **, const char **);
+};
+
+/* Helper function for the event hash table that hashes the entry V.  */
+
+inline hashval_t
+event_hasher::hash (const char **v)
+{
+  return htab_hash_string (*v);
+}
+
+/* Helper function for the event hash table that compares the name of an
+   existing entry (S1) with the given string (S2).  */
+
+inline bool
+event_hasher::equal (const char **s1, const char **s2)
+{
+  return !strcmp (*s1, *s2);
+}
+
 /* A hash table to map event names to the position of the names in the
    plugin_event_name table.  */
-static htab_t event_tab;
+static hash_table<event_hasher> *event_tab;
 
 /* Keep track of the limit of allocated events and space ready for
    allocating events.  */
@@ -90,6 +114,16 @@
 static const char *str_license = "plugin_is_GPL_compatible";
 #endif
 
+/* Helper function for hashing the base_name of the plugin_name_args
+   structure to be inserted into the hash table.  */
+
+static hashval_t
+htab_hash_plugin (const PTR p)
+{
+  const struct plugin_name_args *plugin = (const struct plugin_name_args *) p;
+  return htab_hash_string (plugin->base_name);
+ }
+
 /* Helper function for the hash table that compares the base_name of the
    existing entry (S1) with the given string (S2).  */
 
@@ -149,7 +183,8 @@
 			    plugin_name, ".so", NULL);
       if (access (plugin_name, R_OK))
 	fatal_error
-	  ("inacessible plugin file %s expanded from short plugin name %s: %m",
+	  (input_location,
+	   "inaccessible plugin file %s expanded from short plugin name %s: %m",
 	   plugin_name, base_name);
     }
   else
@@ -158,10 +193,11 @@
   /* If this is the first -fplugin= option we encounter, create
      'plugin_name_args_tab' hash table.  */
   if (!plugin_name_args_tab)
-    plugin_name_args_tab = htab_create (10, htab_hash_string, htab_str_eq,
+    plugin_name_args_tab = htab_create (10, htab_hash_plugin, htab_str_eq,
                                         NULL);
 
-  slot = htab_find_slot (plugin_name_args_tab, base_name, INSERT);
+  slot = htab_find_slot_with_hash (plugin_name_args_tab, base_name,
+				   htab_hash_string (base_name), INSERT);
 
   /* If the same plugin (name) has been specified earlier, either emit an
      error or a warning message depending on if they have identical full
@@ -214,16 +250,13 @@
         }
       else if (*ptr == '=')
         {
-          if (key_parsed)
-            {
-              error ("malformed option -fplugin-arg-%s (multiple '=' signs)",
-		     arg);
-              return;
-            }
-          key_len = len;
-          len = 0;
-          value_start = ptr + 1;
-          key_parsed = true;
+	  if (!key_parsed) 
+	    {
+	      key_len = len;
+	      len = 0;
+	      value_start = ptr + 1;
+	      key_parsed = true;
+	    }
           continue;
         }
       else
@@ -251,7 +284,8 @@
   /* Check if the named plugin has already been specified earlier in the
      command-line.  */
   if (plugin_name_args_tab
-      && ((slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT))
+      && ((slot = htab_find_slot_with_hash (plugin_name_args_tab, name,
+					    htab_hash_string (name), NO_INSERT))
           != NULL))
     {
       struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
@@ -307,47 +341,46 @@
 static void
 register_plugin_info (const char* name, struct plugin_info *info)
 {
-  void **slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT);
-  struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
+  void **slot = htab_find_slot_with_hash (plugin_name_args_tab, name,
+					  htab_hash_string (name), NO_INSERT);
+  struct plugin_name_args *plugin;
+
+  if (slot == NULL)
+    {
+      error ("unable to register info for plugin %qs - plugin name not found",
+	     name);
+      return;
+    }
+  plugin = (struct plugin_name_args *) *slot;
   plugin->version = info->version;
   plugin->help = info->help;
 }
 
-/* Helper function for the event hash table that compares the name of an
-   existing entry (E1) with the given string (S2).  */
-
-static int
-htab_event_eq (const void *e1, const void *s2)
-{
-  const char *s1= *(const char * const *) e1;
-  return !strcmp (s1, (const char *) s2);
-}
-
 /* Look up the event id for NAME.  If the name is not found, return -1
    if INSERT is NO_INSERT.  */
 
 int
 get_named_event_id (const char *name, enum insert_option insert)
 {
-  void **slot;
+  const char ***slot;
 
   if (!event_tab)
     {
       int i;
 
-      event_tab = htab_create (150, htab_hash_string, htab_event_eq, NULL);
+      event_tab = new hash_table<event_hasher> (150);
       for (i = 0; i < event_last; i++)
 	{
-	  slot = htab_find_slot (event_tab, plugin_event_name[i], INSERT);
+	  slot = event_tab->find_slot (&plugin_event_name[i], INSERT);
 	  gcc_assert (*slot == HTAB_EMPTY_ENTRY);
 	  *slot = &plugin_event_name[i];
 	}
     }
-  slot = htab_find_slot (event_tab, name, insert);
+  slot = event_tab->find_slot (&name, insert);
   if (slot == NULL)
     return -1;
   if (*slot != HTAB_EMPTY_ENTRY)
-    return (const char **) *slot - &plugin_event_name[0];
+    return *slot - &plugin_event_name[0];
 
   if (event_last >= event_horizon)
     {
@@ -369,7 +402,7 @@
 					 plugin_callbacks, event_horizon);
 	}
       /* All the pointers in the hash table will need to be updated.  */
-      htab_delete (event_tab);
+      delete event_tab;
       event_tab = NULL;
     }
   else
@@ -406,10 +439,6 @@
 	gcc_assert (!callback);
         ggc_register_root_tab ((const struct ggc_root_tab*) user_data);
 	break;
-      case PLUGIN_REGISTER_GGC_CACHES:
-	gcc_assert (!callback);
-        ggc_register_cache_tab ((const struct ggc_cache_tab*) user_data);
-	break;
       case PLUGIN_EVENT_FIRST_DYNAMIC:
       default:
 	if (event < PLUGIN_EVENT_FIRST_DYNAMIC || event >= event_last)
@@ -419,7 +448,10 @@
 	    return;
 	  }
       /* Fall through.  */
+      case PLUGIN_START_PARSE_FUNCTION:
+      case PLUGIN_FINISH_PARSE_FUNCTION:
       case PLUGIN_FINISH_TYPE:
+      case PLUGIN_FINISH_DECL:
       case PLUGIN_START_UNIT:
       case PLUGIN_FINISH_UNIT:
       case PLUGIN_PRE_GENERICIZE:
@@ -438,6 +470,7 @@
       case PLUGIN_EARLY_GIMPLE_PASSES_START:
       case PLUGIN_EARLY_GIMPLE_PASSES_END:
       case PLUGIN_NEW_PASS:
+      case PLUGIN_INCLUDE_FILE:
         {
           struct callback_info *new_callback;
           if (!callback)
@@ -495,7 +528,10 @@
 	gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC);
 	gcc_assert (event < event_last);
       /* Fall through.  */
+      case PLUGIN_START_PARSE_FUNCTION:
+      case PLUGIN_FINISH_PARSE_FUNCTION:
       case PLUGIN_FINISH_TYPE:
+      case PLUGIN_FINISH_DECL:
       case PLUGIN_START_UNIT:
       case PLUGIN_FINISH_UNIT:
       case PLUGIN_PRE_GENERICIZE:
@@ -514,6 +550,7 @@
       case PLUGIN_EARLY_GIMPLE_PASSES_START:
       case PLUGIN_EARLY_GIMPLE_PASSES_END:
       case PLUGIN_NEW_PASS:
+      case PLUGIN_INCLUDE_FILE:
         {
           /* Iterate over every callback registered with this event and
              call it.  */
@@ -528,7 +565,6 @@
 
       case PLUGIN_PASS_MANAGER_SETUP:
       case PLUGIN_REGISTER_GGC_ROOTS:
-      case PLUGIN_REGISTER_GGC_CACHES:
         gcc_assert (false);
     }
 
@@ -571,7 +607,8 @@
 
   /* Check the plugin license.  */
   if (dlsym (dl_handle, str_license) == NULL)
-    fatal_error ("plugin %s is not licensed under a GPL-compatible license\n"
+    fatal_error (input_location,
+		 "plugin %s is not licensed under a GPL-compatible license\n"
 		 "%s", plugin->full_name, dlerror ());
 
   PTR_UNION_AS_VOID_PTR (plugin_init_union) =
@@ -580,6 +617,7 @@
 
   if ((err = dlerror ()) != NULL)
     {
+      dlclose(dl_handle);
       error ("cannot find %s in plugin %s\n%s", str_plugin_init_func_name,
              plugin->full_name, err);
       return false;
@@ -588,10 +626,12 @@
   /* Call the plugin-provided initialization routine with the arguments.  */
   if ((*plugin_init) (plugin, &gcc_version))
     {
+      dlclose(dl_handle);
       error ("fail to initialize plugin %s", plugin->full_name);
       return false;
     }
-
+  /* leak dl_handle on purpose to ensure the plugin is loaded for the
+     entire run of the compiler. */
   return true;
 }
 
@@ -611,7 +651,8 @@
   bool ok = try_init_one_plugin (plugin);
   if (!ok)
     {
-      htab_remove_elt (plugin_name_args_tab, plugin->base_name);
+      htab_remove_elt_with_hash (plugin_name_args_tab, plugin->base_name,
+				 htab_hash_string (plugin->base_name));
       XDELETE (plugin);
     }
   return 1;
@@ -788,7 +829,7 @@
 	for (ci = plugin_callbacks[event]; ci; ci = ci->next)
 	  fprintf (file, " %s", ci->plugin_name);
 
-	putc('\n', file);
+	putc ('\n', file);
       }
 }
 
@@ -817,16 +858,6 @@
 
 }
 
-/* Likewise, as a callback from the diagnostics code.  */
-
-void
-plugins_internal_error_function (diagnostic_context *context ATTRIBUTE_UNUSED,
-				 const char *msgid ATTRIBUTE_UNUSED,
-				 va_list *ap ATTRIBUTE_UNUSED)
-{
-  warn_if_plugins ();
-}
-
 /* The default version check. Compares every field in VERSION. */
 
 bool
@@ -863,12 +894,13 @@
 
 
 /* Retrieve the default plugin directory.  The gcc driver should have passed
-   it as -iplugindir <dir> to the cc1 program, and it is queriable thru the
+   it as -iplugindir <dir> to the cc1 program, and it is queriable through the
    -print-file-name=plugin option to gcc.  */
 const char*
 default_plugin_dir_name (void)
 {
   if (!plugindir_string)
-    fatal_error ("-iplugindir <dir> option not passed from the gcc driver");
+    fatal_error (input_location,
+		 "-iplugindir <dir> option not passed from the gcc driver");
   return plugindir_string;
 }