[named-addr-spaces-branch][Patch,committed] Work in progress improve named address space pointer incompatibility tests

Michael Meissner meissner@linux.vnet.ibm.com
Fri Dec 5 00:09:00 GMT 2008


I haven't run a full set of valadation tests with these patches, but it is work
in progress to get the compiler to know about named address space pointers that
are subsets of each other, or incompatible.

[gcc]
2008-12-04  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* doc/tm.texi (TARGET_ADDR_SPACE_SUBSET_P): Document new hook to
	determine if one named address is a subset of another.

	* doc/invoke.texi (-mno-ea-to-generic-conversion): Rename from
	-mno-local-ea-conversion.
	(-mea-to-generic-conversion): Rename from
	-mealocal-ea-conversion.
	(-mno-address-space-conversion): New switch to
	prevent automatic conversions of pointers to different named
	addresses from happening automatically.
	(-maddress-space-conversion): New default switch.

	* targhooks.c (default_addr_space_common_pointer): Delete target
	hook, no longer used.
	(default_addr_space_subset_p): New default target hook to
	determine if one named address is a subset of another.

	* targhooks.h (default_addr_space_common_pointer): Delete.
	(default_addr_space_subset_p): New declaration.

	* target.h (struct addr_space): Add subset_p target hook, drop
	common_pointer target hook.

	* c-objc-common (c_types_compatible_p): Drop named address support
	that is no longer needed.

	* c-decl.c (diagnose_mismatched_decls): Add error for mismatched
	named address spaces.
	(start_decl): Don't give an error if the target doesn't have named
	addresses, just don't set the section name.
	(grokdeclarator): Improve named address space mismatch error
	message.
	(declspecs_add_addrspace): Cache address space, rather than call
	target hook twice.

	* c-typechk.c (qualify_type): Check for named addresses.
	(common_pointer_type): Use subset_p target hook instead of the old
	common_pointer hook.
	(c_common_type): Go back to using TYPE_QUALS instead of
	TYPE_QUALS_NO_ADDR_SPACE to get main type.
	(comp_target_types): Add support for checking whether two pointer
	types point to compatible address spaces.
	(build_conditional_expr): Ditto.
	(build_c_cast): Improve named address space type mismatch error.
	(convert_for_assignment): Add support for checking whether
	pointers are to compatible named addresses.

	* target-def.h (TARGET_ADDR_SPACE_COMMON_POINTER): Delete.
	(TARGET_ADDR_SPACE_SUBSET_P): New target hook.
	(TARGET_ADDR_SPACE_HOOKS): Update target hooks.

	* config/spu/spu.opt (-mno-ea-to-generic-conversion): Rename from
	-mno-local-ea-conversion.
	(-mea-to-generic-conversion): Rename from
	-mealocal-ea-conversion.
	(-mno-address-space-conversion): New switch to
	prevent automatic conversions of pointers to different named
	addresses from happening automatically.
	(-maddress-space-conversion): New default switch.

	* config/spu/spu.c (ADDR_SPACE_BAD): New address space to return
	in error conditions.
	(TARGET_ADDR_SPACE_COMMON_POINTER): Delete.
	(spu_addr_space_common_pointer): Ditto.
	(TARGET_ADDR_SPACE_SUBSET_P): New target hook.
	(spu_addr_space_subset_p): New function to determine if one named
	address is a subset of another.
	(spu_addr_space_can_convert_p): Change -mno-local-ea-conversion to
	-mno-ea-to-generic-conversion.
	(spu_addr_space_nop_convert_p): Whitespace changes.

	* convert.c (convert_to_pointer): Improve the named address space
	mismatch error message.

[gcc/testsuite]
2008-12-04  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/spu/ea/errors2.c: Add comment saying this is the same
	as compile2.c without the switch to induce errors.  Change the
	switch to induce the errors to -mno-ea-to-generic-conversion.

	* gcc.target/spu/ea/compile2.c: New file to make sure the tests in
	error2.c compile cleanly with -mea-to-generic-conversion.

	* gcc.target/spu/ea/errors3.c: New file to test the subset hooks
	by making the compiler not convert pointers in different named
	address spaces automatically.

	* gcc.target/spu/ea/compile3.c: New file to test that the code in
	errors3.c compiles cleanly without the switch.

	* gcc.target/spu/ea/compile.c: Compile with optimization.

Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 142412)
+++ gcc/doc/tm.texi	(working copy)
@@ -9665,6 +9665,11 @@ Define this to return whether converting
 conversion needs to be done.
 @end deftypefn
 
+@deftypefn {Target Hook} {bool} TARGET_ADDR_SPACE_SUBSET_P (addr_space_t @var{superset}, addr_space_t @var{subset})
+Define this to return the @var{subset} named address space is
+contained within the @var{superset} named address space.
+@end deftypefn
+
 @deftypefn {Target Hook} {rtx} TARGET_ADDR_SPACE_CONVERT (rtx @var{op}, enum machine_mode @var{mode}, addr_space_t @var{from}, addr_space_t @var{to})
 Define this to convert the pointer expression represented by the RTL
 @var{op} that points to the named address space @var{from} to a new
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 142412)
+++ gcc/doc/invoke.texi	(working copy)
@@ -800,7 +800,8 @@ See RS/6000 and PowerPC Options.
 -mfixed-range=@var{register-range} @gol
 -mea32 -mea64 @gol
 -mcache-size=@var{cache-size} @gol
--mlocal-ea-conversion -mno-local-ea-conversion @gol
+-mea-to-generic-conversion -mno-ea-to-generic-conversion @gol
+-maddress-space-conversion -maddress-space-conversion @gol
 -matomic-updates -mno-atomic-updates}
 
 @emph{System V Options}
@@ -15010,14 +15011,22 @@ address space qualifier specifies that v
 address space.  As this is an ABI changing option, all object code in an
 executable must be compiled with the same option.
 
