This adds two hooks to determine address spaces for local and global
variables, and changes various places in the compiler to ensure stuff
goes to the right place.

If a type is given an address space in this way, the
TYPE_QUAL_AS_IMPLICIT is set. Such a flag is needed to properly handle
such types in situations like passing them to varargs and old-style
functions, and to make typeof behave as expected.

	gcc/c-family/
	* c-common.c (c_common_nodes_and_builtins): If globals need to go into
	a specific address space, rebuild the char array type nodes
	accordingly.

	gcc/c/
	* c-decl.c (start_function): Make the result live in the for_frame
	address space.
	(build_compound_literal): Choose an appropriate address
	space.
	(grokdeclarator): If no address space is specified, use the frame or
	global address space implicitly.
	* c-parser.c (c_parser_typeof_specifier): If it is set, drop the
	address space from the returned type.
	* c-typeck.c (convert_arguments): If we have no type, and a pointer arg
	which points to a type with implicit address space, convert the pointer
	so as to point to the generic address space.

	gcc/
	* target.def (for_frame, for_global): New hooks in addr_space.
	* cfgexpand.c (expand_one_stack_var_at): Use the frame address space.
	* emit-rtl.c (gen_frame_mem): Likewise.
	* function.c (assign_stack_local_1, assign_stack_temp_for_type):
	Likewise.
	(assign_parms_augmented_arg_list, assign_parms_find_data_types):
	Use build_pointer_type_in_frame.
	* calls.c (initialize_argument_information): When we make a copy,
	ensure the decl for it has the for_frame address space.
	* targhooks.c (std_gimplify_va_arg_expr): If an arg is passed by
	reference, assume it lives in the for_frame address space if that
	isn't the generic one.
	* tree-core.h (struct tree_base): Take a new as_implicit_flag out of
	spare0.
	(enum cv_qualifier): Add TYPE_QUAL_AS_IMPLICIT.
	* tree.h (build_pointer_type_in_frame): Declare.
	(TYPE_AS_IMPLICIT): New macro.
	(TYPE_QUALS): Take TYPE_QUAL_AS_IMPLICIT into account.
	* tree.c (set_type_quals): Likewise.
	(build_pointer_type_in_frame): New function.
	* targhooks.c (hook_return_generic_addr_space): New function.
	(hook_return_generic_addr_space_bool): New function.
	* targhooks.h (hook_return_generic_addr_space,
	(hook_return_generic_addr_space_bool): Declare.
	* tree-switch-conversion.c: Include "target.h".
	(build_one_array): Use the for_global hook to determine address space.
	* varasm.c (build_constant_desc): Likewise.
	* doc/tm.texi.in (TARGET_ADDR_SPACE_FOR_FRAME,
	TARGET_ADDR_SPACE_FOR_GLOBAL): Add hooks.
	* doc/tm.texi: Regenerate.

------------------------------------------------------------------------
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi.orig
+++ gcc/doc/tm.texi
@@ -10330,6 +10330,17 @@ guaranteed that one of the two address s
 as determined by the @code{TARGET_ADDR_SPACE_SUBSET_P} target hook.
 @end deftypefn
 
+@deftypefn {Target Hook} addr_space_t TARGET_ADDR_SPACE_FOR_FRAME (void)
+Define this if memory locations in the stack frame should use a different
+address space than the default. It returns the address space to use.
+@end deftypefn
+
+@deftypefn {Target Hook} addr_space_t TARGET_ADDR_SPACE_FOR_GLOBAL (bool @var{constp})
+Define this if global memory locations should use a different
+address space than the default. It returns the address space to use.
+If @var{constp} is nonzero, the variable will be constant.
+@end deftypefn
+
 @node Misc
 @section Miscellaneous Parameters
 @cindex parameters, miscellaneous
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in.orig
+++ gcc/doc/tm.texi.in
@@ -7669,6 +7669,10 @@ c_register_addr_space ("__ea", ADDR_SPAC
 
 @hook TARGET_ADDR_SPACE_CONVERT
 
+@hook TARGET_ADDR_SPACE_FOR_FRAME
+
+@hook TARGET_ADDR_SPACE_FOR_GLOBAL
+
 @node Misc
 @section Miscellaneous Parameters
 @cindex parameters, miscellaneous
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c.orig
+++ gcc/targhooks.c
@@ -1642,7 +1642,17 @@ std_gimplify_va_arg_expr (tree valist, t
 
   indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
   if (indirect)
-    type = build_pointer_type (type);
+    {
+      /* We assume that if there is a frame address space, the caller makes
+	 a copy.  */
+      addr_space_t as = targetm.addr_space.for_frame ();
+      if (!ADDR_SPACE_GENERIC_P (as))
+	type
+	  = build_qualified_type (type,
+				  TYPE_QUALS_NO_ADDR_SPACE (type)
+				  | ENCODE_QUAL_ADDR_SPACE (as));
+      type = build_pointer_type (type);
+    }
 
   align = PARM_BOUNDARY / BITS_PER_UNIT;
   boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
@@ -1750,4 +1760,16 @@ can_use_doloop_if_innermost (double_int,
   return loop_depth == 1;
 }
 
+addr_space_t
+hook_return_generic_addr_space (void)
+{
+  return ADDR_SPACE_GENERIC;
+}
+
+addr_space_t
+hook_return_generic_addr_space_bool (bool)
+{
+  return ADDR_SPACE_GENERIC;
+}
+
 #include "gt-targhooks.h"
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h.orig
+++ gcc/targhooks.h
@@ -164,6 +164,9 @@ extern rtx default_addr_space_legitimize
 						  addr_space_t);
 extern bool default_addr_space_subset_p (addr_space_t, addr_space_t);
 extern rtx default_addr_space_convert (rtx, tree, tree);
+extern addr_space_t hook_return_generic_addr_space (void);
+extern addr_space_t hook_return_generic_addr_space_bool (bool);
+
 extern unsigned int default_case_values_threshold (void);
 extern bool default_have_conditional_execution (void);
 
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c.orig
+++ gcc/c-family/c-common.c
@@ -5560,6 +5560,23 @@ c_common_nodes_and_builtins (void)
   char32_array_type_node
     = build_array_type (char32_type_node, array_domain_type);
 
+  addr_space_t as = targetm.addr_space.for_global (true);
+  if (!ADDR_SPACE_GENERIC_P (as))
+    {
+      int quals = ENCODE_QUAL_ADDR_SPACE (as) | TYPE_QUAL_AS_IMPLICIT;
+      char_array_type_node
+	= build_array_type (build_qualified_type (char_type_node, quals),
+			    array_domain_type);
+      char16_array_type_node
+	= build_array_type (build_qualified_type (char16_type_node, quals),
+			    array_domain_type);
+      char32_array_type_node
+	= build_array_type (build_qualified_type (char32_type_node, quals),
+			    array_domain_type);
+      wchar_array_type_node
+	= build_array_type (build_qualified_type (wchar_type_node, quals),
+			    array_domain_type);
+    }
   wint_type_node =
     TREE_TYPE (identifier_global_value (get_identifier (WINT_TYPE)));
 
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c.orig
+++ gcc/c/c-parser.c
@@ -2994,6 +2994,9 @@ c_parser_typeof_specifier (c_parser *par
 	error_at (here, "%<typeof%> applied to a bit-field");
       mark_exp_read (expr.value);
       ret.spec = TREE_TYPE (expr.value);
+      if (ret.spec != error_mark_node && TYPE_AS_IMPLICIT (ret.spec))
+	ret.spec = build_qualified_type (ret.spec,
+					 TYPE_QUALS_NO_ADDR_SPACE (ret.spec));
       was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
       /* This is returned with the type so that when the type is
 	 evaluated, this can be evaluated.  */
Index: gcc/c/c-typeck.c
===================================================================
--- gcc/c/c-typeck.c.orig
+++ gcc/c/c-typeck.c
@@ -3312,8 +3312,19 @@ convert_arguments (tree typelist, vec<tr
 	  return -1;
 	}
       else
-	/* Convert `short' and `char' to full-size `int'.  */
-	parmval = default_conversion (val);
+	{
+	  if (POINTER_TYPE_P (valtype)
+	      && TYPE_AS_IMPLICIT (TREE_TYPE (valtype)))
+	    {
+	      tree basetype = TREE_TYPE (valtype);
+	      int quals = TYPE_QUALS_NO_ADDR_SPACE (basetype);
+	      basetype = build_qualified_type (basetype, quals);
+	      basetype = build_pointer_type (basetype);
+	      val = convert (basetype, val);
+	    }
+	  /* Convert `short' and `char' to full-size `int'.  */
+	  parmval = default_conversion (val);
+	}
 
       (*values)[parmnum] = parmval;
       if (parmval == error_mark_node)
Index: gcc/c/c-decl.c
===================================================================
--- gcc/c/c-decl.c.orig
+++ gcc/c/c-decl.c
@@ -4665,6 +4665,17 @@ build_compound_literal (location_t loc,
       || init == error_mark_node)
     return error_mark_node;
 
+  addr_space_t as;
+  if (current_function_decl)
+    as = targetm.addr_space.for_frame ();
+  else
+    as = targetm.addr_space.for_global (!non_const);
+  if (!ADDR_SPACE_GENERIC_P (as)
+      && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type)))
+    type = build_qualified_type (type,
+				 (TYPE_QUALS_NO_ADDR_SPACE (type)
+				  | ENCODE_QUAL_ADDR_SPACE (as)));
+
   decl = build_decl (loc, VAR_DECL, NULL_TREE, type);
   DECL_EXTERNAL (decl) = 0;
   TREE_PUBLIC (decl) = 0;
@@ -5850,6 +5861,33 @@ grokdeclarator (const struct c_declarato
 		   c_addr_space_name (address_space));
 	}
     }
