This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[named-addr-spaces-branch][Patch,commited] Fix ptr to __ea address space -> int convert, Add -mno-local-ea-conversion


This patch fixes pointer to __ea named address space conversion to int.  I
added a new switch -mno-local-ea-conversion switch to disallow conversions of
__ea pointers to local address spaces.  In terms of changes needed for named
address, I think the one change left to do is make a target hook to say what
type of pointer to use when two pointers to different address spaces are used
(or make it an error).

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

	* tree.h (TYPE_QUALS_NO_ADDR_SPACE): New macro, like TYPE_QUALS,
	without the address space qualifiers.

	* expr.c (expand_expr_real_1): Add check in converting one pointer
	to another whether you can convert between different named address
	spaces.

	* c-decl.c (null_pointer_constant_p): Use TYPE_QUALS_NO_ADDR_SPACE
	instead of TYPE_QUALS.
	(composite_type): Ditto.
	(c_common_type): Ditto.
	(build_c_cast): Ditto.
	(convert_for_assignment): Ditto.
	(build_c_cast): Add error message if it is not possible to convert
	from one pointer to another.

	* convert.c (convert_to_integer): When converting pointers to
	integer, use the address space the pointer points to and not the
	pointer itself.
	
	* config/spu/spu.opt (-mno-local-ea-conversion): New switch to
	disallow converting __ea pointers to local pointers.
	(-mlocal-ea-conversion): New switch for the default case.

	* config/spu/spu.md (to_ea): Revert previous code.
	(from_ea): Ditto.

	* doc/invoke.texi (-mlocal-ea-conversion): Document.
	(-mno-local-ea-conversion): Ditto.

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

	* gcc.target/spu/ea/errors2.c: New test to test
	-mno-local-ea-conversion switch.

Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 142261)
+++ gcc/doc/invoke.texi	(working copy)
@@ -800,6 +800,7 @@ 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
 -matomic-updates -mno-atomic-updates}
 
 @emph{System V Options}
@@ -15009,6 +15010,14 @@ 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
+
+Allow/disallow pointers to the @code{__ea} address space to be
+converted local pointers.
+
 @item -mcache-size=@var{cache-size}
 @opindex mcache-size
 
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 142261)
+++ gcc/tree.h	(working copy)
@@ -2210,6 +2210,12 @@ struct tree_block GTY(())
    | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)		\
    | (ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (NODE))))
 
+/* The same as TYPE_QUALS without the address space qualifications.  */
+#define TYPE_QUALS_NO_ADDR_SPACE(NODE)				\
+  ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST)			\
+   | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE)		\
+   | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT))
+
 /* These flags are available for each language front end to use internally.  */
 #define TYPE_LANG_FLAG_0(NODE) (TYPE_CHECK (NODE)->type.lang_flag_0)
 #define TYPE_LANG_FLAG_1(NODE) (TYPE_CHECK (NODE)->type.lang_flag_1)
Index: gcc/testsuite/gcc.target/spu/ea/errors2.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/errors2.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/errors2.c	(revision 0)
@@ -0,0 +1,85 @@
+/* Invalid conversions of __ea pointers to local pointers.  */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -pedantic-errors -mno-local-ea-conversion" } */
+
+#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));	/* { dg-error "cast to pointer to address space generic from pointer to address space __ea" } */
+}
+
+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);	/* { dg-error "cast to pointer to address space generic from pointer to address space __ea" } */
+}
+
+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);	/* { dg-error "cast to pointer to address space generic from pointer to address space __ea" } */
+}
+
+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/expr.c
===================================================================
--- gcc/expr.c	(revision 142261)
+++ gcc/expr.c	(working copy)
@@ -8143,16 +8143,20 @@ expand_expr_real_1 (tree exp, rtx target
       /* Handle casts of pointers to/from address space qualified
 	 pointers.  */
       subexp0 = TREE_OPERAND (exp, 0);
-      if (POINTER_TYPE_P (type)
-	  && POINTER_TYPE_P (TREE_TYPE (subexp0))
-	  && (TYPE_ADDR_SPACE (TREE_TYPE (type))
-	      != TYPE_ADDR_SPACE (TREE_TYPE (subexp0))))
-	{
-	  op0 = expand_expr (subexp0, NULL_RTX, VOIDmode, modifier);
-	  return targetm.addr_space.convert (op0,
-					     TYPE_MODE (type),
-					     TYPE_ADDR_SPACE (TREE_TYPE (subexp0)),
-					     TYPE_ADDR_SPACE (TREE_TYPE (type)));
+      if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE (subexp0)))
+	{
+	  tree subexp0_type = TREE_TYPE (subexp0);
+	  addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type));
+	  addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (subexp0_type));
+
+	  if (as_to != as_from)
+	    {
+	      op0 = expand_expr (subexp0, NULL_RTX, VOIDmode, modifier);
+	      return targetm.addr_space.convert (op0,
+						 TYPE_MODE (type),
+						 as_from,
+						 as_to);
+	    }
 	}
 
       if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 142261)