-@item -mlocal-ea-conversion
-@itemx -mno-local-ea-conversion
-@opindex mlocal-ea-conversion
-@opindex mno-local-ea-conversion
+@item -mea-to-generic-conversion
+@itemx -mno-ea-to-generic-conversion
+@opindex mea-to-generic-conversion
+@opindex mno-ea-to-generic-conversion
 
 Allow/disallow pointers to the @code{__ea} address space to be
 converted local pointers.
 
+@item -maddress-space-conversion
+@itemx -mno-address-space-conversion
+@opindex maddress-space-conversion
+@opindex mno-address-space-conversion
+
+Allow/disallow automatically converting pointers to different named
+address spaces (@code{__ea} and generic) to the other address space.
+
 @item -mcache-size=@var{cache-size}
 @opindex mcache-size
 
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	(revision 142412)
+++ gcc/targhooks.c	(working copy)
@@ -739,16 +739,25 @@ default_addr_space_nop_convert_p (addr_s
   return to_addr == from_addr;
 }
 
-/* The default hook for determining whether there is a common pointer format to
-   use when two pointers are used together.  */
+/* The default hook for determining if one named address space is a subset of
+   another and to return which address space to use as the common address
+   space.  */
 
-addr_space_t
-default_addr_space_common_pointer (addr_space_t addr1, addr_space_t addr2)
-{
-  if (addr1 == addr2)
-    return addr1;
-
-  gcc_unreachable ();
+bool
+default_addr_space_subset_p (addr_space_t as1,
+			     addr_space_t as2,
+			     addr_space_t *common_as)
+{
+  if (as1 == as2)
+    {
+      *common_as = as1;
+      return true;
+    }
+  else
+    {
+      *common_as = 0;
+      return false;
+    }
 }
 
 /* The default hook for TARGET_ADDR_SPACE_CONVERT. This hook should never be
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	(revision 142412)
+++ gcc/targhooks.h	(working copy)
@@ -110,6 +110,6 @@ extern rtx default_addr_space_convert (r
 				       addr_space_t);
 extern bool default_addr_space_can_convert_p (addr_space_t, addr_space_t);
 extern bool default_addr_space_nop_convert_p (addr_space_t, addr_space_t);
-extern addr_space_t default_addr_space_common_pointer (addr_space_t,
-						       addr_space_t);
+extern bool default_addr_space_subset_p (addr_space_t, addr_space_t,
+					 addr_space_t *);
 extern tree default_addr_space_section_name (addr_space_t);
Index: gcc/target.h
===================================================================
--- gcc/target.h	(revision 142412)
+++ gcc/target.h	(working copy)
@@ -681,9 +681,9 @@ struct gcc_target
        NOP.  */
     bool (* nop_convert_p) (addr_space_t, addr_space_t);
 
-    /* Return the named address space to use between pointers to different
-       named address spaces.  */
-    addr_space_t (* common_pointer) (addr_space_t, addr_space_t);
+    /* True if one named address space is a subset of another and if so, which
+       address space is the superset.  */
+    bool (* subset_p) (addr_space_t, addr_space_t, addr_space_t *);
 
     /* Function to convert an rtl expression from one address space to
        another.  */
Index: gcc/testsuite/gcc.target/spu/ea/errors2.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/errors2.c	(revision 142412)
+++ gcc/testsuite/gcc.target/spu/ea/errors2.c	(working copy)
@@ -1,7 +1,9 @@
 /* Invalid conversions of __ea pointers to local pointers.  */
 /* { dg-do compile } */
-/* { dg-options "-std=gnu99 -pedantic-errors -mno-local-ea-conversion" } */
+/* { dg-options "-O2 -std=gnu99 -pedantic-errors -mno-ea-to-generic-conversion" } */
 
+/* This is the same code as compile2.c but it should generate errors.  If you
+   modify this file, you should modify errors2.c as well.  */
 #ifndef TYPE
 #define TYPE void
 #endif
@@ -31,7 +33,7 @@ void ea_to_ea_arg (void)
 
 void ea_to_lm_arg (void)
 {
-  arg_lm (LM_CAST (ea_ptr));	/* { dg-error "cast to pointer to address space generic from pointer to address space __ea" } */
+  arg_lm (LM_CAST (ea_ptr));	/* { dg-error "cast to generic address space pointer from __ea address space pointer" } */
 }
 
 void lm_to_ea_arg (void)
@@ -51,7 +53,7 @@ ea_ptr_t ea_to_ea_ret (void)
 
 lm_ptr_t ea_to_lm_ret (void)
 {
-  return LM_CAST (ea_ptr);	/* { dg-error "cast to pointer to address space generic from pointer to address space __ea" } */
+  return LM_CAST (ea_ptr);	/* { dg-error "cast to generic address space pointer from __ea address space pointer" } */
 }
 
 ea_ptr_t lm_to_ea_ret (void)
@@ -71,7 +73,7 @@ void ea_to_ea_store (ea_ptr_t ptr)
 
 void ea_to_lm_store (ea_ptr_t ptr)
 {
-  lm_ptr = LM_CAST (ptr);	/* { dg-error "cast to pointer to address space generic from pointer to address space __ea" } */
+  lm_ptr = LM_CAST (ptr);	/* { dg-error "cast to generic address space pointer from __ea address space pointer" } */
 }
 
 void lm_to_ea_store (lm_ptr_t ptr)
Index: gcc/testsuite/gcc.target/spu/ea/errors3.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/errors3.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/errors3.c	(revision 0)
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=gnu99 -pedantic-errors -mno-address-space-conversion" } */
+
+/* This is the same as compile3.c except it should generate errors where
+   pointers are mixed.  If you modify this code, please modify compile3.c as
+   well.  */
+typedef __ea int *ea_ptr_t;
+typedef      int *lm_ptr_t;
+
+ea_ptr_t ea, ea2;
+lm_ptr_t lm, lm2;
+
+extern void call_ea (ea_ptr_t);
+extern void call_lm (lm_ptr_t);
+
+/* Errors should be generated here.  */
+void to_ea (void) { ea = lm; }				/* { dg-error "assignment to a pointer to an incompatible address space" } */
+void to_lm (void) { lm = ea; }				/* { dg-error "assignment to a pointer to an incompatible address space" } */
+ea_ptr_t ret_ea (void) { return lm; }			/* { dg-error "return of a pointer to an incompatible address space" } */
+lm_ptr_t ret_lm (void) { return ea; }			/* { dg-error "return of a pointer to an incompatible address space" } */
+void call_ea2 (void) { call_ea (lm); }			/* { dg-error "passing argument 1 of 'call_ea' is a pointer to an incompatible address space" } */
+void call_lm2 (void) { call_lm (ea); }			/* { dg-error "passing argument 1 of 'call_lm' is a pointer to an incompatible address space" } */
+int sub_ea (void) { return ea - lm; }			/* { dg-error "invalid operands to binary -" } */
+int sub_lm (void) { return lm - ea; }			/* { dg-error "invalid operands to binary -" } */
+int if_ea (int test) { return *((test) ? ea : lm); }	/* { dg-error "pointers to incompatible address spaces used in conditional expression" } */
+int if_lm (int test) { return *((test) ? lm : ea); }	/* { dg-error "pointers to incompatible address spaces used in conditional expression" } */
+
+/* No errors here.  */
+void to_ea2 (void) { ea = ea2; }
+void to_lm2 (void) { lm = lm2; }
+
+void to_ea_with_cast (void) { ea = (ea_ptr_t)lm; }
+void to_lm_with_cast (void) { lm = (lm_ptr_t)ea; }
+ea_ptr_t ret_ea_with_cast (void) { return (ea_ptr_t)lm; }
+lm_ptr_t ret_lm_with_cast (void) { return (lm_ptr_t)ea; }
+void call_ea2_with_cast (void) { call_ea ((ea_ptr_t)lm); }
+void call_lm2_with_cast (void) { call_lm ((lm_ptr_t)ea); }
+int sub_ea_with_cast (void) { return ea - (ea_ptr_t)lm; }
+int sub_lm_with_cast (void) { return lm - (lm_ptr_t)ea; }
+int if_ea_with_cast (int test) { return *((test) ? ea : (ea_ptr_t)lm); }
+int if_lm_with_cast (int test) { return *((test) ? lm : (lm_ptr_t)ea); }
+
+void void_ea (void) { ea = (void *)0; }
+void void_lm (void) { lm = (__ea void *)0; }
Index: gcc/testsuite/gcc.target/spu/ea/compile2.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/compile2.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/compile2.c	(revision 0)
@@ -0,0 +1,86 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=gnu99 -pedantic-errors -mea-to-generic-conversion" } */
+
+/* This is the same code as errors2.c but it should compile cleanly.  If you
+   modify this file, you should modify errors2.c as well.  */
+#ifndef TYPE
+#define TYPE void
+#endif
+
+typedef __ea TYPE *ea_ptr_t;
+typedef      TYPE *lm_ptr_t;
+
+extern ea_ptr_t ea_ptr;
+extern lm_ptr_t lm_ptr;
+
+extern void arg_ea (ea_ptr_t);
+extern void arg_lm (lm_ptr_t);
+
+#ifdef NO_CAST
+#define EA_CAST(ARG) (ARG)
+#define LM_CAST(ARG) (ARG)
+
+#else
+#define EA_CAST(ARG) ((ea_ptr_t)(ARG))
+#define LM_CAST(ARG) ((lm_ptr_t)(ARG))
+#endif
+
+void ea_to_ea_arg (void)
+{
+  arg_ea (ea_ptr);
+}
+
+void ea_to_lm_arg (void)
+{
+  arg_lm (LM_CAST (ea_ptr));
+}
+
+void lm_to_ea_arg (void)
+{
+  arg_ea (EA_CAST (lm_ptr));
+}
+
+void lm_to_lm_arg (void)
+{
+  arg_lm (lm_ptr);
+}
+
+ea_ptr_t ea_to_ea_ret (void)
+{
+  return ea_ptr;
+}
+
+lm_ptr_t ea_to_lm_ret (void)
+{
+  return LM_CAST (ea_ptr);
+}
+
+ea_ptr_t lm_to_ea_ret (void)
+{
+  return EA_CAST (lm_ptr);
+}
+
+lm_ptr_t lm_to_lm_ret (void)
+{
+  return lm_ptr;
+}
+
+void ea_to_ea_store (ea_ptr_t ptr)
+{
+  ea_ptr = ptr;
+}
+
+void ea_to_lm_store (ea_ptr_t ptr)
+{
+  lm_ptr = LM_CAST (ptr);
+}
+
+void lm_to_ea_store (lm_ptr_t ptr)
+{
+  ea_ptr = EA_CAST (ptr);
+}
+
+void lm_to_lm_store (lm_ptr_t ptr)
+{
+  lm_ptr = ptr;
+}
Index: gcc/testsuite/gcc.target/spu/ea/compile3.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/compile3.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/compile3.c	(revision 0)
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=gnu99 -pedantic-errors -maddress-space-conversion" } */
+
+/* This is the same as errors3.c except it should not generate any errors.
+   If you modify this code, please modify errors3.c as well.  */
+typedef __ea int *ea_ptr_t;
+typedef      int *lm_ptr_t;
+
+ea_ptr_t ea, ea2;
+lm_ptr_t lm, lm2;
+
+extern void call_ea (ea_ptr_t);
+extern void call_lm (lm_ptr_t);
+
+/* No errors here.  */
+void to_ea (void) { ea = lm; }
+void to_lm (void) { lm = ea; }
+ea_ptr_t ret_ea (void) { return lm; }
+lm_ptr_t ret_lm (void) { return ea; }
+void call_ea2 (void) { call_ea (lm); }
+void call_lm2 (void) { call_lm (ea); }
+int sub_ea (void) { return ea - lm; }
+int sub_lm (void) { return lm - ea; }
+int if_ea (int test) { return *((test) ? ea : lm); }
+int if_lm (int test) { return *((test) ? lm : ea); }
+
+void to_ea2 (void) { ea = ea2; }
+void to_lm2 (void) { lm = lm2; }
+
+void to_ea_with_cast (void) { ea = (ea_ptr_t)lm; }
+void to_lm_with_cast (void) { lm = (lm_ptr_t)ea; }
+ea_ptr_t ret_ea_with_cast (void) { return (ea_ptr_t)lm; }
+lm_ptr_t ret_lm_with_cast (void) { return (lm_ptr_t)ea; }
+void call_ea2_with_cast (void) { call_ea ((ea_ptr_t)lm); }
+void call_lm2_with_cast (void) { call_lm ((lm_ptr_t)ea); }
+int sub_ea_with_cast (void) { return ea - (ea_ptr_t)lm; }
+int sub_lm_with_cast (void) { return lm - (lm_ptr_t)ea; }
+int if_ea_with_cast (int test) { return *((test) ? ea : (ea_ptr_t)lm); }
+int if_lm_with_cast (int test) { return *((test) ? lm : (lm_ptr_t)ea); }
+
+void void_ea (void) { ea = (void *)0; }
+void void_lm (void) { lm = (__ea void *)0; }
Index: gcc/testsuite/gcc.target/spu/ea/compile.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/compile.c	(revision 142412)
+++ gcc/testsuite/gcc.target/spu/ea/compile.c	(working copy)
@@ -1,6 +1,6 @@
 /* Valid __ea declarations.  */
 /* { dg-do compile } */
-/* { dg-options "-std=gnu99 -pedantic-errors" } */
+/* { dg-options "-O2 -std=gnu99 -pedantic-errors" } */
 
 /* Typedefs.  */
 typedef __ea int ea_int_t;
Index: gcc/testsuite/ChangeLog.named
===================================================================
--- gcc/testsuite/ChangeLog.named	(revision 142412)
+++ gcc/testsuite/ChangeLog.named	(working copy)
@@ -1,3 +1,21 @@
+2008-12-04  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+	* gcc.target/spu/ea/errors2.c: Add comment saying this is the same
+	as compile2.c without the switch to induce errors.  Change the
+	switch to induce the errors to -mno-ea-to-generic-conversion.
+
+	* gcc.target/spu/ea/compile2.c: New file to make sure the tests in
+	error2.c compile cleanly with -mea-to-generic-conversion.
+
+	* gcc.target/spu/ea/errors3.c: New file to test the subset hooks
+	by making the compiler not convert pointers in different named
+	address spaces automatically.
+
+	* gcc.target/spu/ea/compile3.c: New file to test that the code in
+	errors3.c compiles cleanly without the switch.
+
+	* gcc.target/spu/ea/compile.c: Compile with optimization.
+
 2008-11-29  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
 	* gcc.target/spu/ea/errors2.c: New test to test
Index: gcc/c-objc-common.c
===================================================================
--- gcc/c-objc-common.c	(revision 142412)
+++ gcc/c-objc-common.c	(working copy)
@@ -187,9 +187,6 @@ c_initialize_diagnostics (diagnostic_con
 int
 c_types_compatible_p (tree x, tree y)
 {
-  if (TYPE_ADDR_SPACE (x) != TYPE_ADDR_SPACE (y))
-    return false;
-
   return comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (y));
 }
 
Index: gcc/ChangeLog.named
===================================================================
--- gcc/ChangeLog.named	(revision 142424)
+++ gcc/ChangeLog.named	(working copy)
@@ -1,3 +1,79 @@
+2008-12-04  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+	* doc/tm.texi (TARGET_ADDR_SPACE_SUBSET_P): Document new hook to
+	determine if one named address is a subset of another.
+
+	* doc/invoke.texi (-mno-ea-to-generic-conversion): Rename from
+	-mno-local-ea-conversion.
+	(-mea-to-generic-conversion): Rename from
+	-mealocal-ea-conversion.
+	(-mno-address-space-conversion): New switch to
+	prevent automatic conversions of pointers to different named
+	addresses from happening automatically.
+	(-maddress-space-conversion): New default switch.
+
+	* targhooks.c (default_addr_space_common_pointer): Delete target
+	hook, no longer used.
+	(default_addr_space_subset_p): New default target hook to
+	determine if one named address is a subset of another.
+
+	* targhooks.h (default_addr_space_common_pointer): Delete.
+	(default_addr_space_subset_p): New declaration.
+
+	* target.h (struct addr_space): Add subset_p target hook, drop
+	common_pointer target hook.
+
+	* c-objc-common (c_types_compatible_p): Drop named address support
+	that is no longer needed.
+
+	* c-decl.c (diagnose_mismatched_decls): Add error for mismatched
+	named address spaces.
+	(start_decl): Don't give an error if the target doesn't have named
+	addresses, just don't set the section name.
+	(grokdeclarator): Improve named address space mismatch error
+	message.
+	(declspecs_add_addrspace): Cache address space, rather than call
+	target hook twice.
+
+	* c-typechk.c (qualify_type): Check for named addresses.
+	(common_pointer_type): Use subset_p target hook instead of the old
+	common_pointer hook.
+	(c_common_type): Go back to using TYPE_QUALS instead of
+	TYPE_QUALS_NO_ADDR_SPACE to get main type.
+	(comp_target_types): Add support for checking whether two pointer
+	types point to compatible address spaces.
+	(build_conditional_expr): Ditto.
+	(build_c_cast): Improve named address space type mismatch error.
+	(convert_for_assignment): Add support for checking whether
+	pointers are to compatible named addresses.
+
+	* target-def.h (TARGET_ADDR_SPACE_COMMON_POINTER): Delete.
+	(TARGET_ADDR_SPACE_SUBSET_P): New target hook.
+	(TARGET_ADDR_SPACE_HOOKS): Update target hooks.
+
+	* config/spu/spu.opt (-mno-ea-to-generic-conversion): Rename from
+	-mno-local-ea-conversion.
+	(-mea-to-generic-conversion): Rename from
+	-mealocal-ea-conversion.
+	(-mno-address-space-conversion): New switch to
+	prevent automatic conversions of pointers to different named
+	addresses from happening automatically.
+	(-maddress-space-conversion): New default switch.
+
+	* config/spu/spu.c (ADDR_SPACE_BAD): New address space to return
+	in error conditions.
+	(TARGET_ADDR_SPACE_COMMON_POINTER): Delete.
+	(spu_addr_space_common_pointer): Ditto.
+	(TARGET_ADDR_SPACE_SUBSET_P): New target hook.
+	(spu_addr_space_subset_p): New function to determine if one named
+	address is a subset of another.
+	(spu_addr_space_can_convert_p): Change -mno-local-ea-conversion to
+	-mno-ea-to-generic-conversion.
+	(spu_addr_space_nop_convert_p): Whitespace changes.
+
+	* convert.c (convert_to_pointer): Improve the named address space
+	mismatch error message.
+
 2008-12-03  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
 	* tree.c (int_or_pointer_precision): Simplify if assertion
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 142412)
+++ gcc/c-decl.c	(working copy)
@@ -1254,10 +1254,22 @@ diagnose_mismatched_decls (tree newdecl,
 	      addr_space_t new_addr = DECODE_QUAL_ADDR_SPACE (new_quals);
 	      addr_space_t old_addr = DECODE_QUAL_ADDR_SPACE (old_quals);
 	      if (new_addr != old_addr)
-		error ("conflicting named address spaces (%s vs %s) for %q+D",
-		       targetm.addr_space.name (new_addr),
-		       targetm.addr_space.name (old_addr),
-		       newdecl);
+		{
+		  if (!new_addr)
+		    error ("conflicting named address spaces (generic vs %s) "
+			   "for %q+D",
+			   targetm.addr_space.name (old_addr), newdecl);
+		  else if (!old_addr)
+		    error ("conflicting named address spaces (%s vs generic) "
+			   "for %q+D",
+			   targetm.addr_space.name (new_addr), newdecl);
+		  else
+		    error ("conflicting named address spaces (%s vs %s) "
+			   "for %q+D",
+			   targetm.addr_space.name (new_addr),
+			   targetm.addr_space.name (old_addr),
+			   newdecl);
+		}
 
 	      if (CLEAR_QUAL_ADDR_SPACE (new_quals)
 		  != CLEAR_QUAL_ADDR_SPACE (old_quals))
@@ -3295,17 +3307,13 @@ start_decl (struct c_declarator *declara
   if (TREE_CODE (decl) == VAR_DECL
       && TREE_TYPE (decl) != error_mark_node
       && (addrspace = TYPE_ADDR_SPACE (TREE_TYPE (decl)))
+      && targetm.have_named_sections
       && (declspecs->storage_class == csc_static
 	  || (declspecs->storage_class == csc_none
 	      && !current_function_scope)
 	  || (declspecs->storage_class == csc_extern
 	      && initialized)))
-    {
-      if (!targetm.have_named_sections)
-	error ("%<%s%> definitions not supported for %qD",
-	       targetm.addr_space.name (addrspace), decl);
-      DECL_SECTION_NAME (decl) = targetm.addr_space.section_name (addrspace);
-    }
+    DECL_SECTION_NAME (decl) = targetm.addr_space.section_name (addrspace);
 
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
   decl_attributes (&decl, attributes, 0);
@@ -4141,9 +4149,18 @@ grokdeclarator (const struct c_declarato
     }
 
   if (as1 > 0 && as2 > 0 && as1 != as2)
-    error ("incompatible address space qualifiers %qs and %qs",
-	   targetm.addr_space.name (as1),
-	   targetm.addr_space.name (as2));
+    {
+      if (!as1)
+	error ("conflicting named address spaces (generic vs %s)",
+	       targetm.addr_space.name (as1));
+      else if (!as2)
+	error ("conflicting named address spaces (%s vs generic),",
+	       targetm.addr_space.name (as2));
+      else
+	error ("conflicting named address spaces (%s vs %s)",
+	       targetm.addr_space.name (as1),
+	       targetm.addr_space.name (as2));
+    }
   
   if (!flag_gen_aux_info && (TYPE_QUALS (element_type)))
     type = TYPE_MAIN_VARIANT (type);
@@ -7249,16 +7266,16 @@ build_null_declspecs (void)
 struct c_declspecs *
 declspecs_add_addrspace (struct c_declspecs *specs, tree addrspace)
 {
+  addr_space_t as = targetm.addr_space.number (addrspace);
   specs->non_sc_seen_p = true;
   specs->declspecs_seen_p = true;
 
-  if (specs->address_space > 0
-      && specs->address_space != targetm.addr_space.number (addrspace))
+  if (specs->address_space > 0 && specs->address_space != as)
     error ("incompatible address space qualifiers %qs and %qs",
-	   targetm.addr_space.name (targetm.addr_space.number (addrspace)),
+	   targetm.addr_space.name (as),
 	   targetm.addr_space.name (specs->address_space));
-
-  specs->address_space = targetm.addr_space.number (addrspace);
+  else
+    specs->address_space = as;
   return specs;
 }
 
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 142412)
+++ gcc/c-typeck.c	(working copy)
@@ -106,7 +106,9 @@ static int lvalue_p (const_tree);
 static void record_maybe_used_decl (tree);
 static int comptypes_internal (const_tree, const_tree);
 
-/* Return true if EXP is a null pointer constant, false otherwise.  */
+/* Return true if EXP is a null pointer constant, false otherwise.  If
+   different named address spaces are available, a null pointer to one address
+   space can be converted as a null pointer to another address space.  */
 
 static bool
 null_pointer_constant_p (const_tree expr)
@@ -249,8 +251,27 @@ c_type_promotes_to (tree type)
 static tree
 qualify_type (tree type, tree like)
 {
+  int quals = (TYPE_QUALS_NO_ADDR_SPACE (type)
+	       | TYPE_QUALS_NO_ADDR_SPACE (like));
+  addr_space_t as_type = TYPE_ADDR_SPACE (type);
+  addr_space_t as_like = TYPE_ADDR_SPACE (like);
+  addr_space_t as_common;
+
+  if (as_type == as_like)
+    as_common = as_type;
+
+  /* Two different named address spaces, check for one being a subset of the
+     other, and if there isn't a common superset address space, raise an
+     error.  */
+  else if (!targetm.addr_space.subset_p (as_type, as_like, &as_common))
+    {
+      as_common = 0;
+      error ("%qT and %qT are in different named address spaces",
+	     type, like);
+    }
+
   return c_build_qualified_type (type,
-				 TYPE_QUALS (type) | TYPE_QUALS (like));
+				 quals | ENCODE_QUAL_ADDR_SPACE (as_common));
 }
 
 /* Return true iff the given tree T is a variable length array.  */