+  else if ((current_function_scope
+	    || (decl_context == PARM
+		&& TREE_CODE (type) != ARRAY_TYPE
+		&& TREE_CODE (type) != VOID_TYPE))
+	   && (storage_class == csc_auto || storage_class == csc_none)
+	   && decl_context != TYPENAME)
+    {
+      addr_space_t new_as = targetm.addr_space.for_frame ();
+      if (!ADDR_SPACE_GENERIC_P (new_as))
+	type_quals = (CLEAR_QUAL_ADDR_SPACE (type_quals)
+		      | TYPE_QUAL_AS_IMPLICIT
+		      | ENCODE_QUAL_ADDR_SPACE (new_as));
+    }
+  else if ((!current_function_scope
+	    || storage_class == csc_static
+	    || storage_class == csc_extern)
+	   && decl_context == NORMAL
+	   && declarator->kind != cdk_function
+	   && storage_class != csc_typedef)
+    {
+      bool is_const = (type_quals & TYPE_QUAL_CONST) != 0;
+      addr_space_t new_as = targetm.addr_space.for_global (is_const);
+      if (!ADDR_SPACE_GENERIC_P (new_as))
+	type_quals = (CLEAR_QUAL_ADDR_SPACE (type_quals)
+		      | TYPE_QUAL_AS_IMPLICIT
+		      | ENCODE_QUAL_ADDR_SPACE (new_as));
+    }
 
   /* Check the type and width of a bit-field.  */
   if (bitfield)
