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:
parent
a9040c7798
commit
1b9191d275
|
@ -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
|
||||
|
|
139
gcc/attribs.c
139
gcc/attribs.c
|
@ -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).
|
||||
|
||||
|
|
|
@ -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}.
|
||||
|
||||
|
|
Loading…
Reference in New Issue