@@ -574,12 +595,14 @@ common_pointer_type (tree t1, tree t2)
     target_quals = (quals1 | quals2);
 
   /* Determine the address space to use if the pointers point to different
-     named address spaces.  */
+     named address spaces and if so, whether one address space is a subset of
+     the other.  */
   as1 = TYPE_ADDR_SPACE (pointed_to_1);
   as2 = TYPE_ADDR_SPACE (pointed_to_2);
-  as_common = ((as1 == as2)
-	       ? as1
-	       : targetm.addr_space.common_pointer (as1, as2));
+  if (as1 == as2)
+    as_common = as1;
+  else if (!targetm.addr_space.subset_p (as1, as2, &as_common))
+    gcc_unreachable ();
 
   target_quals |= ENCODE_QUAL_ADDR_SPACE (as_common);
 
@@ -607,10 +630,10 @@ c_common_type (tree t1, tree t2)
   if (t2 == error_mark_node)
     return t1;
 
-  if (TYPE_QUALS_NO_ADDR_SPACE (t1) != TYPE_UNQUALIFIED)
+  if (TYPE_QUALS (t1) != TYPE_UNQUALIFIED)
     t1 = TYPE_MAIN_VARIANT (t1);
 
-  if (TYPE_QUALS_NO_ADDR_SPACE (t2) != TYPE_UNQUALIFIED)
+  if (TYPE_QUALS (t2) != TYPE_UNQUALIFIED)
     t2 = TYPE_MAIN_VARIANT (t2);
 
   if (TYPE_ATTRIBUTES (t1) != NULL_TREE)