@@ -8024,6 +8062,12 @@ start_function (struct c_declspecs *decl
   declare_parm_level ();
 
   restype = TREE_TYPE (TREE_TYPE (current_function_decl));
+  addr_space_t as = targetm.addr_space.for_frame ();
+  if (!ADDR_SPACE_GENERIC_P (as))
+    restype
+      = build_qualified_type (restype,
+			      TYPE_QUALS_NO_ADDR_SPACE (restype)
+			      | ENCODE_QUAL_ADDR_SPACE (as));
   resdecl = build_decl (loc, RESULT_DECL, NULL_TREE, restype);
   DECL_ARTIFICIAL (resdecl) = 1;
   DECL_IGNORED_P (resdecl) = 1;
Index: gcc/target.def
===================================================================
--- gcc/target.def.orig
+++ gcc/target.def
@@ -3017,6 +3017,21 @@ as determined by the @code{TARGET_ADDR_S
  rtx, (rtx op, tree from_type, tree to_type),
  default_addr_space_convert)
 
+DEFHOOK
+(for_frame,
+ "Define this if memory locations in the stack frame should use a different\n\
+address space than the default. It returns the address space to use.",
+ addr_space_t, (void),
+ hook_return_generic_addr_space)
+
+DEFHOOK
+(for_global,
+ "Define this if global memory locations should use a different\n\
+address space than the default. It returns the address space to use.\n\
+If @var{constp} is nonzero, the variable will be constant.",
+ addr_space_t, (bool constp),
+ hook_return_generic_addr_space_bool)
+
 HOOK_VECTOR_END (addr_space)
 
 #undef HOOK_PREFIX
Index: gcc/tree.c
===================================================================
--- gcc/tree.c.orig
+++ gcc/tree.c
@@ -6078,6 +6078,7 @@ set_type_quals (tree type, int type_qual
   TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
   TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
   TYPE_ATOMIC (type) = (type_quals & TYPE_QUAL_ATOMIC) != 0;
+  TYPE_AS_IMPLICIT (type) = (type_quals & TYPE_QUAL_AS_IMPLICIT) != 0;
   TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
 }
 
@@ -7581,6 +7582,22 @@ build_pointer_type (tree to_type)
   return build_pointer_type_for_mode (to_type, pointer_mode, false);
 }
 
