Commit 36c5e70a by Ben Elliston Committed by Ulrich Weigand

tm.texi (TARGET_ADDR_SPACE_KEYWORDS): Document.

2009-10-26  Ben Elliston  <bje@au.ibm.com>
	    Michael Meissner  <meissner@linux.vnet.ibm.com>
	    Ulrich Weigand  <uweigand@de.ibm.com>

	* doc/tm.texi (TARGET_ADDR_SPACE_KEYWORDS): Document.

	* c-common.c (c_common_reswords): If TARGET_ADDR_SPACE_KEYWORDS is
	defined, add the named address space keywords.
	(c_addr_space_name): New function.
	(complete_array_type): Preserve named address space.
	(handle_mode_attribute): Use targetm.addr_space.valid_pointer_mode
	instead of targetm.valid_pointer_mode.

	* c-common.h (enum rid): Add RID_ADDR_SPACE_0 .. RID_ADDR_SPACE_15,
	RID_FIRST_ADDR_SPACE and RID_LAST_ADDR_SPACE.
	(ADDR_SPACE_KEYWORD): New macro.
	(c_addr_space_name): Add prototype.

	* c-tree.h (struct c_declspecs): Add address_space member.
	(declspecs_add_addrspace): Add prototype.

	* c-pretty-print.c (pp_c_type_qualifier_list): Handle address spaces.

	* c-parser.c (c_parse_init): Add assertion.
	(typedef enum c_id_kind): Add C_ID_ADDRSPACE.
	(c_lex_one_token): Handle address space keywords.
	(c_token_starts_typename): Likewise.
	(c_token_starts_declspecs): Likewise.
	(c_parser_declspecs): Likewise.
	(c_parser_postfix_expression_after_paren_type): Diagnose compound
	literal within function qualified with named address space.

	* c-decl.c (diagnose_mismatched_decls): Diagnose conflicting named
	address space qualifiers.
	(shadow_tag_warned): Warn about useless address space qualifiers.
	(quals_from_declspecs): Handle address space qualifiers.
	(grokdeclarator): Likewise.
	(build_null_declspecs): Likewise.
	(declspecs_add_addrspace): New function.

	* c-typeck.c (addr_space_superset): New function.
	(qualify_type): Handle named address spaces.
	(composite_type): Likewise.
	(common_pointer_type): Likewise.
	(comp_target_types): Likewise.
	(build_conditional_expr): Likewise.
	(handle_warn_cast_qual): Likewise.
	(build_c_cast): Likewise.
	(convert_for_assignment): Likewise.
	(build_binary_op): Likewise.
	(pointer_diff): Handle named address spaces.  Use intermediate
	integer type of sufficient size if required.

Co-Authored-By: Michael Meissner <meissner@linux.vnet.ibm.com>
Co-Authored-By: Ulrich Weigand <uweigand@de.ibm.com>

