d: Fix error: aggregate value used where floating point was expected

Casting from vector to static array is permitted, and the frontend
generates a reinterpret cast, but casting back the other way resulted in
an error.  This has been fixed to be properly handled in the code
generation pass of VectorExp, and the conversion for lvalue and rvalue
handling done in convert_expr and convert_for_rvalue respectively.

	PR d/106139

gcc/d/ChangeLog:

	* d-convert.cc (convert_expr): Handle casting from array to vector.
	(convert_for_rvalue): Rewrite vector to array casts of the same
	element type into a constructor.
	(convert_for_assignment): Return calling convert_for_rvalue.
	* expr.cc (ExprVisitor::visit (VectorExp *)): Handle generating a
	vector expression from a static array.
	* toir.cc (IRVisitor::visit (ReturnStatement *)): Call
	convert_for_rvalue on return value.

gcc/testsuite/ChangeLog:

	* gdc.dg/pr106139a.d: New test.
	* gdc.dg/pr106139b.d: New test.
	* gdc.dg/pr106139c.d: New test.
	* gdc.dg/pr106139d.d: New test.

(cherry picked from commit 329bef49da)
This commit is contained in:
Iain Buclaw 2022-06-29 21:52:39 +02:00
parent 6c175b3d17
commit 32dfb075ad
7 changed files with 178 additions and 3 deletions

View File

@ -502,6 +502,15 @@ convert_expr (tree exp, Type *etype, Type *totype)
gcc_assert (totype->size () == etype->size ());
result = build_vconvert (build_ctype (totype), exp);
}
else if (tbtype->ty == TY::Tvector && tbtype->size () == ebtype->size ())
{
/* Allow casting from array to vector as if its an unaligned load. */
tree type = build_ctype (totype);
tree unaligned_type = build_variant_type_copy (type);
SET_TYPE_ALIGN (unaligned_type, 1 * BITS_PER_UNIT);
TYPE_USER_ALIGN (unaligned_type) = 1;
result = convert (type, build_vconvert (unaligned_type, exp));
}
else
{
error ("cannot cast expression of type %qs to type %qs",
@ -643,6 +652,39 @@ convert_for_rvalue (tree expr, Type *etype, Type *totype)
result = convert (build_ctype (tbtype), result);
}
if (tbtype->ty == TY::Tsarray
&& ebtype->ty == TY::Tsarray
&& tbtype->nextOf ()->ty == ebtype->nextOf ()->ty
&& INDIRECT_REF_P (expr)
&& CONVERT_EXPR_CODE_P (TREE_CODE (TREE_OPERAND (expr, 0)))
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (expr, 0), 0)) == ADDR_EXPR)
{
/* If expression is a vector that was casted to an array either by
explicit type cast or by taking the vector's `.array' value, strip the
reinterpret cast and build a constructor instead. */
tree ptr = TREE_OPERAND (TREE_OPERAND (expr, 0), 0);
if (VECTOR_TYPE_P (TREE_TYPE (TREE_TYPE (ptr))))
{
/* Rewrite: `*(Array *)&vector'
into: `{ vector[0], vector[1], ... }' */
tree array = d_save_expr (TREE_OPERAND (ptr, 0));
array = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (expr), array);
uinteger_t dim = tbtype->isTypeSArray ()->dim->toUInteger ();
vec <constructor_elt, va_gc> *elms = NULL;
for (uinteger_t i = 0; i < dim; i++)
{
tree index = size_int (i);
tree value = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (array)),
array, index, NULL_TREE, NULL_TREE);
CONSTRUCTOR_APPEND_ELT (elms, index, value);
}
return build_constructor (build_ctype (totype), elms);
}
}
return result ? result : convert_expr (expr, etype, totype);
}
@ -703,7 +745,7 @@ convert_for_assignment (tree expr, Type *etype, Type *totype)
return expr;
}
return convert_expr (expr, etype, totype);
return convert_for_rvalue (expr, etype, totype);
}
/* Return a TREE representation of EXPR converted to represent

View File

@ -2932,14 +2932,13 @@ public:
void visit (VectorExp *e)
{
tree type = build_ctype (e->type);
/* First handle array literal expressions. */
if (e->e1->op == EXP::arrayLiteral)
{
ArrayLiteralExp *ale = e->e1->isArrayLiteralExp ();
vec <constructor_elt, va_gc> *elms = NULL;
bool constant_p = true;
tree type = build_ctype (e->type);
vec_safe_reserve (elms, ale->elements->length);
for (size_t i = 0; i < ale->elements->length; i++)
@ -2959,9 +2958,16 @@ public:
else
this->result_ = build_constructor (type, elms);
}
else if (e->e1->type->toBasetype ()->ty == TY::Tsarray)
{
/* Build a vector representation from a static array. */
this->result_ = convert_expr (build_expr (e->e1, this->constp_),
e->e1->type, e->type);
}
else
{
/* Build constructor from single value. */
tree type = build_ctype (e->type);
tree value = d_convert (TREE_TYPE (type),
build_expr (e->e1, this->constp_, true));
this->result_ = build_vector_from_val (type, value);

View File

@ -1022,6 +1022,7 @@ public:
/* Generate: (<retval> = expr, return <retval>); */
tree expr = build_expr_dtor (s->exp);
tree init = stabilize_expr (&expr);
expr = convert_for_rvalue (expr, s->exp->type, type);
expr = build_assign (INIT_EXPR, this->func_->shidden, expr);
add_stmt (compound_expr (init, expr));
}

