Commit 7948ae37 by Olivier Hainque

ada-tree.h (TYPE_REPRESENTATIVE_ARRAY): New language specific node.

        ada/
        * gcc-interface/ada-tree.h (TYPE_REPRESENTATIVE_ARRAY): New language
        specific node.  Representative array type for VECTOR_TYPE entities.
        * gcc-interface/utils.c (handle_vector_type_attribute): New handler.
        Turn an ARRAY_TYPE entity into a VECTOR_TYPE.
        (gnat_types_compatible_p): Handle VECTOR_TYPEs.
        (convert): Likewise.  Arrange to produce VECTOR_CST out of constant
        array aggregates for VECTOR_TYPE entities.
        (unchecked_convert): Likewise.
        (maybe_vector_array): New function. If EXP has VECTOR_TYPE, return EXP
        converted to the associated TYPE_REPRESENTATIVE_ARRAY.
        (handle_pure_attribute, handle_sentinel_attribute,
        handle_noreturn_attribute, handle_malloc_attribute,
        handle_vector_size_attribute): Replace uses of qE format by qs.
        Remove GCC_DIAG_STYLE definition.
        * gcc-interface/trans.c (gnat_to_gnu) <N_Indexed_Component>: Convert
        vector input to representative array type on entry.
        <N_Op_Eq, etc>: Likewise.
        * gcc-interface/gigi.h (maybe_vector_array): Declare.
        (VECTOR_TYPE_P): New predicate.
        * gcc-interface/misc.c (gnat_print_type): Handle VECTOR_TYPE.

        testsuite/
        * gnat.dg/sse_nolib.adb: New testcase.