+/* Like build_pointer_type, but adjust the address space of the resulting
+   pointer type as appropriate for an object living in the stack frame.  */
+
+tree
+build_pointer_type_in_frame (tree to_type)
+{
+  tree type = build_pointer_type (to_type);
+  addr_space_t as = targetm.addr_space.for_frame ();
+  if (!ADDR_SPACE_GENERIC_P (as))
+    type
+      = build_qualified_type (type,
+			      TYPE_QUALS_NO_ADDR_SPACE (type)
+			      | ENCODE_QUAL_ADDR_SPACE (as));
+  return type;
+}
+
 /* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE.  */
 
 tree
Index: gcc/tree.h
===================================================================
--- gcc/tree.h.orig
+++ gcc/tree.h
@@ -1628,6 +1628,11 @@ extern void protected_set_expr_location
 /* If nonzero, type's name shouldn't be emitted into debug info.  */
 #define TYPE_NAMELESS(NODE) (TYPE_CHECK (NODE)->base.u.bits.nameless_flag)
 
+/* If nonzero, the address space was chosen implicitly due to target
+   requirements.  */
+#define TYPE_AS_IMPLICIT(NODE) \
+  (TYPE_CHECK (NODE)->base.u.bits.as_implicit_flag)
+
 /* The address space the type is in.  */
 #define TYPE_ADDR_SPACE(NODE) (TYPE_CHECK (NODE)->base.u.bits.address_space)
 
@@ -1649,6 +1654,7 @@ extern void protected_set_expr_location
 	  | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE)		\
 	  | (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC)		\
 	  | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)		\
+	  | (TYPE_AS_IMPLICIT (NODE) * TYPE_QUAL_AS_IMPLICIT)	\
 	  | (ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (NODE)))))
 
 /* The same as TYPE_QUALS without the address space qualifications.  */
