2015-08-01  Nathan Sidwell  <nathan@codesourcery.com>

	include/
	* gomp-constants.h (GOMP_VERSION_INTEL_MIC): New.

	libgomp/
	* plugin/plugin-nvptx.c (GOMP_OFFLOAD_load_image_ver): Rename to ...
	(GOMP_OFFLOAD_load_image): ... here.  Swap version and ord args.
	Adjust version check and mesage.
	(GOMP_OFFLOAD_unload_image_ver): Rename to ...
	(GOMP_OFFLOAD_unload_image): ... here.  Swap version and ord args.
	* oacc-host.c: Include gomp-constants.h.
	(host_version): New.
	(host_load_image, host_unload_image): Add version arg.
	(host_dispatch): Adjust.
	* target.c (gomp_load_image_to_device): Swap version and devicep
	args. Adjust plugin load calling.  Adjust all callers.
	* target.c (gomp_unload_image_from_device): Swap version and devicep
	args. Adjust plugin unload calling. Adjust all callers.
	(load_plugin_for_device): Always look for version function and
	check it.  Adjust load and unload call lookup.
	* libgomp.h: Adjustt load and unload plugin fields.

	liboffloadmic/
	* plugin/libgomp-plugin-intelmic.cpp (GOMP_OFFLOAD_version): New.
	(GOMP_OFFLOAD_load_image): Add version arg and check it.
	(GOMP_OFFLOAD_unload_image): Likewise.

Index: libgomp/plugin/plugin-nvptx.c
===================================================================
--- libgomp/plugin/plugin-nvptx.c	(revision 226462)
+++ libgomp/plugin/plugin-nvptx.c	(working copy)
@@ -1650,9 +1650,9 @@ GOMP_OFFLOAD_version (void)
    number ORD.  Allocate and return TARGET_TABLE.  */
 
 int