+++ gcc/c-decl.c	(working copy)
@@ -3301,9 +3301,9 @@ start_decl (struct c_declarator *declara
 	  || (declspecs->storage_class == csc_extern
 	      && initialized)))
     {
-      /* FIXME: do not use __ea.  */
       if (!targetm.have_named_sections)
-	error ("%<__ea%> definitions not supported for %qD", decl);
+	error ("%<%s%> definitions not supported for %qD",
+	       targetm.addr_space.name (addrspace), decl);
       DECL_SECTION_NAME (decl) = targetm.addr_space.section_name (addrspace);
     }
 
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 142261)
+++ gcc/c-typeck.c	(working copy)
@@ -120,7 +120,8 @@ null_pointer_constant_p (const_tree expr
 	  && (INTEGRAL_TYPE_P (type)
 	      || (TREE_CODE (type) == POINTER_TYPE
 		  && VOID_TYPE_P (TREE_TYPE (type))
-		  && TYPE_QUALS (TREE_TYPE (type)) == TYPE_UNQUALIFIED)));
+		  && (TYPE_QUALS_NO_ADDR_SPACE (TREE_TYPE (type))
+		      == TYPE_UNQUALIFIED))));
 }
 /* This is a cache to hold if two types are compatible or not.  */
 
@@ -328,7 +329,8 @@ composite_type (tree t1, tree t2)
 	bool d1_zero, d2_zero;
 
 	/* We should not have any type quals on arrays at all.  */
-	gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
+	gcc_assert (!TYPE_QUALS_NO_ADDR_SPACE (t1)
+		    && !TYPE_QUALS_NO_ADDR_SPACE (t2));
 
 	d1_zero = d1 == 0 || !TYPE_MAX_VALUE (d1);
 	d2_zero = d2 == 0 || !TYPE_MAX_VALUE (d2);
@@ -589,10 +591,10 @@ c_common_type (tree t1, tree t2)
   if (t2 == error_mark_node)
     return t1;
 
-  if (TYPE_QUALS (t1) != TYPE_UNQUALIFIED)
+  if (TYPE_QUALS_NO_ADDR_SPACE (t1) != TYPE_UNQUALIFIED)
     t1 = TYPE_MAIN_VARIANT (t1);
 
-  if (TYPE_QUALS (t2) != TYPE_UNQUALIFIED)
+  if (TYPE_QUALS_NO_ADDR_SPACE (t2) != TYPE_UNQUALIFIED)
     t2 = TYPE_MAIN_VARIANT (t2);
 
   if (TYPE_ATTRIBUTES (t1) != NULL_TREE)
@@ -3724,9 +3726,11 @@ build_c_cast (tree type, tree expr)
 		 are added, not when they're taken away.  */
 	      if (TREE_CODE (in_otype) == FUNCTION_TYPE
 		  && TREE_CODE (in_type) == FUNCTION_TYPE)
-		added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype));
+		added |= (TYPE_QUALS_NO_ADDR_SPACE (in_type)
+			  & ~TYPE_QUALS_NO_ADDR_SPACE (in_otype));
 	      else
-		discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
+		discarded |= (TYPE_QUALS_NO_ADDR_SPACE (in_otype)
+			      & ~TYPE_QUALS_NO_ADDR_SPACE (in_type));
 	    }
 	  while (TREE_CODE (in_type) == POINTER_TYPE
 		 && TREE_CODE (in_otype) == POINTER_TYPE);
@@ -3740,6 +3744,25 @@ build_c_cast (tree type, tree expr)
 	    warning (OPT_Wcast_qual, "cast discards qualifiers from pointer target type");
 	}
 