From-SVN: r152165
parent 6e1ee24b
2009-09-22 Olivier Hainquqe <hainque@adacore.com>
Eric Botcazou <botcazou@adacore.com>
* gcc-interface/ada-tree.h (TYPE_REPRESENTATIVE_ARRAY): New language
specific node. Representative array type for VECTOR_TYPE entities.
* gcc-interface/utils.c (handle_vector_type_attribute): New handler.
Turn an ARRAY_TYPE entity into a VECTOR_TYPE.
(gnat_types_compatible_p): Handle VECTOR_TYPEs.
(convert): Likewise. Arrange to produce VECTOR_CST out of constant
array aggregates for VECTOR_TYPE entities.
(unchecked_convert): Likewise.
(maybe_vector_array): New function. If EXP has VECTOR_TYPE, return EXP
converted to the associated TYPE_REPRESENTATIVE_ARRAY.
(handle_pure_attribute, handle_sentinel_attribute,
handle_noreturn_attribute, handle_malloc_attribute,
handle_vector_size_attribute): Replace uses of qE format by qs.
Remove GCC_DIAG_STYLE definition.
* gcc-interface/trans.c (gnat_to_gnu) <N_Indexed_Component>: Convert
vector input to representative array type on entry.
<N_Op_Eq, etc>: Likewise.
* gcc-interface/gigi.h (maybe_vector_array): Declare.
(VECTOR_TYPE_P): New predicate.
* gcc-interface/misc.c (gnat_print_type): Handle VECTOR_TYPE.
2009-09-24 Eric Botcazou <ebotcazou@adacore.com> 2009-09-24 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/ada.h: Fix outdated comment. * gcc-interface/ada.h: Fix outdated comment.
......
...@@ -195,6 +195,10 @@ do { \ ...@@ -195,6 +195,10 @@ do { \
refer to the routine gnat_to_gnu_entity. */ refer to the routine gnat_to_gnu_entity. */
#define TYPE_CI_CO_LIST(NODE) TYPE_LANG_SLOT_1 (FUNCTION_TYPE_CHECK (NODE)) #define TYPE_CI_CO_LIST(NODE) TYPE_LANG_SLOT_1 (FUNCTION_TYPE_CHECK (NODE))
/* For a VECTOR_TYPE, this is the representative array type. */
#define TYPE_REPRESENTATIVE_ARRAY(NODE) \
TYPE_LANG_SLOT_1 (VECTOR_TYPE_CHECK (NODE))
/* For numerical types, this holds various RM-defined values. */ /* For numerical types, this holds various RM-defined values. */
#define TYPE_RM_VALUES(NODE) TYPE_LANG_SLOT_1 (NUMERICAL_TYPE_CHECK (NODE)) #define TYPE_RM_VALUES(NODE) TYPE_LANG_SLOT_1 (NUMERICAL_TYPE_CHECK (NODE))
......
...@@ -750,6 +750,10 @@ extern tree remove_conversions (tree exp, bool true_address); ...@@ -750,6 +750,10 @@ extern tree remove_conversions (tree exp, bool true_address);
likewise return an expression pointing to the underlying array. */ likewise return an expression pointing to the underlying array. */
extern tree maybe_unconstrained_array (tree exp); extern tree maybe_unconstrained_array (tree exp);
/* If EXP's type is a VECTOR_TYPE, return EXP converted to the associated
TYPE_REPRESENTATIVE_ARRAY. */
extern tree maybe_vector_array (tree exp);
/* Return an expression that does an unchecked conversion of EXPR to TYPE. /* Return an expression that does an unchecked conversion of EXPR to TYPE.
If NOTRUNC_P is true, truncation operations should be suppressed. */ If NOTRUNC_P is true, truncation operations should be suppressed. */
extern tree unchecked_convert (tree type, tree expr, bool notrunc_p); extern tree unchecked_convert (tree type, tree expr, bool notrunc_p);
...@@ -951,3 +955,6 @@ extern Nat get_target_double_scalar_alignment (void); ...@@ -951,3 +955,6 @@ extern Nat get_target_double_scalar_alignment (void);
#ifndef TARGET_MALLOC64 #ifndef TARGET_MALLOC64
#define TARGET_MALLOC64 0 #define TARGET_MALLOC64 0
#endif #endif
/* Convenient shortcuts. */
#define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE)
...@@ -521,6 +521,11 @@ gnat_print_type (FILE *file, tree node, int indent) ...@@ -521,6 +521,11 @@ gnat_print_type (FILE *file, tree node, int indent)
print_node (file,"actual bounds", TYPE_ACTUAL_BOUNDS (node), indent + 4); print_node (file,"actual bounds", TYPE_ACTUAL_BOUNDS (node), indent + 4);
break; break;
case VECTOR_TYPE:
print_node (file,"representative array",
TYPE_REPRESENTATIVE_ARRAY (node), indent + 4);
break;
case RECORD_TYPE: case RECORD_TYPE:
if (TYPE_IS_FAT_POINTER_P (node) || TYPE_CONTAINS_TEMPLATE_P (node)) if (TYPE_IS_FAT_POINTER_P (node) || TYPE_CONTAINS_TEMPLATE_P (node))
print_node (file, "unconstrained array", print_node (file, "unconstrained array",
......
...@@ -3832,6 +3832,11 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -3832,6 +3832,11 @@ gnat_to_gnu (Node_Id gnat_node)
Node_Id *gnat_expr_array; Node_Id *gnat_expr_array;
gnu_array_object = maybe_implicit_deref (gnu_array_object); gnu_array_object = maybe_implicit_deref (gnu_array_object);
/* Convert vector inputs to their representative array type, to fit
what the code below expects. */
gnu_array_object = maybe_vector_array (gnu_array_object);
gnu_array_object = maybe_unconstrained_array (gnu_array_object); gnu_array_object = maybe_unconstrained_array (gnu_array_object);
/* If we got a padded type, remove it too. */ /* If we got a padded type, remove it too. */
...@@ -4077,6 +4082,8 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -4077,6 +4082,8 @@ gnat_to_gnu (Node_Id gnat_node)
&& TYPE_CONTAINS_TEMPLATE_P (gnu_result_type)) && TYPE_CONTAINS_TEMPLATE_P (gnu_result_type))
gnu_aggr_type gnu_aggr_type
= TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (gnu_result_type))); = TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (gnu_result_type)));
else if (TREE_CODE (gnu_result_type) == VECTOR_TYPE)
gnu_aggr_type = TYPE_REPRESENTATIVE_ARRAY (gnu_result_type);
if (Null_Record_Present (gnat_node)) if (Null_Record_Present (gnat_node))
gnu_result = gnat_build_constructor (gnu_aggr_type, NULL_TREE); gnu_result = gnat_build_constructor (gnu_aggr_type, NULL_TREE);
...@@ -4272,6 +4279,12 @@ gnat_to_gnu (Node_Id gnat_node) ...@@ -4272,6 +4279,12 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_rhs = gnat_to_gnu (Right_Opnd (gnat_node)); gnu_rhs = gnat_to_gnu (Right_Opnd (gnat_node));
gnu_type = gnu_result_type = get_unpadded_type (Etype (gnat_node)); gnu_type = gnu_result_type = get_unpadded_type (Etype (gnat_node));
/* Pending generic support for efficient vector logical operations in
GCC, convert vectors to their representative array type view and
fallthrough. */
gnu_lhs = maybe_vector_array (gnu_lhs);
gnu_rhs = maybe_vector_array (gnu_rhs);
/* If this is a comparison operator, convert any references to /* If this is a comparison operator, convert any references to
an unconstrained array value into a reference to the an unconstrained array value into a reference to the
actual array. */ actual array. */
......
...@@ -23,10 +23,6 @@ ...@@ -23,10 +23,6 @@
* * * *
****************************************************************************/ ****************************************************************************/
/* We have attribute handlers using C specific format specifiers in warning
messages. Make sure they are properly recognized. */
#define GCC_DIAG_STYLE __gcc_cdiag__
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
#include "coretypes.h" #include "coretypes.h"
...@@ -101,6 +97,7 @@ static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); ...@@ -101,6 +97,7 @@ static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
static tree handle_malloc_attribute (tree *, tree, tree, int, bool *); static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *); static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
static tree handle_vector_size_attribute (tree *, tree, tree, int, bool *); static tree handle_vector_size_attribute (tree *, tree, tree, int, bool *);
static tree handle_vector_type_attribute (tree *, tree, tree, int, bool *);
/* Fake handler for attributes we don't properly support, typically because /* Fake handler for attributes we don't properly support, typically because
they'd require dragging a lot of the common-c front-end circuitry. */ they'd require dragging a lot of the common-c front-end circuitry. */
...@@ -122,6 +119,7 @@ const struct attribute_spec gnat_internal_attribute_table[] = ...@@ -122,6 +119,7 @@ const struct attribute_spec gnat_internal_attribute_table[] =
{ "type generic", 0, 0, false, true, true, handle_type_generic_attribute }, { "type generic", 0, 0, false, true, true, handle_type_generic_attribute },
{ "vector_size", 1, 1, false, true, false, handle_vector_size_attribute }, { "vector_size", 1, 1, false, true, false, handle_vector_size_attribute },
{ "vector_type", 0, 0, false, true, false, handle_vector_type_attribute },
{ "may_alias", 0, 0, false, true, false, NULL }, { "may_alias", 0, 0, false, true, false, NULL },
/* ??? format and format_arg are heavy and not supported, which actually /* ??? format and format_arg are heavy and not supported, which actually
...@@ -2269,6 +2267,14 @@ gnat_types_compatible_p (tree t1, tree t2) ...@@ -2269,6 +2267,14 @@ gnat_types_compatible_p (tree t1, tree t2)
if ((code = TREE_CODE (t1)) != TREE_CODE (t2)) if ((code = TREE_CODE (t1)) != TREE_CODE (t2))
return 0; return 0;
/* Vector types are also compatible if they have the same number of subparts
and the same form of (scalar) element type. */
if (code == VECTOR_TYPE
&& TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
&& TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))
&& TYPE_PRECISION (TREE_TYPE (t1)) == TYPE_PRECISION (TREE_TYPE (t2)))
return 1;
/* Array types are also compatible if they are constrained and have /* Array types are also compatible if they are constrained and have
the same component type and the same domain. */ the same component type and the same domain. */
if (code == ARRAY_TYPE if (code == ARRAY_TYPE
...@@ -3981,6 +3987,16 @@ convert (tree type, tree expr) ...@@ -3981,6 +3987,16 @@ convert (tree type, tree expr)
} }
break; break;
case VECTOR_CST:
/* If we are converting a VECTOR_CST to a mere variant type, just make
a new one in the proper type. */
if (code == ecode && gnat_types_compatible_p (type, etype))
{
expr = copy_node (expr);
TREE_TYPE (expr) = type;
return expr;
}
case CONSTRUCTOR: case CONSTRUCTOR:
/* If we are converting a CONSTRUCTOR to a mere variant type, just make /* If we are converting a CONSTRUCTOR to a mere variant type, just make
a new one in the proper type. */ a new one in the proper type. */
...@@ -4043,6 +4059,52 @@ convert (tree type, tree expr) ...@@ -4043,6 +4059,52 @@ convert (tree type, tree expr)
return expr; return expr;
} }
} }
/* Likewise for a conversion between array type and vector type with a
compatible representative array. */
else if (code == VECTOR_TYPE
&& ecode == ARRAY_TYPE
&& gnat_types_compatible_p (TYPE_REPRESENTATIVE_ARRAY (type),
etype))
{
VEC(constructor_elt,gc) *e = CONSTRUCTOR_ELTS (expr);
unsigned HOST_WIDE_INT len = VEC_length (constructor_elt, e);
VEC(constructor_elt,gc) *v;
unsigned HOST_WIDE_INT ix;
tree value;
/* Build a VECTOR_CST from a *constant* array constructor. */
if (TREE_CONSTANT (expr))
{
bool constant_p = true;
/* Iterate through elements and check if all constructor
elements are *_CSTs. */
FOR_EACH_CONSTRUCTOR_VALUE (e, ix, value)
if (!CONSTANT_CLASS_P (value))
{
constant_p = false;
break;
}
if (constant_p)
return build_vector_from_ctor (type,
CONSTRUCTOR_ELTS (expr));
}
/* Otherwise, build a regular vector constructor. */
v = VEC_alloc (constructor_elt, gc, len);
FOR_EACH_CONSTRUCTOR_VALUE (e, ix, value)
{
constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL);
elt->index = NULL_TREE;
elt->value = value;
}
expr = copy_node (expr);
TREE_TYPE (expr) = type;
CONSTRUCTOR_ELTS (expr) = v;
return expr;
}
break; break;
case UNCONSTRAINED_ARRAY_REF: case UNCONSTRAINED_ARRAY_REF:
...@@ -4071,10 +4133,11 @@ convert (tree type, tree expr) ...@@ -4071,10 +4133,11 @@ convert (tree type, tree expr)
if (type == TREE_TYPE (op0)) if (type == TREE_TYPE (op0))
return op0; return op0;
/* Otherwise, if we're converting between two aggregate types, we /* Otherwise, if we're converting between two aggregate or vector
might be allowed to substitute the VIEW_CONVERT_EXPR target type types, we might be allowed to substitute the VIEW_CONVERT_EXPR
in place or to just convert the inner expression. */ target type in place or to just convert the inner expression. */
if (AGGREGATE_TYPE_P (type) && AGGREGATE_TYPE_P (etype)) if ((AGGREGATE_TYPE_P (type) && AGGREGATE_TYPE_P (etype))
|| (VECTOR_TYPE_P (type) && VECTOR_TYPE_P (etype)))
{ {
/* If we are converting between mere variants, we can just /* If we are converting between mere variants, we can just
substitute the VIEW_CONVERT_EXPR in place. */ substitute the VIEW_CONVERT_EXPR in place. */
...@@ -4117,11 +4180,16 @@ convert (tree type, tree expr) ...@@ -4117,11 +4180,16 @@ convert (tree type, tree expr)
if (TYPE_FAT_POINTER_P (type) && !TYPE_FAT_POINTER_P (etype)) if (TYPE_FAT_POINTER_P (type) && !TYPE_FAT_POINTER_P (etype))
return convert_to_fat_pointer (type, expr); return convert_to_fat_pointer (type, expr);
/* If we are converting between two aggregate types that are mere /* If we are converting between two aggregate or vector types that are mere
variants, just make a VIEW_CONVERT_EXPR. */ variants, just make a VIEW_CONVERT_EXPR. Likewise when we are converting
else if (code == ecode to a vector type from its representative array type. */
&& AGGREGATE_TYPE_P (type) else if ((code == ecode
&& gnat_types_compatible_p (type, etype)) && (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type))
&& gnat_types_compatible_p (type, etype))
|| (code == VECTOR_TYPE
&& ecode == ARRAY_TYPE
&& gnat_types_compatible_p (TYPE_REPRESENTATIVE_ARRAY (type),
etype)))
return build1 (VIEW_CONVERT_EXPR, type, expr); return build1 (VIEW_CONVERT_EXPR, type, expr);
/* In all other cases of related types, make a NOP_EXPR. */ /* In all other cases of related types, make a NOP_EXPR. */
...@@ -4237,6 +4305,15 @@ convert (tree type, tree expr) ...@@ -4237,6 +4305,15 @@ convert (tree type, tree expr)
return unchecked_convert (type, expr, false); return unchecked_convert (type, expr, false);
case UNCONSTRAINED_ARRAY_TYPE: case UNCONSTRAINED_ARRAY_TYPE:
/* If the input is a VECTOR_TYPE, convert to the representative
array type first. */
if (ecode == VECTOR_TYPE)
{
expr = convert (TYPE_REPRESENTATIVE_ARRAY (etype), expr);
etype = TREE_TYPE (expr);
ecode = TREE_CODE (etype);
}
/* If EXPR is a constrained array, take its address, convert it to a /* If EXPR is a constrained array, take its address, convert it to a
fat pointer, and then dereference it. Likewise if EXPR is a fat pointer, and then dereference it. Likewise if EXPR is a
record containing both a template and a constrained array. record containing both a template and a constrained array.
...@@ -4366,6 +4443,20 @@ maybe_unconstrained_array (tree exp) ...@@ -4366,6 +4443,20 @@ maybe_unconstrained_array (tree exp)
return exp; return exp;
} }
/* If EXP's type is a VECTOR_TYPE, return EXP converted to the associated
TYPE_REPRESENTATIVE_ARRAY. */
tree
maybe_vector_array (tree exp)
{
tree etype = TREE_TYPE (exp);
if (VECTOR_TYPE_P (etype))
exp = convert (TYPE_REPRESENTATIVE_ARRAY (etype), exp);
return exp;
}
/* Return true if EXPR is an expression that can be folded as an operand /* Return true if EXPR is an expression that can be folded as an operand
of a VIEW_CONVERT_EXPR. See ada-tree.h for a complete rationale. */ of a VIEW_CONVERT_EXPR. See ada-tree.h for a complete rationale. */
...@@ -4501,15 +4592,24 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) ...@@ -4501,15 +4592,24 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
expr = unchecked_convert (type, expr, notrunc_p); expr = unchecked_convert (type, expr, notrunc_p);
} }
/* We have a special case when we are converting between two /* We have a special case when we are converting between two unconstrained
unconstrained array types. In that case, take the address, array types. In that case, take the address, convert the fat pointer
convert the fat pointer types, and dereference. */ types, and dereference. */
else if (TREE_CODE (etype) == UNCONSTRAINED_ARRAY_TYPE else if (TREE_CODE (etype) == UNCONSTRAINED_ARRAY_TYPE
&& TREE_CODE (type) == UNCONSTRAINED_ARRAY_TYPE) && TREE_CODE (type) == UNCONSTRAINED_ARRAY_TYPE)
expr = build_unary_op (INDIRECT_REF, NULL_TREE, expr = build_unary_op (INDIRECT_REF, NULL_TREE,
build1 (VIEW_CONVERT_EXPR, TREE_TYPE (type), build1 (VIEW_CONVERT_EXPR, TREE_TYPE (type),
build_unary_op (ADDR_EXPR, NULL_TREE, build_unary_op (ADDR_EXPR, NULL_TREE,
expr))); expr)));
/* Another special case is when we are converting to a vector type from its
representative array type; this a regular conversion. */
else if (TREE_CODE (type) == VECTOR_TYPE
&& TREE_CODE (etype) == ARRAY_TYPE
&& gnat_types_compatible_p (TYPE_REPRESENTATIVE_ARRAY (type),
etype))
expr = convert (type, expr);
else else
{ {
expr = maybe_unconstrained_array (expr); expr = maybe_unconstrained_array (expr);
...@@ -5060,7 +5160,8 @@ handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args), ...@@ -5060,7 +5160,8 @@ handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
/* ??? TODO: Support types. */ /* ??? TODO: Support types. */
else else
{ {
warning (OPT_Wattributes, "%qE attribute ignored", name); warning (OPT_Wattributes, "%qs attribute ignored",
IDENTIFIER_POINTER (name));
*no_add_attrs = true; *no_add_attrs = true;
} }
...@@ -5175,7 +5276,8 @@ handle_sentinel_attribute (tree *node, tree name, tree args, ...@@ -5175,7 +5276,8 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
if (!params) if (!params)
{ {
warning (OPT_Wattributes, warning (OPT_Wattributes,
"%qE attribute requires prototypes with named arguments", name); "%qs attribute requires prototypes with named arguments",
IDENTIFIER_POINTER (name));
*no_add_attrs = true; *no_add_attrs = true;
} }
else else
...@@ -5186,7 +5288,8 @@ handle_sentinel_attribute (tree *node, tree name, tree args, ...@@ -5186,7 +5288,8 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
if (VOID_TYPE_P (TREE_VALUE (params))) if (VOID_TYPE_P (TREE_VALUE (params)))
{ {
warning (OPT_Wattributes, warning (OPT_Wattributes,
"%qE attribute only applies to variadic functions", name); "%qs attribute only applies to variadic functions",
IDENTIFIER_POINTER (name));
*no_add_attrs = true; *no_add_attrs = true;
} }
} }
...@@ -5233,7 +5336,8 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args), ...@@ -5233,7 +5336,8 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
TYPE_READONLY (TREE_TYPE (type)), 1)); TYPE_READONLY (TREE_TYPE (type)), 1));
else else
{ {
warning (OPT_Wattributes, "%qE attribute ignored", name); warning (OPT_Wattributes, "%qs attribute ignored",
IDENTIFIER_POINTER (name));
*no_add_attrs = true; *no_add_attrs = true;
} }
...@@ -5252,7 +5356,8 @@ handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args), ...@@ -5252,7 +5356,8 @@ handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
DECL_IS_MALLOC (*node) = 1; DECL_IS_MALLOC (*node) = 1;
else else
{ {
warning (OPT_Wattributes, "%qE attribute ignored", name); warning (OPT_Wattributes, "%qs attribute ignored",
IDENTIFIER_POINTER (name));
*no_add_attrs = true; *no_add_attrs = true;
} }
...@@ -5311,7 +5416,8 @@ handle_vector_size_attribute (tree *node, tree name, tree args, ...@@ -5311,7 +5416,8 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
if (!host_integerp (size, 1)) if (!host_integerp (size, 1))
{ {
warning (OPT_Wattributes, "%qE attribute ignored", name); warning (OPT_Wattributes, "%qs attribute ignored",
IDENTIFIER_POINTER (name));
return NULL_TREE; return NULL_TREE;
} }
...@@ -5345,7 +5451,8 @@ handle_vector_size_attribute (tree *node, tree name, tree args, ...@@ -5345,7 +5451,8 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
|| !host_integerp (TYPE_SIZE_UNIT (type), 1) || !host_integerp (TYPE_SIZE_UNIT (type), 1)
|| TREE_CODE (type) == BOOLEAN_TYPE) || TREE_CODE (type) == BOOLEAN_TYPE)
{ {
error ("invalid vector type for attribute %qE", name); error ("invalid vector type for attribute %qs",
IDENTIFIER_POINTER (name));
return NULL_TREE; return NULL_TREE;
} }
...@@ -5377,6 +5484,103 @@ handle_vector_size_attribute (tree *node, tree name, tree args, ...@@ -5377,6 +5484,103 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
return NULL_TREE; return NULL_TREE;
} }
/* Handle a "vector_type" attribute; arguments as in
struct attribute_spec.handler. */
static tree
handle_vector_type_attribute (tree *node, tree name, tree ARG_UNUSED (args),
int ARG_UNUSED (flags),
bool *no_add_attrs)
{
/* Vector representative type and size. */
tree rep_type = *node;
tree rep_size = TYPE_SIZE_UNIT (rep_type);
tree rep_name;
/* Vector size in bytes and number of units. */
unsigned HOST_WIDE_INT vec_bytes, vec_units;
/* Vector element type and mode. */
tree elem_type;
enum machine_mode elem_mode;
*no_add_attrs = true;
/* Get the representative array type, possibly nested within a
padding record e.g. for alignment purposes. */
if (TREE_CODE (rep_type) == RECORD_TYPE && TYPE_IS_PADDING_P (rep_type))
rep_type = TREE_TYPE (TYPE_FIELDS (rep_type));
if (TREE_CODE (rep_type) != ARRAY_TYPE)
{
error ("attribute %qs applies to array types only",
IDENTIFIER_POINTER (name));
return NULL_TREE;
}
/* Silently punt on variable sizes. We can't make vector types for them,
need to ignore them on front-end generated subtypes of unconstrained
bases, and this attribute is for binding implementors, not end-users, so
we should never get there from legitimate explicit uses. */
if (!host_integerp (rep_size, 1))
return NULL_TREE;
/* Get the element type/mode and check this is something we know
how to make vectors of. */
elem_type = TREE_TYPE (rep_type);
elem_mode = TYPE_MODE (elem_type);
if ((!INTEGRAL_TYPE_P (elem_type)
&& !SCALAR_FLOAT_TYPE_P (elem_type)
&& !FIXED_POINT_TYPE_P (elem_type))
|| (!SCALAR_FLOAT_MODE_P (elem_mode)
&& GET_MODE_CLASS (elem_mode) != MODE_INT
&& !ALL_SCALAR_FIXED_POINT_MODE_P (elem_mode))
|| !host_integerp (TYPE_SIZE_UNIT (elem_type), 1))
{
error ("invalid element type for attribute %qs",
IDENTIFIER_POINTER (name));
return NULL_TREE;
}
/* Sanity check the vector size and element type consistency. */
vec_bytes = tree_low_cst (rep_size, 1);
if (vec_bytes % tree_low_cst (TYPE_SIZE_UNIT (elem_type), 1))
{
error ("vector size not an integral multiple of component size");
return NULL;
}
if (vec_bytes == 0)
{
error ("zero vector size");
return NULL;
}
vec_units = vec_bytes / tree_low_cst (TYPE_SIZE_UNIT (elem_type), 1);
if (vec_units & (vec_units - 1))
{
error ("number of components of the vector not a power of two");
return NULL_TREE;
}
/* Build the vector type and replace. */
*node = build_vector_type (elem_type, vec_units);
rep_name = TYPE_NAME (rep_type);
if (TREE_CODE (rep_name) == TYPE_DECL)
rep_name = DECL_NAME (rep_name);
TYPE_NAME (*node) = rep_name;
TYPE_REPRESENTATIVE_ARRAY (*node) = rep_type;
return NULL_TREE;
}
/* ----------------------------------------------------------------------- * /* ----------------------------------------------------------------------- *
* BUILTIN FUNCTIONS * * BUILTIN FUNCTIONS *
* ----------------------------------------------------------------------- */ * ----------------------------------------------------------------------- */
......
2009-09-25 Olivier Hainque <hainque@adacore.com>
* gnat.dg/sse_nolib.adb: New testcase.
2009-09-25 Revital Eres <ERES@il.ibm.com> 2009-09-25 Revital Eres <ERES@il.ibm.com>
* gcc.target/powerpc/vsx-vectorize-8.c: New test. * gcc.target/powerpc/vsx-vectorize-8.c: New test.
......
-- { dg-do run { target i?86-*-* x86_64-*-* } }
-- { dg-options "-O1 -msse" }
with Ada.Unchecked_Conversion;
procedure SSE_Nolib is
-- Base vector type definitions
package SSE_Types is
VECTOR_ALIGN : constant := 16;
VECTOR_BYTES : constant := 16;
type m128 is private;
private
type m128 is array (1 .. 4) of Float;
for m128'Alignment use VECTOR_ALIGN;
pragma Machine_Attribute (m128, "vector_type");
pragma Machine_Attribute (m128, "may_alias");
end SSE_Types;
use SSE_Types;
-- Core operations
function mm_add_ss (A, B : m128) return m128;
pragma Import (Intrinsic, mm_add_ss, "__builtin_ia32_addss");
-- User views / conversions or overlays
type Vf32_View is array (1 .. 4) of Float;
for Vf32_View'Alignment use VECTOR_ALIGN;
function To_m128 is new Ada.Unchecked_Conversion (Vf32_View, m128);
function To_m128 is new Ada.Unchecked_Conversion (m128, Vf32_View);
X, Y, Z : M128;
Vz : Vf32_View;
for Vz'Address use Z'Address;
begin
X := To_m128 ((1.0, 1.0, 2.0, 2.0));
Y := To_m128 ((2.0, 2.0, 1.0, 1.0));
Z := mm_add_ss (X, Y);
if Vz /= (3.0, 1.0, 2.0, 2.0) then
raise Program_Error;
end if;
end SSE_Nolib;
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