OSDN Git Service

* config/i386/sse.md (copysign<mode>3): Allocate registers only for
[pf3gnuchains/gcc-fork.git] / gcc / plugin.c
index 9362e6a..9060683 100644 (file)
@@ -25,7 +25,7 @@ along with GCC; see the file COPYING3.  If not see
 
 /* If plugin support is not enabled, do not try to execute any code
    that may reference libdl.  The generic code is still compiled in to
-   avoid including to many conditional compilation paths in the rest
+   avoid including too many conditional compilation paths in the rest
    of the compiler.  */
 #ifdef ENABLE_PLUGIN
 #include <dlfcn.h>
@@ -38,6 +38,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 #include "plugin.h"
 #include "timevar.h"
+#include "ggc.h"
+
 #ifdef ENABLE_PLUGIN
 #include "plugin-version.h"
 #endif
@@ -51,22 +53,14 @@ const char *plugin_event_name[] =
   "PLUGIN_CXX_CP_PRE_GENERICIZE",
   "PLUGIN_FINISH",
   "PLUGIN_INFO",
+  "PLUGIN_GGC_START",
+  "PLUGIN_GGC_MARKING",
+  "PLUGIN_GGC_END",
+  "PLUGIN_REGISTER_GGC_ROOTS",
+  "PLUGIN_START_UNIT", 
   "PLUGIN_EVENT_LAST"
 };
 
-/* Object that keeps track of the plugin name and its arguments
-   when parsing the command-line options -fplugin=/path/to/NAME.so and
-   -fplugin-arg-NAME-<key>[=<value>].  */
-struct plugin_name_args
-{
-  char *base_name;
-  const char *full_name;
-  int argc;
-  struct plugin_argument *argv;
-  const char *version;
-  const char *help;
-};
-
 /* Hash table for the plugin_name_args objects created during command-line
    parsing.  */
 static htab_t plugin_name_args_tab = NULL;
@@ -102,6 +96,10 @@ static struct pass_list_node *prev_added_pass_node;
 /* Each plugin should define an initialization function with exactly
    this name.  */
 static const char *str_plugin_init_func_name = "plugin_init";
+
+/* Each plugin should define this symbol to assert that it is
+   distributed under a GPL-compatible license.  */
+static const char *str_license = "plugin_is_GPL_compatible";
 #endif
 
 /* Helper function for the hash table that compares the base_name of the
@@ -343,6 +341,11 @@ position_pass (struct plugin_pass *plugin_pass_info,
               case PASS_POS_INSERT_AFTER:
                 new_pass->next = pass->next;
                 pass->next = new_pass;
+
+               /* Skip newly inserted pass to avoid repeated
+                  insertions in the case where the new pass and the
+                  existing one have the same name.  */
+                pass = new_pass; 
                 break;
               case PASS_POS_INSERT_BEFORE:
                 new_pass->next = pass;
@@ -485,14 +488,24 @@ register_callback (const char *plugin_name,
   switch (event)
     {
       case PLUGIN_PASS_MANAGER_SETUP:
+       gcc_assert (!callback);
         register_pass (plugin_name, (struct plugin_pass *) user_data);
         break;
       case PLUGIN_INFO:
+       gcc_assert (!callback);
        register_plugin_info (plugin_name, (struct plugin_info *) user_data);
        break;
+      case PLUGIN_REGISTER_GGC_ROOTS:
+       gcc_assert (!callback);
+        ggc_register_root_tab ((const struct ggc_root_tab*) user_data);
+       break;
       case PLUGIN_FINISH_TYPE:
+      case PLUGIN_START_UNIT:
       case PLUGIN_FINISH_UNIT:
       case PLUGIN_CXX_CP_PRE_GENERICIZE:
+      case PLUGIN_GGC_START:
+      case PLUGIN_GGC_MARKING:
+      case PLUGIN_GGC_END:
       case PLUGIN_ATTRIBUTES:
       case PLUGIN_FINISH:
         {
@@ -533,10 +546,14 @@ invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
   switch (event)
     {
       case PLUGIN_FINISH_TYPE:
+      case PLUGIN_START_UNIT:
       case PLUGIN_FINISH_UNIT:
       case PLUGIN_CXX_CP_PRE_GENERICIZE:
       case PLUGIN_ATTRIBUTES:
       case PLUGIN_FINISH:
+      case PLUGIN_GGC_START:
+      case PLUGIN_GGC_MARKING:
+      case PLUGIN_GGC_END:
         {
           /* Iterate over every callback registered with this event and
              call it.  */
@@ -548,6 +565,7 @@ invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
 
       case PLUGIN_PASS_MANAGER_SETUP:
       case PLUGIN_EVENT_LAST:
+      case PLUGIN_REGISTER_GGC_ROOTS:
       default:
         gcc_assert (false);
     }
@@ -574,7 +592,11 @@ try_init_one_plugin (struct plugin_name_args *plugin)
   char *err;
   PTR_UNION_TYPE (plugin_init_func) plugin_init_union;
 
-  dl_handle = dlopen (plugin->full_name, RTLD_NOW);
+  /* We use RTLD_NOW to accelerate binding and detect any mismatch
+     between the API expected by the plugin and the GCC API; we use
+     RTLD_GLOBAL which is useful to plugins which themselves call
+     dlopen.  */
+  dl_handle = dlopen (plugin->full_name, RTLD_NOW | RTLD_GLOBAL);
   if (!dl_handle)
     {
       error ("Cannot load plugin %s\n%s", plugin->full_name, dlerror ());
@@ -584,6 +606,11 @@ try_init_one_plugin (struct plugin_name_args *plugin)
   /* Clear any existing error.  */
   dlerror ();
 
+  /* Check the plugin license.  */
+  if (dlsym (dl_handle, str_license) == NULL)
+    fatal_error ("plugin %s is not licensed under a GPL-compatible license\n"
+                "%s", plugin->full_name, dlerror ());
+
   PTR_UNION_AS_VOID_PTR (plugin_init_union) =
       dlsym (dl_handle, str_plugin_init_func_name);
   plugin_init = PTR_UNION_AS_CAST_PTR (plugin_init_union);
@@ -596,8 +623,7 @@ try_init_one_plugin (struct plugin_name_args *plugin)
     }
 
   /* Call the plugin-provided initialization routine with the arguments.  */
-  if ((*plugin_init) (plugin->base_name, &gcc_version, plugin->argc,
-                     plugin->argv))
+  if ((*plugin_init) (plugin, &gcc_version))
     {
       error ("Fail to initialize plugin %s", plugin->full_name);
       return false;