View File

@ -0,0 +1,36 @@
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106139
// { dg-do compile }
alias A = int[4];
static if (__traits(compiles, __vector(A))):
A vector2array(__vector(A) v)
{
return cast(A)v;
}
void vector2array(ref A a, __vector(A) v)
{
a = cast(A)v;
}
__vector(A) array2vector(A a)
{
return cast(__vector(A)) a;
}
void array2vector(ref __vector(A) v, A a)
{
v = cast(__vector(A))a;
}
A vector2array_array(__vector(A) v)
{
return v.array;
}
void vector2array_array(ref A a, __vector(A) v)
{
a = v.array;
}

View File

@ -0,0 +1,36 @@
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106139
// { dg-do compile }
alias A = float[4];
static if (__traits(compiles, __vector(A))):
A vector2array(__vector(A) v)
{
return cast(A)v;
}
void vector2array(ref A a, __vector(A) v)
{
a = cast(A)v;
}
__vector(A) array2vector(A a)
{
return cast(__vector(A)) a;
}
void array2vector(ref __vector(A) v, A a)
{
v = cast(__vector(A))a;
}
A vector2array_array(__vector(A) v)
{
return v.array;
}
void vector2array_array(ref A a, __vector(A) v)
{
a = v.array;
}

View File

@ -0,0 +1,27 @@
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106139
// { dg-do compile }
alias V = int[4];
alias A = float[4];
static if (__traits(compiles, __vector(V))):
A vector2array(__vector(V) v)
{
return cast(A)v;
}
void vector2array(ref A a, __vector(V) v)
{
a = cast(A)v;
}
__vector(V) array2vector(A a)
{
return cast(__vector(V)) a;
}
void array2vector(ref __vector(V) v, A a)
{
v = cast(__vector(V))a;
}

View File

@ -0,0 +1,27 @@
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106139
// { dg-do compile }
alias V = float[4];
alias A = int[4];
static if (__traits(compiles, __vector(V))):
A vector2array(__vector(V) v)
{
return cast(A)v;
}
void vector2array(ref A a, __vector(V) v)
{
a = cast(A)v;
}
__vector(V) array2vector(A a)
{
return cast(__vector(V)) a;
}
void array2vector(ref __vector(V) v, A a)
{
v = cast(__vector(V))a;
}