@@ -1037,19 +1060,29 @@ comptypes_internal (const_tree type1, co
   return attrval == 2 && val == 1 ? 2 : val;
 }
 
-/* Return 1 if TTL and TTR are pointers to types that are equivalent,
-   ignoring their qualifiers.  */
+/* Return 1 if TTL and TTR are pointers to types that are equivalent, ignoring
+   their qualifiers, except for named address spaces.  If the pointers point to
+   different named addresses, then we must determine if one address space is a
+   subset of the other.  */
 
 static int
 comp_target_types (tree ttl, tree ttr)
 {
   int val;
-  tree mvl, mvr;
+  tree mvl = TREE_TYPE (ttl);
+  tree mvr = TREE_TYPE (ttr);
+  addr_space_t asl = TYPE_ADDR_SPACE (mvl);
+  addr_space_t asr = TYPE_ADDR_SPACE (mvr);
+  addr_space_t as_common = 0;
+
+  /* See if the pointers point to different address spaces.  */
+  if (asl != asr
+      && !targetm.addr_space.subset_p (asl, asr, &as_common)
+      && (asl != as_common))
+    return 0;
 
   /* Do not lose qualifiers on element types of array types that are
      pointer targets by taking their TYPE_MAIN_VARIANT.  */
-  mvl = TREE_TYPE (ttl);
-  mvr = TREE_TYPE (ttr);
   if (TREE_CODE (mvl) != ARRAY_TYPE)
     mvl = TYPE_MAIN_VARIANT (mvl);
   if (TREE_CODE (mvr) != ARRAY_TYPE)
@@ -3520,6 +3553,10 @@ build_conditional_expr (tree ifexp, tree
     }
   else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
     {
+      addr_space_t as1;
+      addr_space_t as2;
+      addr_space_t as_common = 0;
+
       if (comp_target_types (type1, type2))
 	result_type = common_pointer_type (type1, type2);
       else if (null_pointer_constant_p (orig_op1))
@@ -3544,6 +3581,16 @@ build_conditional_expr (tree ifexp, tree
 	  result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
 							  TREE_TYPE (type1)));
 	}