@@ -3604,6 +3610,7 @@ extern tree unsigned_type_for (tree);
 extern tree truth_type_for (tree);
 extern tree build_pointer_type_for_mode (tree, enum machine_mode, bool);
 extern tree build_pointer_type (tree);
+extern tree build_pointer_type_in_frame (tree);
 extern tree build_reference_type_for_mode (tree, enum machine_mode, bool);
 extern tree build_reference_type (tree);
 extern tree build_vector_type_for_mode (tree, enum machine_mode);
Index: gcc/function.c
===================================================================
--- gcc/function.c.orig
+++ gcc/function.c
@@ -478,6 +478,7 @@ assign_stack_local_1 (enum machine_mode
 
   x = gen_rtx_MEM (mode, addr);
   set_mem_align (x, alignment_in_bits);
+  set_mem_addr_space (x, targetm.addr_space.for_frame ());
   MEM_NOTRAP_P (x) = 1;
 
   stack_slot_list
@@ -886,6 +887,7 @@ assign_stack_temp_for_type (enum machine
 
   /* Create a new MEM rtx to avoid clobbering MEM flags of old slots.  */
   slot = gen_rtx_MEM (mode, XEXP (p->slot, 0));
+  set_mem_addr_space (slot, targetm.addr_space.for_frame ());
   stack_slot_list = gen_rtx_EXPR_LIST (VOIDmode, slot, stack_slot_list);
 
   /* If we know the alias set for the memory that will be used, use
@@ -2299,7 +2301,7 @@ assign_parms_augmented_arg_list (struct
       && ! cfun->returns_pcc_struct
       && targetm.calls.struct_value_rtx (TREE_TYPE (fndecl), 1) == 0)
     {
-      tree type = build_pointer_type (TREE_TYPE (fntype));
+      tree type = build_pointer_type_in_frame (TREE_TYPE (fntype));
       tree decl;
 
       decl = build_decl (DECL_SOURCE_LOCATION (fndecl),
@@ -2381,7 +2383,7 @@ assign_parm_find_data_types (struct assi
   if (pass_by_reference (&all->args_so_far_v, passed_mode,
 			 passed_type, data->named_arg))
     {
-      passed_type = nominal_type = build_pointer_type (passed_type);
+      passed_type = nominal_type = build_pointer_type_in_frame (passed_type);
       data->passed_pointer = true;
       passed_mode = nominal_mode = TYPE_MODE (nominal_type);
     }
Index: gcc/calls.c
===================================================================
--- gcc/calls.c.orig
+++ gcc/calls.c
@@ -1270,6 +1270,13 @@ initialize_argument_information (int num
 	      if (!callee_copies && *ecf_flags & ECF_PURE)
 		*ecf_flags &= ~(ECF_PURE | ECF_LOOPING_CONST_OR_PURE);
 
+	      addr_space_t as = MEM_ADDR_SPACE (copy);
+	      if (!ADDR_SPACE_GENERIC_P (as))
+		type
+		  = build_qualified_type (type,
+					  TYPE_QUALS_NO_ADDR_SPACE (type)
+					  | ENCODE_QUAL_ADDR_SPACE (as));
+
 	      args[i].tree_value
 		= build_fold_addr_expr_loc (loc, make_tree (type, copy));
 	      type = TREE_TYPE (args[i].tree_value);
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c.orig
+++ gcc/emit-rtl.c
@@ -662,12 +662,13 @@ gen_frame_mem (enum machine_mode mode, r
   rtx mem = gen_rtx_MEM (mode, addr);
   MEM_NOTRAP_P (mem) = 1;
   set_mem_alias_set (mem, get_frame_alias_set ());
+  set_mem_addr_space (mem, targetm.addr_space.for_frame ());
   return mem;
 }
 
 /* Generate a MEM referring to a temporary use of the stack, not part
-    of the fixed stack frame.  For example, something which is pushed
-    by a target splitter.  */
+   of the fixed stack frame.  For example, something which is pushed
+   by a target splitter.  */
 rtx
 gen_tmp_stack_mem (enum machine_mode mode, rtx addr)
 {
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c.orig
+++ gcc/cfgexpand.c
@@ -850,6 +850,7 @@ expand_one_stack_var_at (tree decl, rtx
 
   x = plus_constant (Pmode, base, offset);
   x = gen_rtx_MEM (DECL_MODE (SSAVAR (decl)), x);
+  set_mem_addr_space (x, targetm.addr_space.for_frame ());
 
   if (TREE_CODE (decl) != SSA_NAME)
     {
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c.orig
+++ gcc/varasm.c
@@ -3205,9 +3205,14 @@ build_constant_desc (tree exp)
   labelno = const_labelno++;
   ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
 
+  tree type = TREE_TYPE (exp);
+  addr_space_t as = targetm.addr_space.for_global (true);
+  if (!ADDR_SPACE_GENERIC_P (as))
+    type = build_qualified_type (type, (TYPE_QUALS_NO_ADDR_SPACE (type)
+					| ENCODE_QUAL_ADDR_SPACE (as)));
+
   /* Construct the VAR_DECL associated with the constant.  */
-  decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (label),
-		     TREE_TYPE (exp));
+  decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (label), type);
   DECL_ARTIFICIAL (decl) = 1;
   DECL_IGNORED_P (decl) = 1;
   TREE_READONLY (decl) = 1;
@@ -3244,6 +3249,7 @@ build_constant_desc (tree exp)
 
   rtl = gen_const_mem (TYPE_MODE (TREE_TYPE (exp)), symbol);
   set_mem_attributes (rtl, exp, 1);
+  set_mem_addr_space (rtl, as);
   set_mem_alias_set (rtl, 0);
   set_mem_alias_set (rtl, const_alias_set);
 
Index: gcc/tree-switch-conversion.c
===================================================================
--- gcc/tree-switch-conversion.c.orig
+++ gcc/tree-switch-conversion.c
@@ -46,6 +46,7 @@ Software Foundation, 51 Franklin Street,
 #include "tree-pass.h"
 #include "gimple-pretty-print.h"
 #include "cfgloop.h"
+#include "target.h"
 
 /* ??? For lang_hooks.types.type_for_mode, but is there a word_mode
    type in the GIMPLE type system that is language-independent?  */
@@ -1043,6 +1044,14 @@ build_one_array (gimple swtch, int num,
 
       default_type = TREE_TYPE (info->default_values[num]);
       value_type = array_value_type (swtch, default_type, num, info);
+      addr_space_t as = targetm.addr_space.for_global (true);
+      if (!ADDR_SPACE_GENERIC_P (as))
+	{
+	  value_type
+	    = build_qualified_type (value_type,
+				    TYPE_QUALS_NO_ADDR_SPACE (value_type)
+				    | ENCODE_QUAL_ADDR_SPACE (as));
+	}
       array_type = build_array_type (value_type, arr_index_type);
       if (default_type != value_type)
 	{
Index: gcc/tree-core.h
===================================================================
--- gcc/tree-core.h.orig
+++ gcc/tree-core.h
@@ -369,7 +369,8 @@ enum cv_qualifier {
   TYPE_QUAL_CONST    = 0x1,
   TYPE_QUAL_VOLATILE = 0x2,
   TYPE_QUAL_RESTRICT = 0x4,
-  TYPE_QUAL_ATOMIC   = 0x8
+  TYPE_QUAL_ATOMIC   = 0x8,
+  TYPE_QUAL_AS_IMPLICIT = 0x10
 };
 
 /* Enumerate visibility settings.  */
@@ -746,7 +747,8 @@ struct GTY(()) tree_base {
       unsigned user_align : 1;
       unsigned nameless_flag : 1;
       unsigned atomic_flag : 1;
-      unsigned spare0 : 3;
+      unsigned as_implicit_flag : 1;
+      unsigned spare0 : 2;
 
       unsigned spare1 : 8;
 

Reply via email to