public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* PATCH: named address space support (1/2: target-independent parts)
@ 2008-08-20  7:29 Ben Elliston
  2008-08-20 10:36 ` Richard Guenther
                   ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: Ben Elliston @ 2008-08-20  7:29 UTC (permalink / raw)
  To: gcc-patches

This patch introduces all of the target-independent code from the
named-addr-spaces-branch into mainline.  It implements a sensible subset
of the named address space functionality described in:

  http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf

The current state of the implementation is:

  - a target can define any number of address spaces;

  - the target defines how pointers are transformed when
    cast to/from the generic address space;

  - casts between two non-generic address spaces is not yet
    implemented, but there is nothing about the implementation
    that would prevent this from being added at a later
    stage.

I will post a follow-up patch that brings across the SPU backend
changes.

This code has been in use in the Cell SDK compiler for some time, so is
quite well exercised already.  This patch has been tested with a
bootstrap on x86_64-linux and powerpc-linux, regression tested on
spu-elf (no regressions), and doco changes were tested by "make info
dvi" and visual inspection.

Okay for mainline?

Thanks, Ben



--- gcc-clean/gcc/c-decl.c	2008-08-14 13:27:13.000000000 +1000
+++ gcc-nas/gcc/c-decl.c	2008-08-20 11:50:29.000000000 +1000
@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3.  
 #include "except.h"
 #include "langhooks-def.h"
 #include "pointer-set.h"
+#include "targhooks.h"
 #include "gimple.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
@@ -2898,7 +2899,8 @@ shadow_tag_warned (const struct c_declsp
 	  else if (!declspecs->tag_defined_p
 		   && (declspecs->const_p
 		       || declspecs->volatile_p
-		       || declspecs->restrict_p))
+		       || declspecs->restrict_p
+		       || declspecs->address_space))
 	    {
 	      if (warned != 1)
 		pedwarn (0, "empty declaration with type qualifier "
@@ -2967,7 +2969,8 @@ shadow_tag_warned (const struct c_declsp
 
   if (!warned && !in_system_header && (declspecs->const_p
 				       || declspecs->volatile_p
-				       || declspecs->restrict_p))
+				       || declspecs->restrict_p
+				       || declspecs->address_space))
     {
       warning (0, "useless type qualifier in empty declaration");
       warned = 2;
@@ -2990,7 +2993,8 @@ quals_from_declspecs (const struct c_dec
 {
   int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
 	       | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
-	       | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0));
+	       | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
+	       | (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
   gcc_assert (!specs->type
 	      && !specs->decl_attr
 	      && specs->typespec_word == cts_none
@@ -3949,6 +3953,7 @@ grokdeclarator (const struct c_declarato
   int constp;
   int restrictp;
   int volatilep;
+  int addr_space_p;
   int type_quals = TYPE_UNQUALIFIED;
   const char *name, *orig_name;
   bool funcdef_flag = false;
@@ -4063,6 +4068,7 @@ grokdeclarator (const struct c_declarato
   constp = declspecs->const_p + TYPE_READONLY (element_type);
   restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
   volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
+  addr_space_p = (declspecs->address_space > 0) + (TYPE_ADDR_SPACE (element_type) > 0);
   if (pedantic && !flag_isoc99)
     {
       if (constp > 1)
@@ -4071,12 +4077,15 @@ grokdeclarator (const struct c_declarato
 	pedwarn (OPT_pedantic, "duplicate %<restrict%>");
       if (volatilep > 1)
 	pedwarn (OPT_pedantic, "duplicate %<volatile%>");
+      if (addr_space_p > 1)
+	pedwarn (OPT_pedantic, "duplicate %qs", targetm.addr_space_name (TYPE_ADDR_SPACE (element_type)));
     }
   if (!flag_gen_aux_info && (TYPE_QUALS (element_type)))
     type = TYPE_MAIN_VARIANT (type);
   type_quals = ((constp ? TYPE_QUAL_CONST : 0)
 		| (restrictp ? TYPE_QUAL_RESTRICT : 0)
-		| (volatilep ? TYPE_QUAL_VOLATILE : 0));
+		| (volatilep ? TYPE_QUAL_VOLATILE : 0)
+		| (addr_space_p ? ENCODE_QUAL_ADDR_SPACE (declspecs->address_space) : 0));
 
   /* Warn about storage classes that are invalid for certain
      kinds of declarations (parameters, typenames, etc.).  */
@@ -4102,6 +4111,56 @@ grokdeclarator (const struct c_declarato
 	  || storage_class == csc_typedef)
 	storage_class = csc_none;
     }
+  else if (declspecs->address_space)
+    {
+      const char *addrspace_name;
+
+      /* Does the target have named address spaces?  */
+      if (targetm.addr_space_name == default_addr_space_name)
+	{
+	  /* A mere warning is sure to result in improper semantics
+	     at runtime.  Don't bother to allow this to compile.  */
+	  error ("extended address space not supported for this target");
+	  return 0;
+	}
+
+      addrspace_name = targetm.addr_space_name (declspecs->address_space);
+      if (decl_context == NORMAL)
+	{
+	  if (declarator->kind == cdk_function)
+	    error ("%qs specified for function %qs", addrspace_name, name);
+	  else if (declarator->kind == cdk_id)
+	    {
+
+	      switch (storage_class)
+		{
+		case csc_auto:
+		  error ("%qs combined with %<auto%> qualifier for %qs", addrspace_name, name);
+		  break;
+		case csc_register:
+		  error ("%qs combined with %<register%> qualifier for %qs", addrspace_name, name);
+		  break;
+		case csc_static:
+		  error ("%qs combined with %<static%> qualifier for %qs", addrspace_name, name);
+		  break;
+		case csc_none:
+		  if (current_function_scope)
+		    error ("%qs specified for auto variable %qs", addrspace_name, name);
+		  else
+		    error ("%qs variable %qs must be extern", addrspace_name, name);
+		  break;
+		case csc_extern:
+		  /* fall through */
+		case csc_typedef:
+		  break;
+		}
+	    }
+	}
+      else if (decl_context == PARM && declarator->kind == cdk_id)
+	error ("%qs specified for parameter %qs", addrspace_name, name);
+      else if (decl_context == FIELD)
+	error ("%qs specified for structure field %qs", addrspace_name, name);
+    }
   else if (decl_context != NORMAL && (storage_class != csc_none || threadp))
     {
       if (decl_context == PARM && storage_class == csc_register)
@@ -4846,6 +4905,10 @@ grokdeclarator (const struct c_declarato
 
 	type = c_build_qualified_type (type, type_quals);
 
+	if (POINTER_TYPE_P (type) && TYPE_ADDR_SPACE (type) && !extern_ref)
+	  error ("%qs variable %qs must be extern", 
+		 targetm.addr_space_name (TYPE_ADDR_SPACE (type)), name);
+
 	/* C99 6.2.2p7: It is invalid (compile-time undefined
 	   behavior) to create an 'extern' declaration for a
 	   variable if there is a global declaration that is
@@ -7085,9 +7148,23 @@ build_null_declspecs (void)
   ret->volatile_p = false;
   ret->restrict_p = false;
   ret->saturating_p = false;
+  ret->address_space = 0;
   return ret;
 }
 
+struct c_declspecs *
+declspecs_add_addrspace (struct c_declspecs *specs, tree addrspace)
+{
+  specs->non_sc_seen_p = true;
+  specs->declspecs_seen_p = true;
+
+  if (specs->address_space > 0)
+    pedwarn (OPT_pedantic, "duplicate %qs", targetm.addr_space_name (specs->address_space));
+
+  specs->address_space = targetm.addr_space_number (addrspace);
+  return specs;
+}
+
 /* Add the type qualifier QUAL to the declaration specifiers SPECS,
    returning SPECS.  */
 
--- gcc-clean/gcc/c-objc-common.c	2008-04-03 15:14:25.000000000 +1100
+++ gcc-nas/gcc/c-objc-common.c	2008-06-16 16:22:24.000000000 +1000
@@ -187,6 +187,9 @@ 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));
 }
 
--- gcc-clean/gcc/c-parser.c	2008-08-18 22:11:04.000000000 +1000
+++ gcc-nas/gcc/c-parser.c	2008-08-20 11:50:29.000000000 +1000
@@ -130,6 +130,8 @@ typedef enum c_id_kind {
   C_ID_TYPENAME,
   /* An identifier declared as an Objective-C class name.  */
   C_ID_CLASSNAME,
+  /* An address space identifier.  */
+  C_ID_ADDRSPACE,
   /* Not an identifier.  */
   C_ID_NONE
 } c_id_kind;
@@ -256,6 +258,11 @@ c_lex_one_token (c_parser *parser, c_tok
 		break;
 	      }
 	  }
+	else if (targetm.valid_addr_space (token->value))
+	  {
+	    token->id_kind = C_ID_ADDRSPACE;
+	    break;
+	  }
 	else if (c_dialect_objc ())
 	  {
 	    tree objc_interface_decl = objc_is_class_name (token->value);
@@ -352,6 +359,8 @@ c_token_starts_typename (c_token *token)
 	{
 	case C_ID_ID:
 	  return false;
+	case C_ID_ADDRSPACE:
+	  return true;
 	case C_ID_TYPENAME:
 	  return true;
 	case C_ID_CLASSNAME:
@@ -422,6 +431,8 @@ c_token_starts_declspecs (c_token *token
 	{
 	case C_ID_ID:
 	  return false;
+	case C_ID_ADDRSPACE:
+	  return true;
 	case C_ID_TYPENAME:
 	  return true;
 	case C_ID_CLASSNAME:
@@ -1393,6 +1404,7 @@ c_parser_asm_definition (c_parser *parse
      const
      restrict
      volatile
+     address-space-qualifier
 
    (restrict is new in C99.)
 
@@ -1401,6 +1413,12 @@ c_parser_asm_definition (c_parser *parse
    declaration-specifiers:
      attributes declaration-specifiers[opt]
 
+   type-qualifier:
+     address-space
+
+   address-space:
+     identifier recognized by the target
+
    storage-class-specifier:
      __thread
 
@@ -1440,6 +1458,16 @@ c_parser_declspecs (c_parser *parser, st
 	{
 	  tree value = c_parser_peek_token (parser)->value;
 	  c_id_kind kind = c_parser_peek_token (parser)->id_kind;
+
+	  if (kind == C_ID_ADDRSPACE && !c_dialect_objc ())
+	    {
+	      declspecs_add_addrspace (specs, c_parser_peek_token (parser)->value);
+	      c_parser_consume_token (parser);
+	      attrs_ok = true;
+	      seen_type = true;
+	      continue;
+	    }
+
 	  /* This finishes the specifiers unless a type name is OK, it
 	     is declared as a type name and a type name hasn't yet
 	     been seen.  */
@@ -5506,6 +5534,12 @@ c_parser_postfix_expression_after_paren_
   finish_init ();
   maybe_warn_string_init (type, init);
 
+  if (type != error_mark_node && TYPE_ADDR_SPACE (type) && current_function_decl)
+    {
+      error ("compound literal qualified by address-space qualifier");
+      type = error_mark_node;
+    }
+
   if (!flag_isoc99)
     pedwarn (OPT_pedantic, "%HISO C90 forbids compound literals", 
 	     &start_loc);
--- gcc-clean/gcc/c-pretty-print.c	2008-07-29 09:09:02.000000000 +1000
+++ gcc-nas/gcc/c-pretty-print.c	2008-07-29 16:14:41.000000000 +1000
@@ -29,6 +29,8 @@ along with GCC; see the file COPYING3.  
 #include "c-tree.h"
 #include "tree-iterator.h"
 #include "diagnostic.h"
+#include "target.h"
+#include "target-def.h"
 
 /* The pretty-printer code is primarily designed to closely follow
    (GNU) C and C++ grammars.  That is to be contrasted with spaghetti
@@ -220,7 +222,11 @@ pp_c_space_for_pointer_operator (c_prett
        const
        restrict                              -- C99
        __restrict__                          -- GNU C
-       volatile    */
+       address-space-qualifier		     -- GNU C
+       volatile
+
+   address-space-qualifier:
+       identifier			     -- GNU C  */
 
 void
 pp_c_type_qualifier_list (c_pretty_printer *pp, tree t)
@@ -240,6 +246,12 @@ pp_c_type_qualifier_list (c_pretty_print
     pp_c_cv_qualifier (pp, "volatile");
   if (qualifiers & TYPE_QUAL_RESTRICT)
     pp_c_cv_qualifier (pp, flag_isoc99 ? "restrict" : "__restrict__");
+
+  if (TYPE_ADDR_SPACE (t))
+    {
+      const char *as = targetm.addr_space_name (TYPE_ADDR_SPACE (t));
+      pp_c_identifier (pp, as);
+    }
 }
 
 /* pointer:
--- gcc-clean/gcc/c-tree.h	2008-08-14 13:27:13.000000000 +1000
+++ gcc-nas/gcc/c-tree.h	2008-08-20 11:50:29.000000000 +1000
@@ -286,6 +286,8 @@ struct c_declspecs {
   BOOL_BITFIELD restrict_p : 1;
   /* Whether "_Sat" was specified.  */
   BOOL_BITFIELD saturating_p : 1;
+  /* Whether the declaration is in another address space.  */
+  unsigned char address_space;
 };
 
 /* The various kinds of declarators in C.  */
@@ -515,6 +517,7 @@ extern struct c_declspecs *declspecs_add
 					       struct c_typespec);
 extern struct c_declspecs *declspecs_add_scspec (struct c_declspecs *, tree);
 extern struct c_declspecs *declspecs_add_attrs (struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_addrspace (struct c_declspecs *, tree);
 extern struct c_declspecs *finish_declspecs (struct c_declspecs *);
 
 /* in c-objc-common.c */
--- gcc-clean/gcc/c-typeck.c	2008-08-11 09:37:45.000000000 +1000
+++ gcc-nas/gcc/c-typeck.c	2008-08-19 20:18:46.000000000 +1000
@@ -8180,6 +8180,16 @@ build_binary_op (enum tree_code code, tr
 		  && TREE_CODE (tt1) == FUNCTION_TYPE)
 		pedwarn (OPT_pedantic, "ISO C forbids "
 			 "comparison of %<void *%> with function pointer");
+
+	      /* If this operand is a pointer into another address
+		 space, make the result of the comparison such a
+		 pointer also.  */
+	      if (OTHER_ADDR_SPACE_POINTER_TYPE_P (type0))
+		{
+		  int qual = ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (TREE_TYPE (type0)));
+		  result_type = build_pointer_type
+		    (build_qualified_type (void_type_node, qual));
+		}
 	    }
 	  else if (VOID_TYPE_P (tt1))
 	    {
@@ -8187,6 +8197,16 @@ build_binary_op (enum tree_code code, tr
 		  && TREE_CODE (tt0) == FUNCTION_TYPE)
 		pedwarn (OPT_pedantic, "ISO C forbids "
 			 "comparison of %<void *%> with function pointer");
+
+	      /* If this operand is a pointer into another address
+		 space, make the result of the comparison such a
+		 pointer also.  */
+	      if (OTHER_ADDR_SPACE_POINTER_TYPE_P (type1))
+		{
+		  int qual = ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (TREE_TYPE (type1)));
+		  result_type = build_pointer_type
+		    (build_qualified_type (void_type_node, qual));
+		}
 	    }
 	  else
 	    /* Avoid warning about the volatile ObjC EH puts on decls.  */
--- gcc-clean/gcc/convert.c	2008-05-11 14:37:53.000000000 +1000
+++ gcc-nas/gcc/convert.c	2008-06-16 16:22:24.000000000 +1000
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  
 #include "langhooks.h"
 #include "real.h"
 #include "fixed-value.h"
+#include "target.h"
 
 /* Convert EXPR to some pointer or reference type TYPE.
    EXPR must be pointer, reference, integer, enumeral, or literal zero;
@@ -58,11 +59,16 @@ convert_to_pointer (tree type, tree expr
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
-      if (TYPE_PRECISION (TREE_TYPE (expr)) != POINTER_SIZE)
-	expr = fold_build1 (NOP_EXPR,
-                            lang_hooks.types.type_for_size (POINTER_SIZE, 0),
-			    expr);
-      return fold_build1 (CONVERT_EXPR, type, expr);
+    {
+      int pointer_size =
+	TYPE_ADDR_SPACE (TREE_TYPE (type))
+	? GET_MODE_BITSIZE (targetm.addr_space_pointer_mode (TYPE_ADDR_SPACE (TREE_TYPE (type))))
+	: POINTER_SIZE;
+
+      if (TYPE_PRECISION (TREE_TYPE (expr)) != pointer_size)
+	expr = fold_build1 (NOP_EXPR, lang_hooks.types.type_for_size (pointer_size, 0), expr);
+    }
+    return fold_build1 (CONVERT_EXPR, type, expr);
 
 
     default:
@@ -448,15 +454,24 @@ convert_to_integer (tree type, tree expr
     {
     case POINTER_TYPE:
     case REFERENCE_TYPE:
-      if (integer_zerop (expr))
-	return build_int_cst (type, 0);
+      {
+ 	int pointer_size;
+
+ 	if (integer_zerop (expr))
+ 	  return build_int_cst (type, 0);
 
-      /* Convert to an unsigned integer of the correct width first,
-	 and from there widen/truncate to the required type.  */
-      expr = fold_build1 (CONVERT_EXPR,
-			  lang_hooks.types.type_for_size (POINTER_SIZE, 0),
-			  expr);
-      return fold_convert (type, expr);
+ 	/* Convert to an unsigned integer of the correct width first,
+ 	   and from there widen/truncate to the required type.  */
+ 	pointer_size =
+ 	  TYPE_ADDR_SPACE (TREE_TYPE (intype))
+	  ? GET_MODE_BITSIZE (targetm.addr_space_pointer_mode (TYPE_ADDR_SPACE (TREE_TYPE (intype))))
+ 	  : POINTER_SIZE;
+
+ 	expr = fold_build1 (CONVERT_EXPR,
+ 			    lang_hooks.types.type_for_size (pointer_size, 0),
+ 			    expr);
+ 	return fold_build1 (NOP_EXPR, type, expr);
+      }
 
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
--- gcc-clean/gcc/dwarf2out.c	2008-08-14 13:27:13.000000000 +1000
+++ gcc-nas/gcc/dwarf2out.c	2008-08-19 20:16:13.000000000 +1000
@@ -9505,6 +9505,9 @@ modified_type_die (tree type, int is_con
       add_AT_unsigned (mod_type_die, DW_AT_byte_size,
 		       simple_type_size_in_bits (type) / BITS_PER_UNIT);
       item_type = TREE_TYPE (type);
+      if (TYPE_ADDR_SPACE (item_type))
+	add_AT_unsigned (mod_type_die, DW_AT_address_class,
+			 TYPE_ADDR_SPACE (item_type));
     }
   else if (code == REFERENCE_TYPE)
     {
@@ -9512,6 +9515,9 @@ modified_type_die (tree type, int is_con
       add_AT_unsigned (mod_type_die, DW_AT_byte_size,
 		       simple_type_size_in_bits (type) / BITS_PER_UNIT);
       item_type = TREE_TYPE (type);
+      if (TYPE_ADDR_SPACE (item_type))
+	add_AT_unsigned (mod_type_die, DW_AT_address_class,
+			 TYPE_ADDR_SPACE (item_type));
     }
   else if (is_subrange_type (type))
     {
--- gcc-clean/gcc/emit-rtl.c	2008-07-31 13:23:06.000000000 +1000
+++ gcc-nas/gcc/emit-rtl.c	2008-07-31 13:41:57.000000000 +1000
@@ -193,7 +193,7 @@ static rtx lookup_const_fixed (rtx);
 static hashval_t mem_attrs_htab_hash (const void *);
 static int mem_attrs_htab_eq (const void *, const void *);
 static mem_attrs *get_mem_attrs (alias_set_type, tree, rtx, rtx, unsigned int,
-				 enum machine_mode);
+				 unsigned char, enum machine_mode);
 static hashval_t reg_attrs_htab_hash (const void *);
 static int reg_attrs_htab_eq (const void *, const void *);
 static reg_attrs *get_reg_attrs (tree, int);
@@ -321,7 +321,7 @@ mem_attrs_htab_eq (const void *x, const 
 
 static mem_attrs *
 get_mem_attrs (alias_set_type alias, tree expr, rtx offset, rtx size,
-	       unsigned int align, enum machine_mode mode)
+	       unsigned int align, unsigned char addrspace, enum machine_mode mode)
 {
   mem_attrs attrs;
   void **slot;
@@ -341,6 +341,7 @@ get_mem_attrs (alias_set_type alias, tre
   attrs.offset = offset;
   attrs.size = size;
   attrs.align = align;
+  attrs.addrspace = addrspace;
 
   slot = htab_find_slot (mem_attrs_htab, &attrs, INSERT);
   if (*slot == 0)
@@ -1748,7 +1749,7 @@ set_mem_attributes_minus_bitpos (rtx ref
 
   /* Now set the attributes we computed above.  */
   MEM_ATTRS (ref)
-    = get_mem_attrs (alias, expr, offset, size, align, GET_MODE (ref));
+    = get_mem_attrs (alias, expr, offset, size, align, TYPE_ADDR_SPACE (type), GET_MODE (ref));
 
   /* If this is already known to be a scalar or aggregate, we are done.  */
   if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref))
@@ -1776,7 +1777,7 @@ set_mem_attrs_from_reg (rtx mem, rtx reg
   MEM_ATTRS (mem)
     = get_mem_attrs (MEM_ALIAS_SET (mem), REG_EXPR (reg),
 		     GEN_INT (REG_OFFSET (reg)),
-		     MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem));
+		     MEM_SIZE (mem), MEM_ALIGN (mem), MEM_ADDR_SPACE (mem), GET_MODE (mem));
 }
 
 /* Set the alias set of MEM to SET.  */
@@ -1790,17 +1791,27 @@ set_mem_alias_set (rtx mem, alias_set_ty
 #endif
 
   MEM_ATTRS (mem) = get_mem_attrs (set, MEM_EXPR (mem), MEM_OFFSET (mem),
-				   MEM_SIZE (mem), MEM_ALIGN (mem),
+				   MEM_SIZE (mem), MEM_ALIGN (mem), MEM_ADDR_SPACE (mem),
 				   GET_MODE (mem));
 }
 
+/* Set the address space of MEM to ADDRSPACE (target-defined).  */
+
+void
+set_mem_addr_space (rtx mem, unsigned char addrspace)
+{
+  MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
+				   MEM_OFFSET (mem), MEM_SIZE (mem), MEM_ALIGN (mem),
+				   addrspace, GET_MODE (mem));
+}
+
 /* Set the alignment of MEM to ALIGN bits.  */
 
 void
 set_mem_align (rtx mem, unsigned int align)
 {
   MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
-				   MEM_OFFSET (mem), MEM_SIZE (mem), align,
+				   MEM_OFFSET (mem), MEM_SIZE (mem), align, MEM_ADDR_SPACE (mem),
 				   GET_MODE (mem));
 }
 
@@ -1811,7 +1822,7 @@ set_mem_expr (rtx mem, tree expr)
 {
   MEM_ATTRS (mem)
     = get_mem_attrs (MEM_ALIAS_SET (mem), expr, MEM_OFFSET (mem),
-		     MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem));
+		     MEM_SIZE (mem), MEM_ALIGN (mem), MEM_ADDR_SPACE (mem), GET_MODE (mem));
 }
 
 /* Set the offset of MEM to OFFSET.  */
@@ -1820,7 +1831,7 @@ void
 set_mem_offset (rtx mem, rtx offset)
 {
   MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
-				   offset, MEM_SIZE (mem), MEM_ALIGN (mem),
+				   offset, MEM_SIZE (mem), MEM_ALIGN (mem), MEM_ADDR_SPACE (mem),
 				   GET_MODE (mem));
 }
 
@@ -1830,7 +1841,7 @@ void
 set_mem_size (rtx mem, rtx size)
 {
   MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
-				   MEM_OFFSET (mem), size, MEM_ALIGN (mem),
+				   MEM_OFFSET (mem), size, MEM_ALIGN (mem), MEM_ADDR_SPACE (mem),
 				   GET_MODE (mem));
 }
 \f
@@ -1898,7 +1909,7 @@ change_address (rtx memref, enum machine
     }
 
   MEM_ATTRS (new_rtx)
-    = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, mmode);
+    = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, MEM_ADDR_SPACE (memref), mmode);
 
   return new_rtx;
 }
@@ -1965,7 +1976,8 @@ adjust_address_1 (rtx memref, enum machi
     size = plus_constant (MEM_SIZE (memref), -offset);
 
   MEM_ATTRS (new_rtx) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref),
-				   memoffset, size, memalign, GET_MODE (new_rtx));
+				   memoffset, size, memalign, MEM_ADDR_SPACE (memref),
+				   GET_MODE (new_rtx));
 
   /* At some point, we should validate that this offset is within the object,
      if all the appropriate values are known.  */
@@ -2023,7 +2035,7 @@ offset_address (rtx memref, rtx offset, 
   MEM_ATTRS (new_rtx)
     = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 0, 0,
 		     MIN (MEM_ALIGN (memref), pow2 * BITS_PER_UNIT),
-		     GET_MODE (new_rtx));
+		     MEM_ADDR_SPACE (memref), GET_MODE (new_rtx));
   return new_rtx;
 }
 
@@ -2127,7 +2139,7 @@ widen_memory_access (rtx memref, enum ma
   /* ??? Maybe use get_alias_set on any remaining expression.  */
 
   MEM_ATTRS (new_rtx) = get_mem_attrs (0, expr, memoffset, GEN_INT (size),
-				   MEM_ALIGN (new_rtx), mode);
+				   MEM_ALIGN (new_rtx), MEM_ADDR_SPACE (new_rtx), mode);
 
   return new_rtx;
 }
--- gcc-clean/gcc/emit-rtl.h	2008-04-03 15:14:25.000000000 +1100
+++ gcc-nas/gcc/emit-rtl.h	2008-07-15 15:46:04.000000000 +1000
@@ -26,6 +26,9 @@ extern void set_mem_alias_set (rtx, alia
 /* Set the alignment of MEM to ALIGN bits.  */
 extern void set_mem_align (rtx, unsigned int);
 
+/* Set the address space of MEM to ADDRSPACE.  */
+extern void set_mem_addr_space (rtx, unsigned char);
+
 /* Set the expr for MEM to EXPR.  */
 extern void set_mem_expr (rtx, tree);
 
--- gcc-clean/gcc/explow.c	2008-08-17 09:48:19.000000000 +1000
+++ gcc-nas/gcc/explow.c	2008-08-19 20:18:53.000000000 +1000
@@ -414,7 +414,8 @@ memory_address (enum machine_mode mode, 
 {
   rtx oldx = x;
 
-  x = convert_memory_address (Pmode, x);
+  if (MEM_P (x) && !targetm.valid_pointer_mode (GET_MODE (x)))
+    x = convert_memory_address (Pmode, x);
 
   /* By passing constant addresses through registers
      we get a chance to cse them.  */
@@ -484,6 +485,8 @@ memory_address (enum machine_mode mode, 
 
       /* Last resort: copy the value to a register, since
 	 the register is a valid address.  */
+      else if (targetm.valid_pointer_mode (GET_MODE (x)))
+	x = force_reg (GET_MODE (x), x);
       else
 	x = force_reg (Pmode, x);
     }
--- gcc-clean/gcc/expr.c	2008-08-19 06:55:43.000000000 +1000
+++ gcc-nas/gcc/expr.c	2008-08-19 20:16:16.000000000 +1000
@@ -6894,17 +6894,22 @@ expand_expr_addr_expr (tree exp, rtx tar
 		       enum expand_modifier modifier)
 {
   enum machine_mode rmode;
+  enum machine_mode addrmode;
   rtx result;
 
   /* Target mode of VOIDmode says "whatever's natural".  */
   if (tmode == VOIDmode)
     tmode = TYPE_MODE (TREE_TYPE (exp));
 
+  addrmode = Pmode;
+  if (OTHER_ADDR_SPACE_POINTER_TYPE_P (TREE_TYPE (exp)))
+    addrmode = targetm.addr_space_pointer_mode (TYPE_ADDR_SPACE (TREE_TYPE (exp)));
+
   /* We can get called with some Weird Things if the user does silliness
      like "(short) &a".  In that case, convert_memory_address won't do
      the right thing, so ignore the given target mode.  */
-  if (tmode != Pmode && tmode != ptr_mode)
-    tmode = Pmode;
+  if (tmode != addrmode && tmode != ptr_mode)
+    tmode = addrmode;
 
   result = expand_expr_addr_expr_1 (TREE_OPERAND (exp, 0), target,
 				    tmode, modifier);
@@ -7142,6 +7147,8 @@ expand_expr_real_1 (tree exp, rtx target
   int ignore;
   tree context, subexp0, subexp1;
   bool reduce_bit_field;
+  rtx (*genfn) (rtx, rtx);
+
 #define REDUCE_BIT_FIELD(expr)	(reduce_bit_field			  \
 				 ? reduce_to_bit_field_precision ((expr), \
 								  target, \
@@ -8105,6 +8112,27 @@ expand_expr_real_1 (tree exp, rtx target
 	  return target;
 	}
 
+      /* Handle casts of pointers to/from address space qualified
+	 pointers.  */
+      if (OTHER_ADDR_SPACE_POINTER_TYPE_P (type)
+	  && GENERIC_ADDR_SPACE_POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
+	{
+	  rtx reg = gen_reg_rtx (TYPE_MODE (type));
+	  op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, modifier);
+	  genfn = targetm.addr_space_conversion_rtl (0, 1);
+	  emit_insn (genfn (reg, op0));
+	  return reg;
+	}
+      else if (GENERIC_ADDR_SPACE_POINTER_TYPE_P (type)
+	       && (OTHER_ADDR_SPACE_POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0)))))
+	{
+	  rtx reg = gen_reg_rtx (Pmode);
+	  op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, modifier);
+	  genfn = targetm.addr_space_conversion_rtl (1, 0);
+	  emit_insn (genfn (reg, op0));
+	  return reg;
+	}
+
       if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
 	{
 	  op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode,
--- gcc-clean/gcc/fold-const.c	2008-08-19 06:55:43.000000000 +1000
+++ gcc-nas/gcc/fold-const.c	2008-08-19 20:14:19.000000000 +1000
@@ -65,6 +65,7 @@ along with GCC; see the file COPYING3.  
 #include "hashtab.h"
 #include "langhooks.h"
 #include "md5.h"
+#include "target.h"
 #include "gimple.h"
 
 /* Nonzero if we are folding constants inside an initializer; zero
@@ -203,8 +204,10 @@ fit_double_type (unsigned HOST_WIDE_INT 
   unsigned int prec;
   int sign_extended_type;
 
-  if (POINTER_TYPE_P (type)
-      || TREE_CODE (type) == OFFSET_TYPE)
+  if (OTHER_ADDR_SPACE_POINTER_TYPE_P (type))
+    prec = GET_MODE_BITSIZE (targetm.addr_space_pointer_mode (TYPE_ADDR_SPACE (type)));
+  else if (POINTER_TYPE_P (type)
+	   || TREE_CODE (type) == OFFSET_TYPE)
     prec = POINTER_SIZE;
   else
     prec = TYPE_PRECISION (type);
@@ -2396,7 +2399,9 @@ fold_convert_const (enum tree_code code,
   if (TREE_TYPE (arg1) == type)
     return arg1;
 
-  if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type)
+  if (OTHER_ADDR_SPACE_POINTER_TYPE_P (type))
+    return NULL_TREE;
+  else if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type)
       || TREE_CODE (type) == OFFSET_TYPE)
     {
       if (TREE_CODE (arg1) == INTEGER_CST)
--- gcc-clean/gcc/output.h	2008-04-28 12:07:15.000000000 +1000
+++ gcc-nas/gcc/output.h	2008-06-16 16:22:24.000000000 +1000
@@ -616,6 +616,7 @@ extern void default_internal_label (FILE
 extern void default_file_start (void);
 extern void file_end_indicate_exec_stack (void);
 extern bool default_valid_pointer_mode (enum machine_mode);
+extern enum machine_mode default_addr_space_pointer_mode (int);
 
 extern void default_elf_asm_output_external (FILE *file, tree,
 					     const char *);
--- gcc-clean/gcc/print-rtl.c	2008-04-17 10:45:38.000000000 +1000
+++ gcc-nas/gcc/print-rtl.c	2008-08-11 11:51:39.000000000 +1000
@@ -556,6 +556,9 @@ print_rtx (const_rtx in_rtx)
       if (MEM_ALIGN (in_rtx) != 1)
 	fprintf (outfile, " A%u", MEM_ALIGN (in_rtx));
 
+      if (MEM_ADDR_SPACE (in_rtx))
+	fprintf (outfile, " AS%u", MEM_ADDR_SPACE (in_rtx));
+
       fputc (']', outfile);
       break;
 
--- gcc-clean/gcc/rtl.h	2008-07-31 13:23:06.000000000 +1000
+++ gcc-nas/gcc/rtl.h	2008-08-20 10:32:01.000000000 +1000
@@ -146,6 +146,7 @@ typedef struct mem_attrs GTY(())
   rtx offset;			/* Offset from start of DECL, as CONST_INT.  */
   rtx size;			/* Size in bytes, as a CONST_INT.  */
   unsigned int align;		/* Alignment of MEM in bits.  */
+  unsigned char addrspace;	/* Address space (0 for generic).  */
 } mem_attrs;
 
 /* Structure used to describe the attributes of a REG in similar way as
@@ -1207,6 +1208,10 @@ do {						\
    RTX that is always a CONST_INT.  */
 #define MEM_OFFSET(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->offset)
 
+/* For a MEM rtx, the address space.  If 0, the MEM belongs to the
+   generic address space.  */
+#define MEM_ADDR_SPACE(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->addrspace)
+
 /* For a MEM rtx, the size in bytes of the MEM, if known, as an RTX that
    is always a CONST_INT.  */
 #define MEM_SIZE(RTX)							\
--- gcc-clean/gcc/target-def.h	2008-07-31 13:23:06.000000000 +1000
+++ gcc-nas/gcc/target-def.h	2008-07-31 13:42:01.000000000 +1000
@@ -437,6 +437,26 @@
 #define TARGET_VALID_POINTER_MODE default_valid_pointer_mode
 #endif
 
+#ifndef TARGET_ADDR_SPACE_POINTER_MODE
+#define TARGET_ADDR_SPACE_POINTER_MODE default_addr_space_pointer_mode
+#endif
+
+#ifndef TARGET_ADDR_SPACE_NAME
+#define TARGET_ADDR_SPACE_NAME default_addr_space_name
+#endif
+
+#ifndef TARGET_ADDR_SPACE_NUMBER
+#define TARGET_ADDR_SPACE_NUMBER default_addr_space_number
+#endif
+
+#ifndef TARGET_ADDR_SPACE_CONVERSION_RTL
+#define TARGET_ADDR_SPACE_CONVERSION_RTL default_addr_space_conversion_rtl
+#endif
+
+#ifndef TARGET_VALID_ADDR_SPACE
+#define TARGET_VALID_ADDR_SPACE hook_bool_const_tree_false
+#endif
+
 #ifndef TARGET_SCALAR_MODE_SUPPORTED_P
 #define TARGET_SCALAR_MODE_SUPPORTED_P default_scalar_mode_supported_p
 #endif
@@ -862,6 +882,11 @@
   TARGET_MIN_DIVISIONS_FOR_RECIP_MUL,		\
   TARGET_MODE_REP_EXTENDED,			\
   TARGET_VALID_POINTER_MODE,                    \
+  TARGET_ADDR_SPACE_POINTER_MODE,		\
+  TARGET_ADDR_SPACE_NAME,			\
+  TARGET_ADDR_SPACE_NUMBER,			\
+  TARGET_ADDR_SPACE_CONVERSION_RTL,		\
+  TARGET_VALID_ADDR_SPACE,			\
   TARGET_SCALAR_MODE_SUPPORTED_P,		\
   TARGET_VECTOR_MODE_SUPPORTED_P,               \
   TARGET_VECTOR_OPAQUE_P,			\
--- gcc-clean/gcc/target.h	2008-07-31 13:23:05.000000000 +1000
+++ gcc-nas/gcc/target.h	2008-07-31 13:40:36.000000000 +1000
@@ -627,6 +627,21 @@ struct gcc_target
   /* True if MODE is valid for a pointer in __attribute__((mode("MODE"))).  */
   bool (* valid_pointer_mode) (enum machine_mode mode);
 
+  /* MODE to use for a pointer into another address space.  */
+  enum machine_mode (* addr_space_pointer_mode) (int);
+
+  /* Function to map an address space to a descriptive string.  */
+  const char * (* addr_space_name) (int);
+
+  /* Function to map an address space to a descriptive string.  */
+  unsigned char (* addr_space_number) (const tree);
+
+  /* Function to return a gen function for the pointer conversion.  */
+  rtx (* (* addr_space_conversion_rtl) (int, int)) (rtx, rtx);
+
+  /* True if an identifier that is a valid address space.  */
+  bool (* valid_addr_space) (const_tree);
+
   /* True if MODE is valid for the target.  By "valid", we mean able to
      be manipulated in non-trivial ways.  In particular, this means all
      the arithmetic is supported.  */
--- gcc-clean/gcc/targhooks.h	2008-07-24 13:24:12.000000000 +1000
+++ gcc-nas/gcc/targhooks.h	2008-07-24 13:49:34.000000000 +1000
@@ -100,3 +100,6 @@ extern tree default_emutls_var_init (tre
 extern bool default_hard_regno_scratch_ok (unsigned int);
 extern bool default_target_option_valid_attribute_p (tree, tree, tree, int);
 extern bool default_target_option_can_inline_p (tree, tree);
+extern const char *default_addr_space_name (int);
+extern unsigned char default_addr_space_number (const tree);
+extern rtx (*default_addr_space_conversion_rtl (int, int)) (rtx, rtx);
--- gcc-clean/gcc/targhooks.c	2008-07-24 13:24:12.000000000 +1000
+++ gcc-nas/gcc/targhooks.c	2008-07-24 13:43:29.000000000 +1000
@@ -703,6 +703,22 @@ default_builtin_vector_alignment_reachab
   return true;
 }
 
+const char *
+default_addr_space_name (int addrspace ATTRIBUTE_UNUSED)
+{
+  gcc_unreachable ();
+}
+
+rtx (* default_addr_space_conversion_rtl (int from ATTRIBUTE_UNUSED, int to ATTRIBUTE_UNUSED)) (rtx, rtx)
+{
+  gcc_unreachable ();
+}
+
+unsigned char default_addr_space_number (const tree ident ATTRIBUTE_UNUSED)
+{
+  gcc_unreachable ();
+}
+
 bool
 default_hard_regno_scratch_ok (unsigned int regno ATTRIBUTE_UNUSED)
 {
--- gcc-clean/gcc/tree-pretty-print.c	2008-08-07 14:06:16.000000000 +1000
+++ gcc-nas/gcc/tree-pretty-print.c	2008-08-19 20:23:57.000000000 +1000
@@ -36,6 +36,8 @@ along with GCC; see the file COPYING3.  
 #include "fixed-value.h"
 #include "value-prof.h"
 #include "predict.h"
+#include "target.h"
+#include "target-def.h"
 
 /* Local functions, macros and variables.  */
 static int op_prio (const_tree);
@@ -528,6 +530,13 @@ dump_generic_node (pretty_printer *buffe
 	else if (quals & TYPE_QUAL_RESTRICT)
 	  pp_string (buffer, "restrict ");
 
+	if (TYPE_ADDR_SPACE (node))
+	  {
+	    const char *as = targetm.addr_space_name (TYPE_ADDR_SPACE (node));
+	    pp_string (buffer, as);
+	    pp_space (buffer);
+	  }
+
 	tclass = TREE_CODE_CLASS (TREE_CODE (node));
 
 	if (tclass == tcc_declaration)
@@ -604,6 +613,13 @@ dump_generic_node (pretty_printer *buffe
 	  if (quals & TYPE_QUAL_RESTRICT)
 	    pp_string (buffer, " restrict");
 
+	  if (TYPE_ADDR_SPACE (node))
+	    {
+	      const char *as = targetm.addr_space_name (TYPE_ADDR_SPACE (node));
+	      pp_string (buffer, as);
+	      pp_space (buffer);
+	    }
+	  
 	  if (TYPE_REF_CAN_ALIAS_ALL (node))
 	    pp_string (buffer, " {ref-all}");
 	}
--- gcc-clean/gcc/tree-ssa-loop-ivopts.c	2008-08-05 08:57:25.000000000 +1000
+++ gcc-nas/gcc/tree-ssa-loop-ivopts.c	2008-08-05 23:36:33.000000000 +1000
@@ -2011,9 +2011,16 @@ strip_offset (tree expr, unsigned HOST_W
 static tree
 generic_type_for (tree type)
 {
-  if (POINTER_TYPE_P (type))
+  if (GENERIC_ADDR_SPACE_POINTER_TYPE_P (type))
     return unsigned_type_for (type);
 
+  if (OTHER_ADDR_SPACE_POINTER_TYPE_P (type))
+    {
+      int qual = ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (TREE_TYPE (type)));
+      return build_pointer_type
+	(build_qualified_type (void_type_node, qual));
+    }
+
   if (TYPE_UNSIGNED (type))
     return type;
 
--- gcc-clean/gcc/tree-ssa.c	2008-08-11 09:37:45.000000000 +1000
+++ gcc-nas/gcc/tree-ssa.c	2008-08-19 20:19:06.000000000 +1000
@@ -1118,6 +1118,12 @@ useless_type_conversion_p_1 (tree outer_
 	  && TYPE_VOLATILE (TREE_TYPE (outer_type)))
 	return false;
 
+      /* Do not lose casts between pointers in different address
+	 spaces.  */
+      if (TYPE_ADDR_SPACE (TREE_TYPE (inner_type))
+	  != TYPE_ADDR_SPACE (TREE_TYPE (outer_type)))
+	return false;
+
       /* Do not lose casts between pointers with different
 	 TYPE_REF_CAN_ALIAS_ALL setting or alias sets.  */
       if ((TYPE_REF_CAN_ALIAS_ALL (inner_type)
@@ -1211,7 +1217,9 @@ useless_type_conversion_p (tree outer_ty
      recursing though.  */
   if (POINTER_TYPE_P (inner_type)
       && POINTER_TYPE_P (outer_type)
-      && TREE_CODE (TREE_TYPE (outer_type)) == VOID_TYPE)
+      && TREE_CODE (TREE_TYPE (outer_type)) == VOID_TYPE
+      && GENERIC_ADDR_SPACE_POINTER_TYPE_P (inner_type)
+      && GENERIC_ADDR_SPACE_POINTER_TYPE_P (outer_type))
     return true;
 
   return useless_type_conversion_p_1 (outer_type, inner_type);
--- gcc-clean/gcc/tree.c	2008-08-20 09:32:13.000000000 +1000
+++ gcc-nas/gcc/tree.c	2008-08-19 20:14:04.000000000 +1000
@@ -1476,8 +1476,13 @@ integer_pow2p (const_tree expr)
   if (TREE_CODE (expr) != INTEGER_CST)
     return 0;
 
-  prec = (POINTER_TYPE_P (TREE_TYPE (expr))
-	  ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
+  if (OTHER_ADDR_SPACE_POINTER_TYPE_P (TREE_TYPE (expr)))
+    prec = GET_MODE_BITSIZE (targetm.addr_space_pointer_mode (TYPE_ADDR_SPACE (TREE_TYPE (expr))));
+  else if (POINTER_TYPE_P (TREE_TYPE (expr)))
+    prec = POINTER_SIZE;
+  else
+    prec = TYPE_PRECISION (TREE_TYPE (expr));
+
   high = TREE_INT_CST_HIGH (expr);
   low = TREE_INT_CST_LOW (expr);
 
@@ -1541,8 +1546,12 @@ tree_log2 (const_tree expr)
   if (TREE_CODE (expr) == COMPLEX_CST)
     return tree_log2 (TREE_REALPART (expr));
 
-  prec = (POINTER_TYPE_P (TREE_TYPE (expr))
-	  ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
+  if (OTHER_ADDR_SPACE_POINTER_TYPE_P (TREE_TYPE (expr)))
+    prec = GET_MODE_BITSIZE (targetm.addr_space_pointer_mode (TYPE_ADDR_SPACE (TREE_TYPE (expr))));
+  else if (POINTER_TYPE_P (TREE_TYPE (expr)))
+    prec = POINTER_SIZE;
+  else
+    prec = TYPE_PRECISION (TREE_TYPE (expr));
 
   high = TREE_INT_CST_HIGH (expr);
   low = TREE_INT_CST_LOW (expr);
@@ -1579,8 +1588,12 @@ tree_floor_log2 (const_tree expr)
   if (TREE_CODE (expr) == COMPLEX_CST)
     return tree_log2 (TREE_REALPART (expr));
 
-  prec = (POINTER_TYPE_P (TREE_TYPE (expr))
-	  ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
+  if (OTHER_ADDR_SPACE_POINTER_TYPE_P (TREE_TYPE (expr)))
+    prec = GET_MODE_BITSIZE (targetm.addr_space_pointer_mode (TYPE_ADDR_SPACE (TREE_TYPE (expr))));
+  else if (POINTER_TYPE_P (TREE_TYPE (expr)))
+    prec = POINTER_SIZE;
+  else
+    prec = TYPE_PRECISION (TREE_TYPE (expr));
 
   high = TREE_INT_CST_HIGH (expr);
   low = TREE_INT_CST_LOW (expr);
@@ -4130,6 +4143,7 @@ set_type_quals (tree type, int type_qual
   TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
   TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
   TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+  TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
 }
 
 /* Returns true iff CAND is equivalent to BASE with TYPE_QUALS.  */
@@ -5462,7 +5476,8 @@ build_pointer_type_for_mode (tree to_typ
 tree
 build_pointer_type (tree to_type)
 {
-  return build_pointer_type_for_mode (to_type, ptr_mode, false);
+  enum machine_mode mode = targetm.addr_space_pointer_mode (TYPE_ADDR_SPACE (to_type));
+  return build_pointer_type_for_mode (to_type, mode, false);
 }
 
 /* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE.  */
@@ -8819,9 +8834,7 @@ block_nonartificial_location (tree block
     {
       tree ao = BLOCK_ABSTRACT_ORIGIN (block);
 
-      while (TREE_CODE (ao) == BLOCK
-	     && BLOCK_ABSTRACT_ORIGIN (ao)
-	     && BLOCK_ABSTRACT_ORIGIN (ao) != ao)
+      while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao))
 	ao = BLOCK_ABSTRACT_ORIGIN (ao);
 
       if (TREE_CODE (ao) == FUNCTION_DECL)
--- gcc-clean/gcc/tree.h	2008-08-19 06:55:43.000000000 +1000
+++ gcc-nas/gcc/tree.h	2008-08-20 10:45:59.000000000 +1000
@@ -1084,6 +1084,16 @@ extern void omp_clause_range_check_faile
 #define POINTER_TYPE_P(TYPE) \
   (TREE_CODE (TYPE) == POINTER_TYPE || TREE_CODE (TYPE) == REFERENCE_TYPE)
 
+/* Nonzero if TYPE is pointer or reference type qualified as belonging
+   to an address space that is not the generic address space.  */
+#define OTHER_ADDR_SPACE_POINTER_TYPE_P(TYPE) \
+  (POINTER_TYPE_P (TYPE) && TYPE_ADDR_SPACE (TREE_TYPE (TYPE)))
+
+/* Nonzero if TYPE is a pointer or reference type, but does not belong
+   to an address space outside the generic address space.  */
+#define GENERIC_ADDR_SPACE_POINTER_TYPE_P(TYPE) \
+  (POINTER_TYPE_P (TYPE) && !TYPE_ADDR_SPACE (TREE_TYPE (TYPE)))
+
 /* Nonzero if this type is a complete type.  */
 #define COMPLETE_TYPE_P(NODE) (TYPE_SIZE (NODE) != NULL_TREE)
 
@@ -2173,6 +2183,9 @@ struct tree_block GTY(())
    the term.  */
 #define TYPE_RESTRICT(NODE) (TYPE_CHECK (NODE)->type.restrict_flag)
 
+/* If nonzero, this type is in the extended address space.  */
+#define TYPE_ADDR_SPACE(NODE) (TYPE_CHECK (NODE)->type.address_space)
+
 /* There is a TYPE_QUAL value for each type qualifier.  They can be
    combined by bitwise-or to form the complete set of qualifiers for a
    type.  */
@@ -2182,11 +2195,15 @@ struct tree_block GTY(())
 #define TYPE_QUAL_VOLATILE 0x2
 #define TYPE_QUAL_RESTRICT 0x4
 
+#define ENCODE_QUAL_ADDR_SPACE(NUM) ((NUM & 0xFF) << 8)
+#define DECODE_QUAL_ADDR_SPACE(X) (((X) >> 8) && 0xFF)
+
 /* The set of type qualifiers for this type.  */
 #define TYPE_QUALS(NODE)					\
   ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST)			\
    | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE)		\
-   | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT))
+   | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)		\
+   | (ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (NODE))))
 
 /* 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)
@@ -2279,6 +2296,8 @@ struct tree_type GTY(())
   unsigned user_align : 1;
 
   unsigned int align;
+  unsigned char address_space;
+
   tree pointer_to;
   tree reference_to;
   union tree_type_symtab {
--- gcc-clean/gcc/varasm.c	2008-08-20 09:32:13.000000000 +1000
+++ gcc-nas/gcc/varasm.c	2008-08-06 21:21:55.000000000 +1000
@@ -1284,6 +1284,7 @@ make_decl_rtl (tree decl)
   const char *name = 0;
   int reg_number;
   rtx x;
+  enum machine_mode addrmode;
 
   /* Check that we are not being given an automatic variable.  */
   gcc_assert (TREE_CODE (decl) != PARM_DECL
@@ -1428,7 +1429,10 @@ make_decl_rtl (tree decl)
   if (use_object_blocks_p () && use_blocks_for_decl_p (decl))
     x = create_block_symbol (name, get_block_for_decl (decl), -1);
   else
-    x = gen_rtx_SYMBOL_REF (Pmode, name);
+    {
+      addrmode = (TREE_TYPE (decl) == error_mark_node) ? Pmode : targetm.addr_space_pointer_mode (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
+      x = gen_rtx_SYMBOL_REF (addrmode, name);
+    }
   SYMBOL_REF_WEAK (x) = DECL_WEAK (decl);
   SET_SYMBOL_REF_DECL (x, decl);
 
@@ -2286,10 +2290,6 @@ process_pending_assemble_externals (void
 #endif
 }
 
-/* This TREE_LIST contains any weak symbol declarations waiting
-   to be emitted.  */
-static GTY(()) tree weak_decls;
-
 /* Output something to declare an external symbol to the assembler.
    (Most assemblers don't need this, so we normally output nothing.)
    Do nothing if DECL is not external.  */
@@ -2307,9 +2307,6 @@ assemble_external (tree decl ATTRIBUTE_U
   if (!DECL_P (decl) || !DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
     return;
 
-  if (SUPPORTS_WEAK && DECL_WEAK (decl))
-    weak_decls = tree_cons (NULL, decl, weak_decls);
-
   /* We want to output external symbols at very last to check if they
      are references or not.  */
   pending_assemble_externals = tree_cons (0, decl,
@@ -4853,6 +4850,10 @@ output_constructor (tree exp, unsigned H
     assemble_zeros (size - total_bytes);
 }
 
+/* This TREE_LIST contains any weak symbol declarations waiting
+   to be emitted.  */
+static GTY(()) tree weak_decls;
+
 /* Mark DECL as weak.  */
 
 static void
@@ -4945,7 +4946,12 @@ declare_weak (tree decl)
     error ("weak declaration of %q+D must be public", decl);
   else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl))
     error ("weak declaration of %q+D must precede definition", decl);
-  else if (!SUPPORTS_WEAK)
+  else if (SUPPORTS_WEAK)
+    {
+      if (! DECL_WEAK (decl))
+	weak_decls = tree_cons (NULL, decl, weak_decls);
+    }
+  else
     warning (0, "weak declaration of %q+D not supported", decl);
 
   mark_weak (decl);
@@ -6283,6 +6289,13 @@ default_valid_pointer_mode (enum machine
   return (mode == ptr_mode || mode == Pmode);
 }
 
+enum machine_mode
+default_addr_space_pointer_mode (int addrspace)
+{
+  gcc_assert (addrspace == 0);
+  return ptr_mode;
+}
+
 /* Default function to output code that will globalize a label.  A
    target must define GLOBAL_ASM_OP or provide its own function to
    globalize a label.  */
--- gcc-clean/gcc/doc/extend.texi	2008-08-18 22:11:01.000000000 +1000
+++ gcc-nas/gcc/doc/extend.texi	2008-08-19 20:13:38.000000000 +1000
@@ -37,6 +37,7 @@ extensions, accepted by GCC in C89 mode 
 * Decimal Float::       Decimal Floating Types. 
 * Hex Floats::          Hexadecimal floating-point constants.
 * Fixed-Point::         Fixed-Point Types.
+* Named Address Spaces::Named address spaces.
 * Zero Length::         Zero-length arrays.
 * Variable Length::     Arrays whose length is computed at run time.
 * Empty Structures::    Structures with no members.
@@ -1119,6 +1120,31 @@ Pragmas to control overflow and rounding
 
 Fixed-point types are supported by the DWARF2 debug information format.
 
+@node Named Address Spaces
+@section Named address spaces
+@cindex named address spaces
+
+As an extension, the GNU C compiler supports named address spaces as
+defined in the N1169 draft of ISO/IEC DTR 18037.  Support for named
+address spaces in GCC will evolve as the draft technical report changes.
+Calling conventions for any target might also change.  At present, only
+the SPU target supports other address spaces.  On the SPU target, for
+example, variables may be declared as belonging to another address space
+by qualifying the type with the @var{__ea} address space identifier:
+
+@smallexample
+extern int __ea i;
+@end smallexample
+
+When the variable @var{i} is accessed, the compiler will generate
+special code to access this variable.  It may use runtime library
+support, or generate special machine instructions to access that address
+space.
+
+The @var{__ea} identifier may be used exactly like any other C type
+qualifier (e.g. const or volatile).  See the N1169 document for more
+details.
+
 @node Zero Length
 @section Arrays of Length Zero
 @cindex arrays of length zero
--- gcc-clean/gcc/doc/rtl.texi	2008-06-30 10:09:13.000000000 +1000
+++ gcc-nas/gcc/doc/rtl.texi	2008-07-15 15:46:04.000000000 +1000
@@ -420,6 +420,11 @@ the size is implied by the mode.
 @findex MEM_ALIGN
 @item MEM_ALIGN (@var{x})
 The known alignment in bits of the memory reference.
+
+@findex MEM_ADDR_SPACE
+@item MEM_ADDR_SPACE (@var{x})
+The address space of the memory reference.  This will commonly be zero
+for the generic address space.
 @end table
 
 @item REG
--- gcc-clean/gcc/doc/tm.texi	2008-08-17 09:48:09.000000000 +1000
+++ gcc-nas/gcc/doc/tm.texi	2008-08-20 12:28:17.000000000 +1000
@@ -4170,10 +4170,9 @@ hook returns true for both @code{ptr_mod
 @end deftypefn
 
 @deftypefn {Target Hook} bool TARGET_SCALAR_MODE_SUPPORTED_P (enum machine_mode @var{mode})
-Define this to return nonzero if the port is prepared to handle
-insns involving scalar mode @var{mode}.  For a scalar mode to be
-considered supported, all the basic arithmetic and comparisons
-must work.
+Define this to return nonzero if the port is prepared to handle insns
+involving scalar mode @var{mode}.  For a scalar mode to be considered
+supported, all the basic arithmetic and comparisons must work.
 
 The default version of this hook returns true for any mode
 required to handle the basic C types (as defined by the port).
@@ -10550,3 +10549,37 @@ cannot safely move arguments from the re
 to the stack.  Therefore, this hook should return true in general, but
 false for naked functions.  The default implementation always returns true.
 @end deftypefn
+
+@deftypefn {Target Hook} {enum machine_mode} TARGET_ADDR_SPACE_POINTER_MODE (int @var{address_space})
+Define this to return a pointer mode for a given @var{address_space} if
+the target supports named address spaces.  The default version of this
+hook returns @code{ptr_mode} for the generic address space only.
+@end deftypefn
+
+@deftypefn {Target Hook} {const char *} TARGET_ADDR_SPACE_NAME (int @var{address_space})
+Define this to return a string that describes the @var{address_space}.
+As this hook should never be called for targets that do not support
+named address spaces, the default version of this hook will cause the
+compiler to abort.
+@end deftypefn
+
+@deftypefn {Target Hook} {unsigned char} TARGET_ADDR_SPACE_NUMBER (tree @var{address_space})
+Define this to return a target-defined address space number for the
+given @var{address_space}.  As this hook should never be called for
+targets that do not support named address spaces, the default version
+of this hook will cause the compiler to abort.
+@end deftypefn
+
+@deftypefn {Target Hook} {rtx (*int, int)} TARGET_ADDR_SPACE_CONVERSION_RTL (int @var{from}, int @var{to})
+Define this to return a pointer to a function that generates the RTL for
+a pointer conversion from the @var{from} address space to the @var{to}
+address space.  As this hook should never be called for targets that do
+not support named address spaces, the default version of this hook will
+cause the compiler to abort.
+@end deftypefn
+
+@deftypefn {Target Hook} bool TARGET_VALID_ADDR_SPACE (tree @var{address_space})
+Define this to return true if the @var{address_space} is recognized
+for the target.  The default version of this hook unconditionally
+returns false.
+@end deftypefn


^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2008-08-29  6:10 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-08-20  7:29 PATCH: named address space support (1/2: target-independent parts) Ben Elliston
2008-08-20 10:36 ` Richard Guenther
2008-08-20 12:00   ` Ben Elliston
2008-08-20 12:47     ` C++ support? Re: PATCH: named address space support Ulrich Weigand
2008-08-20 14:05       ` Ben Elliston
2008-08-21  6:03   ` PATCH: named address space support (1/2: target-independent parts) Ben Elliston
2008-08-21 10:51     ` Richard Guenther
2008-08-21 11:25       ` Ben Elliston
2008-08-20 12:11 ` Joseph S. Myers
2008-08-21  8:37   ` Ben Elliston
2008-08-20 19:49 ` Joseph S. Myers
2008-08-20 20:49   ` Ben Elliston
2008-08-28 21:30   ` Ben Elliston
2008-08-28 21:52     ` Joseph S. Myers
2008-08-29  0:40       ` Ben Elliston
2008-08-30 13:05   ` *revised* " Ben Elliston
2008-08-30 13:35     ` Ralf Wildenhues
2008-08-30 13:37       ` Ben Elliston

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).