+      else if (((as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1)))
+		!= (as2 = TYPE_ADDR_SPACE (TREE_TYPE (type2))))
+	       && (TYPE_MAIN_VARIANT (TREE_TYPE (type1))
+		   == TYPE_MAIN_VARIANT (TREE_TYPE (type2)))
+	       && !targetm.addr_space.subset_p (as1, as2, &as_common))
+	{
+	  error ("pointers to incompatible address spaces used in conditional "
+		 "expression");
+	  result_type = type1;
+	}
       else
 	{
 	  pedwarn (input_location, 0, 
@@ -3771,10 +3818,22 @@ build_c_cast (tree type, tree expr)
 	  if (as_to != as_from
 	      && !targetm.addr_space.can_convert_p (as_from, as_to))
 	    {
-	      error ("cast to pointer to address space %s from pointer "
-		     "to address space %s",
-		     targetm.addr_space.name (as_to),
-		     targetm.addr_space.name (as_from));
+	      if (!as_from)
+		error ("cast to %s address space pointer from generic address "
+		       "space pointer",
+		       targetm.addr_space.name (as_to));
+
+	      else if (!as_to)
+		error ("cast to generic address space pointer from %s address "
+		       "space pointer",
+		       targetm.addr_space.name (as_from));
+
+	      else
+		error ("cast to %s address space pointer from %s address "
+		       "space pointer",
+		       targetm.addr_space.name (as_to),
+		       targetm.addr_space.name (as_from));
+
 	      return error_mark_node;
 	    }
 	}
@@ -4289,6 +4348,9 @@ convert_for_assignment (tree type, tree 
       tree mvr = ttr;
       bool is_opaque_pointer;
       int target_cmp = 0;   /* Cache comp_target_types () result.  */
+      addr_space_t asl;
+      addr_space_t asr;
+      addr_space_t as_common;
 
       if (TREE_CODE (mvl) != ARRAY_TYPE)
 	mvl = TYPE_MAIN_VARIANT (mvl);
@@ -4308,6 +4370,38 @@ convert_for_assignment (tree type, tree 
 	warning (OPT_Wc___compat, "request for implicit conversion from "
 		 "%qT to %qT not permitted in C++", rhstype, type);
 
+	      /* See if the pointers point to incompatible address spaces.  */
+      asl = TYPE_ADDR_SPACE (ttl);
+      asr = TYPE_ADDR_SPACE (ttr);
+      as_common = 0;
+      if ((asl != asr)
+	  && !null_pointer_constant_p (rhs)
+	  && !targetm.addr_space.subset_p (asl, asr, &as_common)
+	  && asl != as_common)
+	{
+	  switch (errtype)
+	    {
+	    case ic_argpass:
+	      error ("passing argument %d of %qE is a pointer to an "
+		     "incompatible address space", parmnum, rname);
+	      break;
+	    case ic_assign:
+	      error ("assignment to a pointer to an incompatible address "
+		     "space");
+	      break;
+	    case ic_init:
+	      error ("initialization of a pointer to an incompatible space"
+		     "address space");
+	      break;
+	    case ic_return:
+	      error ("return of a pointer to an incompatible address space");
+	      break;
+	    default:
+	      gcc_unreachable ();
+	    }
+	  return error_mark_node;
+      }
+
       /* Check if the right-hand side has a format attribute but the
 	 left-hand side doesn't.  */
       if (warn_missing_format_attribute
Index: gcc/target-def.h
===================================================================
--- gcc/target-def.h	(revision 142412)
+++ gcc/target-def.h	(working copy)
@@ -477,8 +477,8 @@
 #define TARGET_ADDR_SPACE_NOP_CONVERT_P default_addr_space_nop_convert_p
 #endif
 
-#ifndef TARGET_ADDR_SPACE_COMMON_POINTER
-#define TARGET_ADDR_SPACE_COMMON_POINTER default_addr_space_common_pointer
+#ifndef TARGET_ADDR_SPACE_SUBSET_P
+#define TARGET_ADDR_SPACE_SUBSET_P default_addr_space_subset_p
 #endif
 
 #ifndef TARGET_ADDR_SPACE_CONVERT
@@ -500,7 +500,7 @@
     TARGET_ADDR_SPACE_NUMBER,			\
     TARGET_ADDR_SPACE_CAN_CONVERT_P,		\
     TARGET_ADDR_SPACE_NOP_CONVERT_P,		\
-    TARGET_ADDR_SPACE_COMMON_POINTER,		\
+    TARGET_ADDR_SPACE_SUBSET_P,			\
     TARGET_ADDR_SPACE_CONVERT,			\
     TARGET_ADDR_SPACE_VALID_P,			\
     TARGET_ADDR_SPACE_SECTION_NAME,		\
Index: gcc/config/spu/spu.opt
===================================================================
--- gcc/config/spu/spu.opt	(revision 142412)
+++ gcc/config/spu/spu.opt	(working copy)
@@ -91,10 +91,21 @@ mea64
 Target Report RejectNegative Var(spu_ea_model,64) VarExists
 Access variables in 64-bit PPU objects
 
-mno-local-ea-conversion
-Target Report RejectNegative Mask(NO_LOCAL_EA_CONVERSION)
-Don't allow pointers in the __ea address space to be converted to local pointers.
+mno-ea-to-generic-conversion
+Target Report RejectNegative Mask(NO_EA_TO_GENERIC_CONVERSION)
+Don't allow pointers in the __ea address space to be converted to generic pointers.
 
-mlocal-ea-conversion
-Target Report RejectNegative InverseMask(NO_LOCAL_EA_CONVERSION)
+mea-to-generic-conversion
+Target Report RejectNegative InverseMask(NO_EA_TO_GENERIC_CONVERSION)
 Allow pointers in the __ea address space to be converted to local pointers (default).
+
+mno-address-space-conversion
+Target Report RejectNegative Mask(NO_ADDRESS_SPACE_CONVERSION)
+Do not allow automatic conversion between pointers to different named address
+spaces (__ea and generic) without an explicit cast.
+
+maddress-space-conversion
+Target Report RejectNegative InverseMask(NO_ADDRESS_SPACE_CONVERSION)
+Allow automatic conversion between pointers to different named address spaces
+(__ea and generic) without an explicit cast.
+
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	(revision 142412)
+++ gcc/config/spu/spu.c	(working copy)
@@ -82,6 +82,7 @@ static struct spu_builtin_range spu_buil
 /* Address spaces */
 #define ADDR_SPACE_GENERIC	0
 #define ADDR_SPACE_EA		1
+#define ADDR_SPACE_BAD		255
 
 
 /*  Target specific attribute specifications.  */
@@ -230,10 +231,10 @@ static bool spu_addr_space_nop_convert_p
 #undef TARGET_ADDR_SPACE_NOP_CONVERT_P
 #define TARGET_ADDR_SPACE_NOP_CONVERT_P spu_addr_space_nop_convert_p
 
-static addr_space_t spu_addr_space_common_pointer (addr_space_t,
-						   addr_space_t);
-#undef TARGET_ADDR_SPACE_COMMON_POINTER
-#define TARGET_ADDR_SPACE_COMMON_POINTER spu_addr_space_common_pointer
+static bool spu_addr_space_subset_p (addr_space_t, addr_space_t,
+				     addr_space_t *);
+#undef TARGET_ADDR_SPACE_SUBSET_P
+#define TARGET_ADDR_SPACE_SUBSET_P spu_addr_space_subset_p
 
 static rtx spu_addr_space_convert (rtx, enum machine_mode, addr_space_t,
 				   addr_space_t);
@@ -6619,14 +6620,8 @@ spu_libgcc_shift_count_mode (void)
 static const char *
 spu_addr_space_name (addr_space_t addrspace)
 {
-  switch (addrspace)
-    {
-    case ADDR_SPACE_GENERIC:
-      return "generic";
-
-    case ADDR_SPACE_EA:
-      return "__ea";
-    }
+  if (addrspace == ADDR_SPACE_EA)
+    return "__ea";
 
   gcc_unreachable ();
 }
@@ -6634,13 +6629,12 @@ spu_addr_space_name (addr_space_t addrsp
 /* Determine if you can convert one address to another.  */
 
 static bool
-spu_addr_space_can_convert_p (addr_space_t from,
-			      addr_space_t to)
+spu_addr_space_can_convert_p (addr_space_t from, addr_space_t to)
 {
   gcc_assert (from == ADDR_SPACE_GENERIC || from == ADDR_SPACE_EA);
   gcc_assert (to == ADDR_SPACE_GENERIC || to == ADDR_SPACE_EA);
 
-  if (TARGET_NO_LOCAL_EA_CONVERSION
+  if (TARGET_NO_EA_TO_GENERIC_CONVERSION
       && from == ADDR_SPACE_EA
       && to == ADDR_SPACE_GENERIC)
     return false;
@@ -6651,25 +6645,44 @@ spu_addr_space_can_convert_p (addr_space
 /* Determine if converting one address to another is a NOP.  */
 
 static bool
-spu_addr_space_nop_convert_p (addr_space_t from,
-			      addr_space_t to)
+spu_addr_space_nop_convert_p (addr_space_t from, addr_space_t to)
 {
   gcc_assert (from == ADDR_SPACE_GENERIC || from == ADDR_SPACE_EA);
   gcc_assert (to == ADDR_SPACE_GENERIC || to == ADDR_SPACE_EA);
   return (to == from);
 }
 
-/* Determine what named address space pointer to use between pointers to two
-   different address spaces.  */
+/* Determine if one named address space is a subset of another.  */
 
-static addr_space_t
-spu_addr_space_common_pointer (addr_space_t as1,
-			       addr_space_t as2)
+static bool
+spu_addr_space_subset_p (addr_space_t as1,
+			 addr_space_t as2,
+			 addr_space_t *common_as)
 {
   gcc_assert (as1 == ADDR_SPACE_GENERIC || as1 == ADDR_SPACE_EA);
   gcc_assert (as2 == ADDR_SPACE_GENERIC || as2 == ADDR_SPACE_EA);
 
-  return (as1 == as2) ? as1 : ADDR_SPACE_EA;
+  if (as1 == as2)
+    {
+      *common_as = as1;
+      return true;
+    }
+
+  /* If we have -mno-address-space-conversion, treat __ea and generic as not
+     being subsets but instead as disjoint address spaces.  This will require
+     the user to explicitly convert between the different address spaces,
+     instead of relying on the compiler to do it automatically.  */
+  else if (TARGET_NO_ADDRESS_SPACE_CONVERSION)
+    {
+      *common_as = ADDR_SPACE_BAD;
+      return false;
+    }
+
+  else
+    {
+      *common_as = ADDR_SPACE_EA;
+      return true;
+    }
 }
 
 /* Convert from one address space to another.  */
Index: gcc/convert.c
===================================================================
--- gcc/convert.c	(revision 142412)
+++ gcc/convert.c	(working copy)
@@ -68,10 +68,20 @@ convert_to_pointer (tree type, tree expr
 	{
 	  if (! targetm.addr_space.can_convert_p (from_as, to_as))
 	    {
-	      error ("cannot convert %s address space pointers to "
-		     "%s address space pointers",
-		     targetm.addr_space.name (from_as),
-		     targetm.addr_space.name (to_as));
+	      if (!from_as)
+		error ("cannot convert generic address space pointers to "
+		       "%s address space pointers",
+		       targetm.addr_space.name (to_as));
+	      else if (!to_as)
+		error ("cannot convert %s address space pointers to "
+		       "generic address space pointers",
+		       targetm.addr_space.name (from_as));
+	      else
+		error ("cannot convert %s address space pointers to "
+		       "%s address space pointers",
+		       targetm.addr_space.name (from_as),
+		       targetm.addr_space.name (to_as));
+
 	      return convert_to_pointer (type, integer_zero_node);
 	    }
 

-- 
Michael Meissner, IBM
4 Technology Place Drive, MS 2203A, Westford, MA, 01886, USA
meissner@linux.vnet.ibm.com



More information about the Gcc-patches mailing list