+      /* Determine whether a pointer to one named address space can be
+	 converted to a pointer to another named address. */
+      if (TREE_CODE (type) == POINTER_TYPE
+	  && TREE_CODE (otype) == POINTER_TYPE)
+	{
+	  addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type));
+	  addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (otype));
+
+	  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));
+	      return error_mark_node;
+	    }
+	}
+
       /* Warn about possible alignment problems.  */
       if (STRICT_ALIGNMENT
 	  && TREE_CODE (type) == POINTER_TYPE
@@ -4201,7 +4224,8 @@ convert_for_assignment (tree type, tree 
 		     certain things, it is okay to use a const or volatile
 		     function where an ordinary one is wanted, but not
 		     vice-versa.  */
-		  if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
+		  if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
+		      & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
 		    WARN_FOR_ASSIGNMENT (input_location, 0,
 					 G_("passing argument %d of %qE "
 					    "makes qualified function "
@@ -4215,7 +4239,8 @@ convert_for_assignment (tree type, tree 
 					 G_("return makes qualified function "
 					    "pointer from unqualified"));
 		}
-	      else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
+	      else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
+		       & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
 		WARN_FOR_ASSIGNMENT (input_location, 0,
 				     G_("passing argument %d of %qE discards "
 					"qualifiers from pointer target type"),
@@ -4330,7 +4355,8 @@ convert_for_assignment (tree type, tree 
 	  else if (TREE_CODE (ttr) != FUNCTION_TYPE
 		   && TREE_CODE (ttl) != FUNCTION_TYPE)
 	    {
-	      if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
+	      if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
+		  & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
 		{
 		  /* Types differing only by the presence of the 'volatile'
 		     qualifier are acceptable if the 'volatile' has been added
@@ -4370,7 +4396,8 @@ convert_for_assignment (tree type, tree 
 		 that say the function will not do certain things,
 		 it is okay to use a const or volatile function
 		 where an ordinary one is wanted, but not vice-versa.  */
-	      if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
+	      if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
+		  & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
 		WARN_FOR_ASSIGNMENT (input_location, 0,
 				     G_("passing argument %d of %qE makes "
 					"qualified function pointer "
Index: gcc/config/spu/spu.opt
===================================================================
--- gcc/config/spu/spu.opt	(revision 142261)
+++ gcc/config/spu/spu.opt	(working copy)
@@ -90,3 +90,11 @@ Access variables in 32-bit PPU objects
 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_EA_LOCAL_CONVERSION)
+Don't allow pointers in the __ea address space to be converted to local pointers.
+
+mlocal-ea-conversion
+Target Report RejectNegative InverseMask(NO_EA_LOCAL_CONVERSION)
+Allow pointers in the __ea address space to be converted to local pointers (default).
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	(revision 142261)
+++ gcc/config/spu/spu.c	(working copy)
@@ -6634,6 +6634,12 @@ spu_addr_space_can_convert_p (addr_space
 {
   gcc_assert (from == ADDR_SPACE_GENERIC || from == ADDR_SPACE_EA);
   gcc_assert (to == ADDR_SPACE_GENERIC || to == ADDR_SPACE_EA);
+
+  if (TARGET_NO_EA_LOCAL_CONVERSION
+      && from == ADDR_SPACE_EA
+      && to == ADDR_SPACE_GENERIC)
+    return false;
+
   return true;
 }
 
Index: gcc/config/spu/spu.md
===================================================================
--- gcc/config/spu/spu.md	(revision 142261)
+++ gcc/config/spu/spu.md	(working copy)
@@ -5248,24 +5248,17 @@ DONE;
 
   ls_mem = gen_rtx_MEM (DImode, gen_rtx_SYMBOL_REF (Pmode, "__ea_local_store"));
 
-  op0 = (REG_P (operands[0]) ? operands[0] : gen_reg_rtx (mode));
-
-  if (GET_MODE (operands[1]) == mode)
-    op1 = force_reg (mode, operands[1]);
-  else
-    {
-      op1 = gen_reg_rtx (mode);
-      convert_move (op1, operands[1], true);
-    }
+  op0 = force_reg (mode, operands[0]);
+  op1 = force_reg (Pmode, operands[1]);
 
   if (mode == Pmode)
     emit_insn (gen_addsi3 (op0, op1, force_reg (mode, gen_lowpart (mode, ls_mem))));
   else
-    emit_insn (gen_adddi3 (op0, op1, force_reg (mode, ls_mem)));
-
-  if (op0 != operands[0])
-    emit_move_insn (operands[0], op0);
-
+    {
+      rtx tmp = gen_reg_rtx (DImode);
+      emit_move_insn (tmp, gen_rtx_ZERO_EXTEND (DImode, op1));
+      emit_insn (gen_adddi3 (op0, tmp, force_reg (mode, ls_mem)));
+    }
   DONE;
 })
 
@@ -5280,22 +5273,76 @@ DONE;
   ls_mem = gen_rtx_MEM (DImode, gen_rtx_SYMBOL_REF (Pmode, "__ea_local_store"));
   ls = force_reg (Pmode, gen_lowpart (Pmode, ls_mem));
 
-  op0 = (REG_P (operands[0]) ? operands[0] : gen_reg_rtx (mode));
-
-  if (GET_MODE (operands[1]) == mode)
-    op1 = force_reg (mode, operands[1]);
-  else
-    {
-      op1 = gen_reg_rtx (mode);
-      convert_move (op1, operands[1], true);
-    }
-
+  op0 = force_reg (Pmode, operands[0]);
+  op1 = force_reg (mode, operands[1]);
   tmp = (mode == Pmode) ? op1 : force_reg (Pmode, gen_lowpart (Pmode, op1));
 
   emit_insn (gen_subsi3 (op0, tmp, ls));
-
-  if (op0 != operands[0])
-    emit_move_insn (operands[0], op0);
-
   DONE;
 })
+
+;; (define_expand "to_ea"
+;;   [(use (match_operand 0 "" ""))
+;;    (use (match_operand 1 "" ""))]
+;;   ""
+;; {
+;;   rtx ls_mem, op0, op1;
+;;   enum machine_mode mode = (spu_ea_model == 32) ? Pmode : DImode;
+;; 
+;;   ls_mem = gen_rtx_MEM (DImode, gen_rtx_SYMBOL_REF (Pmode, "__ea_local_store"));
+;; 
+;;   op0 = (REG_P (operands[0]) ? operands[0] : gen_reg_rtx (mode));
+;; 
+;;   if (GET_MODE (operands[1]) == mode)
+;;     {
+;;       debug_rtx (operands[1]);
+;;       op1 = force_reg (mode, operands[1]);
+;;     }
+;;   else
+;;     {
+;;       op1 = gen_reg_rtx (mode);
+;;       convert_move (op1, operands[1], true);
+;;     }
+;; 
+;;   if (mode == Pmode)
+;;     emit_insn (gen_addsi3 (op0, op1, force_reg (mode, gen_lowpart (mode, ls_mem))));
+;;   else
+;;     emit_insn (gen_adddi3 (op0, op1, force_reg (mode, ls_mem)));
+;; 
+;;   if (op0 != operands[0])
+;;     emit_move_insn (operands[0], op0);
+;; 
+;;   DONE;
+;; })
+;; 
+;; (define_expand "from_ea"
+;;   [(use (match_operand 0 "" ""))
+;;    (use (match_operand 1 "" ""))]
+;;   ""
+;; {
+;;   rtx ls_mem, ls, op0, op1, tmp;
+;;   enum machine_mode mode = (spu_ea_model == 32) ? Pmode : DImode;
+;; 
+;;   ls_mem = gen_rtx_MEM (DImode, gen_rtx_SYMBOL_REF (Pmode, "__ea_local_store"));
+;;   ls = force_reg (Pmode, gen_lowpart (Pmode, ls_mem));
+;; 
+;;   op0 = (REG_P (operands[0]) ? operands[0] : gen_reg_rtx (mode));
+;; 
+;;   if (GET_MODE (operands[1]) == mode)
+;;     op1 = force_reg (mode, operands[1]);
+;;   else
+;;     {
+;;       op1 = gen_reg_rtx (mode);
+;;       convert_move (op1, operands[1], true);
+;;     }
+;; 
+;;   tmp = (mode == Pmode) ? op1 : force_reg (Pmode, gen_lowpart (Pmode, op1));
+;; 
+;;   emit_insn (gen_subsi3 (op0, tmp, ls));
+;; 
+;;   if (op0 != operands[0])
+;;     emit_move_insn (operands[0], op0);
+;; 
+;;   DONE;
+;; })
+ 
Index: gcc/convert.c
===================================================================
--- gcc/convert.c	(revision 142261)
+++ gcc/convert.c	(working copy)
@@ -518,7 +518,7 @@ convert_to_integer (tree type, tree expr
 
  	/* Convert to an unsigned integer of the correct width first,
  	   and from there widen/truncate to the required type.  */
-	as = TYPE_ADDR_SPACE (intype);
+	as = TYPE_ADDR_SPACE (TREE_TYPE (intype));
 	if (!as)
 	  pointer_size = POINTER_SIZE;
 

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]