From-SVN: r153574
parent d4ebfa65
......@@ -2,6 +2,59 @@
Michael Meissner <meissner@linux.vnet.ibm.com>
Ulrich Weigand <uweigand@de.ibm.com>
* doc/tm.texi (TARGET_ADDR_SPACE_KEYWORDS): Document.
* c-common.c (c_common_reswords): If TARGET_ADDR_SPACE_KEYWORDS is
defined, add the named address space keywords.
(c_addr_space_name): New function.
(complete_array_type): Preserve named address space.
(handle_mode_attribute): Use targetm.addr_space.valid_pointer_mode
instead of targetm.valid_pointer_mode.
* c-common.h (enum rid): Add RID_ADDR_SPACE_0 .. RID_ADDR_SPACE_15,
RID_FIRST_ADDR_SPACE and RID_LAST_ADDR_SPACE.
(ADDR_SPACE_KEYWORD): New macro.
(c_addr_space_name): Add prototype.
* c-tree.h (struct c_declspecs): Add address_space member.
(declspecs_add_addrspace): Add prototype.
* c-pretty-print.c (pp_c_type_qualifier_list): Handle address spaces.
* c-parser.c (c_parse_init): Add assertion.
(typedef enum c_id_kind): Add C_ID_ADDRSPACE.
(c_lex_one_token): Handle address space keywords.
(c_token_starts_typename): Likewise.
(c_token_starts_declspecs): Likewise.
(c_parser_declspecs): Likewise.
(c_parser_postfix_expression_after_paren_type): Diagnose compound
literal within function qualified with named address space.
* c-decl.c (diagnose_mismatched_decls): Diagnose conflicting named
address space qualifiers.
(shadow_tag_warned): Warn about useless address space qualifiers.
(quals_from_declspecs): Handle address space qualifiers.
(grokdeclarator): Likewise.
(build_null_declspecs): Likewise.
(declspecs_add_addrspace): New function.
* c-typeck.c (addr_space_superset): New function.
(qualify_type): Handle named address spaces.
(composite_type): Likewise.
(common_pointer_type): Likewise.
(comp_target_types): Likewise.
(build_conditional_expr): Likewise.
(handle_warn_cast_qual): Likewise.
(build_c_cast): Likewise.
(convert_for_assignment): Likewise.
(build_binary_op): Likewise.
(pointer_diff): Handle named address spaces. Use intermediate
integer type of sufficient size if required.
2009-10-26 Ben Elliston <bje@au.ibm.com>
Michael Meissner <meissner@linux.vnet.ibm.com>
Ulrich Weigand <uweigand@de.ibm.com>
* doc/tm.texi (TARGET_ADDR_SPACE_POINTER_MODE): Document.
(TARGET_ADDR_SPACE_ADDRESS_MODE): Likewise.
(TARGET_ADDR_SPACE_VALID_POINTER_MODE): Likewise.
......@@ -710,6 +710,11 @@ const struct c_common_resword c_common_reswords[] =
{ "inout", RID_INOUT, D_OBJC },
{ "oneway", RID_ONEWAY, D_OBJC },
{ "out", RID_OUT, D_OBJC },
#ifdef TARGET_ADDR_SPACE_KEYWORDS
/* Any address space keywords recognized by the target. */
TARGET_ADDR_SPACE_KEYWORDS,
#endif
};
const unsigned int num_c_common_reswords =
......@@ -840,6 +845,19 @@ const struct attribute_spec c_common_format_attribute_table[] =
{ NULL, 0, 0, false, false, false, NULL }
};
/* Return identifier for address space AS. */
const char *
c_addr_space_name (addr_space_t as)
{
unsigned int i;
for (i = 0; i < num_c_common_reswords; i++)
if (c_common_reswords[i].rid == RID_FIRST_ADDR_SPACE + as)
return c_common_reswords[i].word;
gcc_unreachable ();
}
/* Push current bindings for the function name VAR_DECLS. */
void
......@@ -6459,9 +6477,10 @@ handle_mode_attribute (tree *node, tree name, tree args,
if (POINTER_TYPE_P (type))
{
addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type));
tree (*fn)(tree, enum machine_mode, bool);
if (!targetm.valid_pointer_mode (mode))
if (!targetm.addr_space.valid_pointer_mode (mode, as))
{
error ("invalid pointer mode %qs", p);
return NULL_TREE;
......@@ -8511,7 +8530,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
if (quals == 0)
unqual_elt = elt;
else
unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
unqual_elt = c_build_qualified_type (elt, KEEP_QUAL_ADDR_SPACE (quals));
/* Using build_distinct_type_copy and modifying things afterward instead
of using build_array_type to create a new type preserves all of the
......
......@@ -126,6 +126,30 @@ enum rid
RID_AT_INTERFACE,
RID_AT_IMPLEMENTATION,
/* Named address support, mapping the keyword to a particular named address
number. Named address space 0 is reserved for the generic address. If
there are more than 254 named addresses, the addr_space_t type will need
to be grown from an unsigned char to unsigned short. */
RID_ADDR_SPACE_0, /* generic address */
RID_ADDR_SPACE_1,
RID_ADDR_SPACE_2,
RID_ADDR_SPACE_3,
RID_ADDR_SPACE_4,
RID_ADDR_SPACE_5,
RID_ADDR_SPACE_6,
RID_ADDR_SPACE_7,
RID_ADDR_SPACE_8,
RID_ADDR_SPACE_9,
RID_ADDR_SPACE_10,
RID_ADDR_SPACE_11,
RID_ADDR_SPACE_12,
RID_ADDR_SPACE_13,
RID_ADDR_SPACE_14,
RID_ADDR_SPACE_15,
RID_FIRST_ADDR_SPACE = RID_ADDR_SPACE_0,
RID_LAST_ADDR_SPACE = RID_ADDR_SPACE_15,
RID_MAX,
RID_FIRST_MODIFIER = RID_STATIC,
......@@ -263,6 +287,10 @@ struct c_common_resword
#define D_CXX_OBJC 0x100 /* In Objective C, and C++, but not C. */
#define D_CXXWARN 0x200 /* In C warn with -Wcxx-compat. */
/* Macro for backends to define named address keywords. */
#define ADDR_SPACE_KEYWORD(STRING, VALUE) \
{ STRING, RID_FIRST_ADDR_SPACE + (VALUE), D_CONLY | D_EXT }
/* The reserved keyword table. */
extern const struct c_common_resword c_common_reswords[];
......@@ -760,6 +788,7 @@ extern const struct attribute_spec c_common_format_attribute_table[];
extern tree (*make_fname_decl) (location_t, tree, int);
extern const char *c_addr_space_name (addr_space_t as);
extern tree identifier_global_value (tree);
extern void record_builtin_type (enum rid, const char *, tree);
extern tree build_void_list_node (void);
......
......@@ -1746,8 +1746,35 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
else
{
if (TYPE_QUALS (newtype) != TYPE_QUALS (oldtype))
error ("conflicting type qualifiers for %q+D", newdecl);
int new_quals = TYPE_QUALS (newtype);
int old_quals = TYPE_QUALS (oldtype);
if (new_quals != old_quals)
{
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)
{
if (ADDR_SPACE_GENERIC_P (new_addr))
error ("conflicting named address spaces (generic vs %s) "
"for %q+D",
c_addr_space_name (old_addr), newdecl);
else if (ADDR_SPACE_GENERIC_P (old_addr))
error ("conflicting named address spaces (%s vs generic) "
"for %q+D",
c_addr_space_name (new_addr), newdecl);
else
error ("conflicting named address spaces (%s vs %s) "
"for %q+D",
c_addr_space_name (new_addr),
c_addr_space_name (old_addr),
newdecl);
}
if (CLEAR_QUAL_ADDR_SPACE (new_quals)
!= CLEAR_QUAL_ADDR_SPACE (old_quals))
error ("conflicting type qualifiers for %q+D", newdecl);
}
else
error ("conflicting types for %q+D", newdecl);
diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
......@@ -3605,7 +3632,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
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 (input_location, 0,
......@@ -3676,7 +3704,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
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;
......@@ -3699,7 +3728,8 @@ quals_from_declspecs (const struct c_declspecs *specs)
{
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
......@@ -4750,6 +4780,7 @@ grokdeclarator (const struct c_declarator *declarator,
bool bitfield = width != NULL;
tree element_type;
struct c_arg_info *arg_info = 0;
addr_space_t as1, as2, address_space;
location_t loc = UNKNOWN_LOCATION;
const char *errmsg;
tree expr_dummy;
......@@ -4880,6 +4911,10 @@ grokdeclarator (const struct c_declarator *declarator,
constp = declspecs->const_p + TYPE_READONLY (element_type);
restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
as1 = declspecs->address_space;
as2 = TYPE_ADDR_SPACE (element_type);
address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
if (pedantic && !flag_isoc99)
{
if (constp > 1)
......@@ -4889,11 +4924,17 @@ grokdeclarator (const struct c_declarator *declarator,
if (volatilep > 1)
pedwarn (loc, OPT_pedantic, "duplicate %<volatile%>");
}
if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
error_at (loc, "conflicting named address spaces (%s vs %s)",
c_addr_space_name (as1), c_addr_space_name (as2));
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)
| ENCODE_QUAL_ADDR_SPACE (address_space));
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
......@@ -5309,7 +5350,14 @@ grokdeclarator (const struct c_declarator *declarator,
it, but here we want to make sure we don't ever
modify the shared type, so we gcc_assert (itype)
below. */
type = build_array_type (type, itype);
{
addr_space_t as = DECODE_QUAL_ADDR_SPACE (type_quals);
if (!ADDR_SPACE_GENERIC_P (as) && as != TYPE_ADDR_SPACE (type))
type = build_qualified_type (type,
ENCODE_QUAL_ADDR_SPACE (as));
type = build_array_type (type, itype);
}
if (type != error_mark_node)
{
......@@ -5515,6 +5563,59 @@ grokdeclarator (const struct c_declarator *declarator,
/* Now TYPE has the actual type, apart from any qualifiers in
TYPE_QUALS. */
/* Warn about address space used for things other than static memory or
pointers. */
address_space = DECODE_QUAL_ADDR_SPACE (type_quals);
if (!ADDR_SPACE_GENERIC_P (address_space))
{
if (decl_context == NORMAL)
{
switch (storage_class)
{
case csc_auto:
error ("%qs combined with %<auto%> qualifier for %qE",
c_addr_space_name (address_space), name);
break;
case csc_register:
error ("%qs combined with %<register%> qualifier for %qE",
c_addr_space_name (address_space), name);
break;
case csc_none:
if (current_function_scope)
{
error ("%qs specified for auto variable %qE",
c_addr_space_name (address_space), name);
break;
}
break;
case csc_static:
case csc_extern:
case csc_typedef:
break;
default:
gcc_unreachable ();
}
}
else if (decl_context == PARM && TREE_CODE (type) != ARRAY_TYPE)
{
if (name)
error ("%qs specified for parameter %qE",
c_addr_space_name (address_space), name);
else
error ("%qs specified for unnamed parameter",
c_addr_space_name (address_space));
}
else if (decl_context == FIELD)
{
if (name)
error ("%qs specified for structure field %qE",
c_addr_space_name (address_space), name);
else
error ("%qs specified for structure field",
c_addr_space_name (address_space));
}
}
/* Check the type and width of a bit-field. */
if (bitfield)
check_bitfield_type_and_width (&type, width, name);
......@@ -8297,9 +8398,29 @@ build_null_declspecs (void)
ret->volatile_p = false;
ret->restrict_p = false;
ret->saturating_p = false;
ret->address_space = ADDR_SPACE_GENERIC;
return ret;
}
/* Add the address space ADDRSPACE to the declaration specifiers
SPECS, returning SPECS. */
struct c_declspecs *
declspecs_add_addrspace (struct c_declspecs *specs, addr_space_t as)
{
specs->non_sc_seen_p = true;
specs->declspecs_seen_p = true;
if (!ADDR_SPACE_GENERIC_P (specs->address_space)
&& specs->address_space != as)
error ("incompatible address space qualifiers %qs and %qs",
c_addr_space_name (as),
c_addr_space_name (specs->address_space));
else
specs->address_space = as;
return specs;
}
/* Add the type qualifier QUAL to the declaration specifiers SPECS,
returning SPECS. */
......
......@@ -72,6 +72,10 @@ c_parse_init (void)
tree id;
int mask = 0;
/* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in
the c_token structure. */
gcc_assert (RID_MAX <= 255);
mask |= D_CXXONLY;
if (!flag_isoc99)
mask |= D_C99;
......@@ -132,6 +136,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;
......@@ -226,6 +232,13 @@ c_lex_one_token (c_parser *parser, c_token *token)
"identifier %qE conflicts with C++ keyword",
token->value);
}
else if (rid_code >= RID_FIRST_ADDR_SPACE
&& rid_code <= RID_LAST_ADDR_SPACE)
{
token->id_kind = C_ID_ADDRSPACE;
token->keyword = rid_code;
break;
}
else if (c_dialect_objc ())
{
if (!objc_is_reserved_word (token->value)
......@@ -352,6 +365,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 +437,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:
......@@ -1411,6 +1428,7 @@ c_parser_asm_definition (c_parser *parser)
const
restrict
volatile
address-space-qualifier
(restrict is new in C99.)
......@@ -1419,6 +1437,12 @@ c_parser_asm_definition (c_parser *parser)
declaration-specifiers:
attributes declaration-specifiers[opt]
type-qualifier:
address-space
address-space:
identifier recognized by the target
storage-class-specifier:
__thread
......@@ -1459,6 +1483,17 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
{
tree value = c_parser_peek_token (parser)->value;
c_id_kind kind = c_parser_peek_token (parser)->id_kind;
if (kind == C_ID_ADDRSPACE)
{
addr_space_t as
= c_parser_peek_token (parser)->keyword - RID_FIRST_ADDR_SPACE;
declspecs_add_addrspace (specs, as);
c_parser_consume_token (parser);
attrs_ok = 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. */
......@@ -5775,6 +5810,14 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
finish_init ();
maybe_warn_string_init (type, init);
if (type != error_mark_node
&& !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
&& current_function_decl)
{
error ("compound literal qualified by address-space qualifier");
type = error_mark_node;
}
if (!flag_isoc99)
pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals");
non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
......
......@@ -225,7 +225,11 @@ pp_c_space_for_pointer_operator (c_pretty_printer *pp, tree t)
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)
......@@ -245,6 +249,12 @@ pp_c_type_qualifier_list (c_pretty_printer *pp, tree t)
pp_c_cv_qualifier (pp, "volatile");
if (qualifiers & TYPE_QUAL_RESTRICT)
pp_c_cv_qualifier (pp, flag_isoc99 ? "restrict" : "__restrict__");
if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (t)))
{
const char *as = c_addr_space_name (TYPE_ADDR_SPACE (t));
pp_c_identifier (pp, as);
}
}
/* pointer:
......
......@@ -277,6 +277,8 @@ struct c_declspecs {
BOOL_BITFIELD restrict_p : 1;
/* Whether "_Sat" was specified. */
BOOL_BITFIELD saturating_p : 1;
/* The address space that the declaration belongs to. */
addr_space_t address_space;
};
/* The various kinds of declarators in C. */
......@@ -476,6 +478,8 @@ extern struct c_declspecs *declspecs_add_type (location_t,
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 *,
addr_space_t);
extern struct c_declspecs *finish_declspecs (struct c_declspecs *);
/* in c-objc-common.c */
......
......@@ -9855,6 +9855,18 @@ Internally, address spaces are represented as a small integer in the
range 0 to 15 with address space 0 being reserved for the generic
address space.
@defmac TARGET_ADDR_SPACE_KEYWORDS
A list of @code{ADDR_SPACE_KEYWORD} macros to define each named
address keyword. The @code{ADDR_SPACE_KEYWORD} macro takes two
arguments, the keyword string and the number of the named address
space. For example, the SPU port uses the following to declare
@code{__ea} as the keyword for named address space #1:
@smallexample
#define ADDR_SPACE_EA 1
#define TARGET_ADDR_SPACE_KEYWORDS ADDR_SPACE_KEYWORD ("__ea", ADDR_SPACE_EA)
@end smallexample
@end defmac
@deftypefn {Target Hook} {enum machine_mode} TARGET_ADDR_SPACE_POINTER_MODE (addr_space_t @var{address_space})
Define this to return the machine mode to use for pointers to
@var{address_space} if the target supports named address spaces.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment