extend.texi (Variable Attributes): Document vector_size.

2001-12-07  Aldy Hernandez  <aldyh@redhat.com>

	* doc/extend.texi (Variable Attributes): Document vector_size.

        * attribs.c (c_common_attribute_table): Add vector_size.
	(handle_vector_size_attribute): New.
        (vector_size_helper): New.
	(decl_attributes): Relayout the decl after calculating attribs.

From-SVN: r47764
This commit is contained in:
Aldy Hernandez 2001-12-07 18:49:16 +00:00 committed by Aldy Hernandez
parent a9040c7798
commit 1b9191d275
3 changed files with 184 additions and 6 deletions

View File

@ -1,3 +1,12 @@
2001-12-07 Aldy Hernandez <aldyh@redhat.com>
* doc/extend.texi (Variable Attributes): Document vector_size.
* attribs.c (c_common_attribute_table): Add vector_size.
(handle_vector_size_attribute): New.
(vector_size_helper): New.
(decl_attributes): Relayout the decl after calculating attribs.
2001-12-07 Joseph S. Myers <jsm28@cam.ac.uk>
* doc/gcc.texi: Don't include install-old.texi. Adjust menu

View File

@ -82,6 +82,9 @@ static tree handle_no_limit_stack_attribute PARAMS ((tree *, tree, tree, int,
bool *));
static tree handle_pure_attribute PARAMS ((tree *, tree, tree, int,
bool *));
static tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int,
bool *));
static tree vector_size_helper PARAMS ((tree, tree));
/* Table of machine-independent attributes common to all C-like languages. */
static const struct attribute_spec c_common_attribute_table[] =
@ -135,6 +138,8 @@ static const struct attribute_spec c_common_attribute_table[] =
handle_no_limit_stack_attribute },
{ "pure", 0, 0, true, false, false,
handle_pure_attribute },
{ "vector_size", 1, 1, false, true, false,
handle_vector_size_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
@ -363,6 +368,18 @@ decl_attributes (node, attributes, flags)
returned_attrs = chainon ((*spec->handler) (anode, name, args,
flags, &no_add_attrs),
returned_attrs);
/* Layout the decl in case anything changed. */
if (spec->type_required && DECL_P (*node)
&& TREE_CODE (*node) == VAR_DECL)
{
/* Force a recalculation of mode and size. */
DECL_MODE (*node) = VOIDmode;
DECL_SIZE (*node) = 0;
layout_decl (*node, 0);
}
if (!no_add_attrs)
{
tree old_attrs;
@ -1119,6 +1136,128 @@ handle_pure_attribute (node, name, args, flags, no_add_attrs)
return NULL_TREE;
}
/* Handle a "vector_size" attribute; arguments as in
struct attribute_spec.handler. */
static tree
handle_vector_size_attribute (node, name, args, flags, no_add_attrs)
tree *node;
tree name;
tree args;
int flags ATTRIBUTE_UNUSED;
bool *no_add_attrs;
{
unsigned int vecsize, nunits;
enum machine_mode mode, orig_mode, new_mode;
tree type = *node, new_type;
*no_add_attrs = true;
if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
{
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
return NULL_TREE;
}
/* Get the vector size (in bytes). */
vecsize = TREE_INT_CST_LOW (TREE_VALUE (args));
/* We need to provide for vector pointers, vector arrays, and
functions returning vectors. For example:
__attribute__((vector_size(16))) short *foo;
In this case, the mode is SI, but the type being modified is
HI, so we need to look further. */
while (POINTER_TYPE_P (type)
|| TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
/* Get the mode of the type being modified. */
orig_mode = TYPE_MODE (type);
if (TREE_CODE (type) == RECORD_TYPE ||
(GET_MODE_CLASS (orig_mode) != MODE_FLOAT
&& GET_MODE_CLASS (orig_mode) != MODE_INT))
{
error ("invalid vector type for attribute `%s'",
IDENTIFIER_POINTER (name));
return NULL_TREE;
}
/* Calculate how many units fit in the vector. */
nunits = vecsize / TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
/* Find a suitably sized vector. */
new_mode = VOIDmode;
for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT
? MODE_VECTOR_INT
: MODE_VECTOR_FLOAT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
if (vecsize == GET_MODE_SIZE (mode) && nunits == GET_MODE_NUNITS (mode))
{
new_mode = mode;
break;
}
if (new_mode == VOIDmode)
error ("no vector mode with the size and type specified could be found");
else
{
new_type = type_for_mode (new_mode, TREE_UNSIGNED (type));
if (!new_type)
error ("no vector mode with the size and type specified could be found");
else
/* Build back pointers if needed. */
*node = vector_size_helper (*node, new_type);
}
return NULL_TREE;
}
/* HACK. GROSS. This is absolutely disgusting. I wish there was a
better way.
If we requested a pointer to a vector, build up the pointers that
we stripped off while looking for the inner type. Similarly for
return values from functions.
The argument "type" is the top of the chain, and "bottom" is the
new type which we will point to. */
static tree
vector_size_helper (type, bottom)
tree type, bottom;
{
tree inner, outer;
if (POINTER_TYPE_P (type))
{
inner = vector_size_helper (TREE_TYPE (type), bottom);
outer = build_pointer_type (inner);
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{
inner = vector_size_helper (TREE_TYPE (type), bottom);
outer = build_array_type (inner, TYPE_VALUES (type));
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
inner = vector_size_helper (TREE_TYPE (type), bottom);
outer = build_function_type (inner, TYPE_VALUES (type));
}
else
return bottom;
TREE_READONLY (outer) = TREE_READONLY (type);
TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type);
return outer;
}
/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
lists. SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).

View File

@ -2794,14 +2794,15 @@ section.
The keyword @code{__attribute__} allows you to specify special
attributes of variables or structure fields. This keyword is followed
by an attribute specification inside double parentheses. Eight
by an attribute specification inside double parentheses. Nine
attributes are currently defined for variables: @code{aligned},
@code{mode}, @code{nocommon}, @code{packed}, @code{section},
@code{transparent_union}, @code{unused}, and @code{weak}. Some other
attributes are defined for variables on particular target systems. Other
attributes are available for functions (@pxref{Function Attributes}) and
for types (@pxref{Type Attributes}). Other front ends might define more
attributes (@pxref{C++ Extensions,,Extensions to the C++ Language}).
@code{transparent_union}, @code{unused}, @code{vector_size}, and
@code{weak}. Some other attributes are defined for variables on
particular target systems. Other attributes are available for functions
(@pxref{Function Attributes}) and for types (@pxref{Type Attributes}).
Other front ends might define more attributes (@pxref{C++
Extensions,,Extensions to the C++ Language}).
You may also specify attributes with @samp{__} preceding and following
each keyword. This allows you to use them in header files without
@ -3003,6 +3004,35 @@ This attribute, attached to a variable, means that the variable is meant
to be possibly unused. GCC will not produce a warning for this
variable.
@item vector_size (@var{bytes})
This attribute specifies the vector size for the variable, measured in
bytes. For example, the declaration:
@smallexample
int foo __attribute__ ((vector_size (16)));
@end smallexample
@noindent
causes the compiler to set the mode for @code{foo}, to be 16 bytes,
divided into @code{int} sized units. Assuming a 32-bit int (a vector of
4 units of 4 bytes), the corresponding mode of @code{foo} will be V4SI@.
This attribute is only applicable to integral and float scalars,
although arrays, pointers, and function return values are allowed in
conjunction with this construct.
Aggregates with this attribute are invalid, even if they are of the same
size as a corresponding scalar. For example, the declaration:
@smallexample
struct S { int a; };
struct S __attribute__ ((vector_size (16))) foo;
@end smallexample
@noindent
is invalid even if the size of the structure is the same as the size of
the @code{int}.
@item weak
The @code{weak} attribute is described in @xref{Function Attributes}.