-GOMP_OFFLOAD_load_image_ver (unsigned version, int ord,
-			     const void *target_data,
-			     struct addr_pair **target_table)
+GOMP_OFFLOAD_load_image (int ord, unsigned version,
+			 const void *target_data,
+			 struct addr_pair **target_table)
 {
   CUmodule module;
   const char *const *var_names;
@@ -1665,9 +1665,9 @@ GOMP_OFFLOAD_load_image_ver (unsigned ve
   struct ptx_image_data *new_image;
   struct ptx_device *dev;
 
-  if (GOMP_VERSION_DEV (version) != GOMP_VERSION_NVIDIA_PTX)
+  if (GOMP_VERSION_DEV (version) > GOMP_VERSION_NVIDIA_PTX)
     GOMP_PLUGIN_fatal ("Offload data incompatible with PTX plugin"
-		       " (version %u ! %u)",
+		       " (expected %u, received %u)",
 		       GOMP_VERSION_NVIDIA_PTX, GOMP_VERSION_DEV (version));
   
   GOMP_OFFLOAD_init_device (ord);
@@ -1739,13 +1739,12 @@ GOMP_OFFLOAD_load_image_ver (unsigned ve
    function descriptors allocated by G_O_load_image.  */
 
 void
-GOMP_OFFLOAD_unload_image_ver (unsigned version, int ord,
-			       const void *target_data)
+GOMP_OFFLOAD_unload_image (int ord, unsigned version, const void *target_data)
 {
   struct ptx_image_data *image, **prev_p;
   struct ptx_device *dev = ptx_devices[ord];
 
-  if (GOMP_VERSION_DEV (version) != GOMP_VERSION_NVIDIA_PTX)
+  if (GOMP_VERSION_DEV (version) > GOMP_VERSION_NVIDIA_PTX)
     return;
   
   pthread_mutex_lock (&dev->image_lock);
Index: libgomp/oacc-host.c
===================================================================
--- libgomp/oacc-host.c	(revision 226462)
+++ libgomp/oacc-host.c	(working copy)
@@ -28,6 +28,7 @@
 
 #include "libgomp.h"
 #include "oacc-int.h"
+#include "gomp-constants.h"
 
 #include <stdbool.h>
 #include <stddef.h>
@@ -69,8 +70,15 @@ host_fini_device (int n __attribute__ ((
 {
 }
 
+static unsigned
+host_version (void)
+{
+  return GOMP_VERSION;
+}
+
 static int
 host_load_image (int n __attribute__ ((unused)),
+		 unsigned v __attribute__ ((unused)),
 		 const void *t __attribute__ ((unused)),
 		 struct addr_pair **r __attribute__ ((unused)))
 {
@@ -79,6 +87,7 @@ host_load_image (int n __attribute__ ((u
 
 static void
 host_unload_image (int n __attribute__ ((unused)),
+		   unsigned v __attribute__ ((unused)),
 		   const void *t __attribute__ ((unused)))
 {
 }
@@ -203,9 +212,9 @@ static struct gomp_device_descr host_dis
     .get_num_devices_func = host_get_num_devices,
     .init_device_func = host_init_device,
     .fini_device_func = host_fini_device,
-    .version_func = NULL,
-    .load_image = {.unver_func = host_load_image},
-    .unload_image = {.unver_func = host_unload_image},
+    .version_func = host_version,
+    .load_image_func = host_load_image,
+    .unload_image_func = host_unload_image,
     .alloc_func = host_alloc,
     .free_func = host_free,
     .dev2host_func = host_dev2host,
Index: libgomp/target.c
===================================================================
--- libgomp/target.c	(revision 226462)
+++ libgomp/target.c	(working copy)
@@ -652,8 +652,7 @@ gomp_update (struct gomp_device_descr *d
    emitting variable and functions in the same order.  */
 
 static void
-gomp_load_image_to_device (unsigned version,
-			   struct gomp_device_descr *devicep,
+gomp_load_image_to_device (struct gomp_device_descr *devicep, unsigned version,
 			   const void *host_table, const void *target_data,
 			   bool is_register_lock)
 {
@@ -671,17 +670,9 @@ gomp_load_image_to_device (unsigned vers
   struct addr_pair *target_table = NULL;
   int i, num_target_entries;
 
-  if (devicep->version_func)
-    num_target_entries
-      = devicep->load_image.ver_func (version, devicep->target_id,
-					target_data, &target_table);
-  else if (GOMP_VERSION_DEV (version))
-    gomp_fatal ("Plugin too old for offload data (0 < %u)",
-		GOMP_VERSION_DEV (version));
-  else
-    num_target_entries
-      = devicep->load_image.unver_func (devicep->target_id,
-					target_data, &target_table);
+  num_target_entries
+    = devicep->load_image_func (devicep->target_id, version,
+				target_data, &target_table);
 
   if (num_target_entries != num_funcs + num_vars)
     {
@@ -763,8 +754,8 @@ gomp_load_image_to_device (unsigned vers
    The device must be locked.   */
 
 static void
-gomp_unload_image_from_device (unsigned version,
-			       struct gomp_device_descr *devicep,
+gomp_unload_image_from_device (struct gomp_device_descr *devicep,
+			       unsigned version,
 			       const void *host_table, const void *target_data)
 {
   void **host_func_table = ((void ***) host_table)[0];
@@ -790,11 +781,7 @@ gomp_unload_image_from_device (unsigned
       node = splay_tree_lookup (&devicep->mem_map, &k);
     }
 
-  if (devicep->version_func)
-    devicep->unload_image.ver_func (version,
-				    devicep->target_id, target_data);
-  else
-    devicep->unload_image.unver_func (devicep->target_id, target_data);
+  devicep->unload_image_func (devicep->target_id, version, target_data);
 
   /* Remove mappings from splay tree.  */
   for (j = 0; j < num_funcs; j++)
@@ -840,7 +827,7 @@ GOMP_offload_register_ver (unsigned vers
       struct gomp_device_descr *devicep = &devices[i];
       gomp_mutex_lock (&devicep->lock);
       if (devicep->type == target_type && devicep->is_initialized)
-	gomp_load_image_to_device (version, devicep,
+	gomp_load_image_to_device (devicep, version,
 				   host_table, target_data, true);
       gomp_mutex_unlock (&devicep->lock);
     }
@@ -884,7 +871,7 @@ GOMP_offload_unregister_ver (unsigned ve
       struct gomp_device_descr *devicep = &devices[i];
       gomp_mutex_lock (&devicep->lock);
       if (devicep->type == target_type && devicep->is_initialized)
-	gomp_unload_image_from_device (version, devicep,
+	gomp_unload_image_from_device (devicep, version,
 				       host_table, target_data);
       gomp_mutex_unlock (&devicep->lock);
     }
@@ -921,7 +908,7 @@ gomp_init_device (struct gomp_device_des
     {
       struct offload_image_descr *image = &offload_images[i];
       if (image->type == devicep->type)
-	gomp_load_image_to_device (image->version, devicep,
+	gomp_load_image_to_device (devicep, image->version,
 				   image->host_table, image->target_data,
 				   false);
     }
@@ -941,7 +928,7 @@ gomp_unload_device (struct gomp_device_d
 	{
 	  struct offload_image_descr *image = &offload_images[i];
 	  if (image->type == devicep->type)
-	    gomp_unload_image_from_device (image->version, devicep,
+	    gomp_unload_image_from_device (devicep, image->version,
 					   image->host_table,
 					   image->target_data);
 	}
@@ -1147,23 +1134,11 @@ gomp_load_plugin_for_device (struct gomp
   ((device->f##_func = dlsym (plugin_handle, "GOMP_OFFLOAD_" #n))	\
    || (last_missing = #n, 0))
 
-  if (DLSYM_OPT (version, version))
-    {
-      unsigned v = device->version_func ();
-      if (v != GOMP_VERSION)
-	{
-	  err = "plugin version mismatch";
-	  goto fail;
-	}
-      if (!DLSYM_OPT (load_image.ver, load_image_ver)
-	  || !DLSYM_OPT (unload_image.ver, unload_image_ver))
-	goto  dl_fail;
-    }
-  else
+  DLSYM (version);
+  if (device->version_func () != GOMP_VERSION)
     {
-      if (!DLSYM_OPT (load_image.unver, load_image)
-	  || !DLSYM_OPT (unload_image.unver, unload_image))
-	goto dl_fail;
+      err = "plugin version mismatch";
+      goto fail;
     }
 
   DLSYM (get_name);
@@ -1172,6 +1147,8 @@ gomp_load_plugin_for_device (struct gomp
   DLSYM (get_num_devices);
   DLSYM (init_device);
   DLSYM (fini_device);
+  DLSYM (load_image);
+  DLSYM (unload_image);
   DLSYM (alloc);
   DLSYM (free);
   DLSYM (dev2host);
Index: libgomp/libgomp.h
===================================================================
--- libgomp/libgomp.h	(revision 226462)
+++ libgomp/libgomp.h	(working copy)
@@ -750,22 +750,9 @@ struct gomp_device_descr
   int (*get_num_devices_func) (void);
   void (*init_device_func) (int);
   void (*fini_device_func) (int);
-
   unsigned (*version_func) (void);
-  
-  /* When all plugins updated, we can remove these unions and just
-     have the versioned entry points.  */
-  union 
-  {
-    int (*unver_func) (int, const void *, struct addr_pair **);
-    int (*ver_func) (unsigned, int, const void *, struct addr_pair **);
-  } load_image;
-  union
-  {
-    void (*unver_func) (int, const void *);
-    void (*ver_func) (unsigned, int, const void *);
-  } unload_image;
-  
+  int (*load_image_func) (int, unsigned, const void *, struct addr_pair **);
+  void (*unload_image_func) (int, unsigned, const void *);
   void *(*alloc_func) (int, size_t);
   void (*free_func) (int, void *);
   void *(*dev2host_func) (int, void *, const void *, size_t);
Index: liboffloadmic/plugin/libgomp-plugin-intelmic.cpp
===================================================================
--- liboffloadmic/plugin/libgomp-plugin-intelmic.cpp	(revision 226462)
+++ liboffloadmic/plugin/libgomp-plugin-intelmic.cpp	(working copy)
@@ -327,12 +327,26 @@ offload_image (const void *target_image)
   free (image);
 }
 
+/* Return the libgomp version number we're compatible with.  There is
+   no requirement for cross-version compatibility.  */
+
+extern "C" unsigned
+GOMP_OFFLOAD_version (void)
+{
+  return GOMP_VERSION;
+}
+
 extern "C" int
-GOMP_OFFLOAD_load_image (int device, const void *target_image,
-			 addr_pair **result)
+GOMP_OFFLOAD_load_image (int device, const unsigned version,
+			 void *target_image, addr_pair **result)
 {
   TRACE ("(device = %d, target_image = %p)", device, target_image);
 
+  if (GOMP_VERSION_DEV (version) > GOMP_VERSION_INTEL_MIC)
+    GOMP_PLUGIN_fatal ("Offload data incompatible with intelmic plugin"
+		       " (expected %u, received %u)",
+		       GOMP_VERSION_INTEL_MIC, GOMP_VERSION_DEV (version));
+
   /* If target_image is already present in address_table, then there is no need
      to offload it.  */
   if (address_table->count (target_image) == 0)
@@ -353,8 +367,12 @@ GOMP_OFFLOAD_load_image (int device, con
 }
 
 extern "C" void
-GOMP_OFFLOAD_unload_image (int device, const void *target_image)
+GOMP_OFFLOAD_unload_image (int device, unsigned version,
+			   const void *target_image)
 {
+  if (GOMP_VERSION_DEV (version) > GOMP_VERSION_INTEL_MIC)
+    return;
+
   TRACE ("(device = %d, target_image = %p)", device, target_image);
 
   /* TODO: Currently liboffloadmic doesn't support __offload_unregister_image
