d/dmd: Merge upstream dmd 19b1454b5

Backports fixes for many ICEs that occurred when using the vector .array
property in both CTFE and code generation passes.

Fixes https://gcc.gnu.org/PR88957

Reviewed-on: https://github.com/dlang/dmd/pull/9438

gcc/d/ChangeLog:

2019-03-13  Iain Buclaw  <ibuclaw@gdcproject.org>

	PR d/88957
	* expr.cc (ExprVisitor::visit(VectorArrayExp)): New override.

gcc/testsuite/ChangeLog:

2019-03-13  Iain Buclaw  <ibuclaw@gdcproject.org>

	PR d/88957
	* gdc.dg/pr88957.d: New test.
	* gdc.dg/simd.d: Add new vector tests.

From-SVN: r269627
This commit is contained in:
Iain Buclaw 2019-03-12 23:10:49 +00:00 committed by Iain Buclaw
parent 035f5b9e0b
commit b9da027866
17 changed files with 437 additions and 15 deletions

View File

@ -1,3 +1,8 @@
2019-03-13 Iain Buclaw <ibuclaw@gdcproject.org>
PR d/88957
* expr.cc (ExprVisitor::visit(VectorArrayExp)): New override.
2019-03-12 Iain Buclaw <ibuclaw@gdcproject.org>
PR d/87866

View File

@ -1,4 +1,4 @@
7423993c996ed9f73d6ba6d58f625ad3c778ca1d
19b1454b5ca7b1036ea5fde197d91d4a7d05c0a5
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View File

@ -517,7 +517,7 @@ Expression *resolveSlice(Expression *e, UnionExp *pue)
uinteger_t resolveArrayLength(Expression *e)
{
if (e->op == TOKvector)
e = ((VectorExp *)e)->e1;
return ((VectorExp *)e)->dim;
if (e->op == TOKnull)
return 0;

View File

@ -2920,7 +2920,6 @@ public:
case TOKneg: *pue = Neg(e->type, e1); break;
case TOKtilde: *pue = Com(e->type, e1); break;
case TOKnot: *pue = Not(e->type, e1); break;
case TOKvector: result = e; return; // do nothing
default: assert(0);
}
result = (*pue).exp();
@ -3839,8 +3838,6 @@ public:
Expression *aggregate;
dinteger_t firstIndex;
if (e1->op == TOKvector)
e1 = ((VectorExp *)e1)->e1;
if (e1->op == TOKslice)
{
// ------------------------------
@ -4893,6 +4890,87 @@ public:
result = pue->exp();
}
/**
* Interpret the vector expression as an array literal.
* Params:
* pue = non-null pointer to temporary storage that can be used to store the return value
* e = Expression to interpret
* Returns:
* resulting array literal or 'e' if unable to interpret
*/
static Expression *interpretVectorToArray(UnionExp *pue, VectorExp *e)
{
if (e->e1->op == TOKarrayliteral)
return (ArrayLiteralExp *)e->e1;
if (e->e1->op == TOKint64 || e->e1->op == TOKfloat64)
{
// Convert literal __vector(int) -> __vector([array])
Expressions *elements = new Expressions();
elements->setDim(e->dim);
for (size_t i = 0; i < elements->dim; i++)
(*elements)[i] = copyLiteral(e->e1).copy();
TypeSArray *type = NULL;
if (e->type->ty == Tvector)
{
TypeVector *tv = (TypeVector *)e->type;
if (tv->basetype->ty == Tsarray)
type = (TypeSArray *)tv->basetype;
}
else if (e->type->ty == Tsarray)
type = (TypeSArray *)e->type;
assert(type);
new(pue) ArrayLiteralExp(e->loc, type, elements);
ArrayLiteralExp *ale = (ArrayLiteralExp *)pue->exp();
ale->ownedByCtfe = OWNEDctfe;
return ale;
}
return e;
}
void visit(VectorExp *e)
{
if (e->ownedByCtfe >= OWNEDctfe) // We've already interpreted all the elements
{
result = e;
return;
}
Expression *e1 = interpret(pue, e->e1, istate);
assert(e1);
if (exceptionOrCant(e1))
return;
if (e1->op != TOKarrayliteral && e1->op != TOKint64 && e1->op != TOKfloat64)
{
e->error("`%s` cannot be evaluated at compile time", e->toChars());
result = CTFEExp::cantexp;
return;
}
if (e1 == pue->exp())
e1 = pue->copy();
new(pue) VectorExp(e->loc, e1, e->to);
VectorExp *ve = (VectorExp *)pue->exp();
ve->type = e->type;
ve->dim = e->dim;
ve->ownedByCtfe = OWNEDctfe;
result = ve;
}
void visit(VectorArrayExp *e)
{
Expression *e1 = interpret(pue, e->e1, istate);
assert(e1);
if (exceptionOrCant(e1))
return;
if (e1->op == TOKvector)
{
VectorExp *ve = (VectorExp *)e1;
result = interpretVectorToArray(pue, ve);
if (result->op != TOKvector)
return;
}
e->error("`%s` cannot be evaluated at compile time", e->toChars());
result = CTFEExp::cantexp;
}
void visit(DelegatePtrExp *e)
{
Expression *e1 = interpret(pue, e->e1, istate);
@ -4984,12 +5062,17 @@ public:
return false;
}
if (e1->op == TOKvector)
e1 = ((VectorExp *)e1)->e1;
{
UnionExp ue;
e1 = interpretVectorToArray(&ue, (VectorExp *)e1);
e1 = (e1 == ue.exp()) ? ue.copy() : e1;
}
// Set the $ variable, and find the array literal to modify
if (e1->op != TOKarrayliteral &&
e1->op != TOKstring &&
e1->op != TOKslice)
e1->op != TOKslice &&
e1->op != TOKvector)
{
e->error("cannot determine length of %s at compile time",
e->e1->toChars());
@ -5239,9 +5322,15 @@ public:
return;
}
if (e1->op == TOKvector)
{
e1 = interpretVectorToArray(pue, (VectorExp *)e1);
e1 = (e1 == pue->exp()) ? pue->copy() : e1;
}
/* Set the $ variable
*/
if (e1->op != TOKarrayliteral && e1->op != TOKstring && e1->op != TOKnull && e1->op != TOKslice)
if (e1->op != TOKarrayliteral && e1->op != TOKstring && e1->op != TOKnull && e1->op != TOKslice && e1->op != TOKvector)
{
e->error("cannot determine length of %s at compile time", e1->toChars());
result = CTFEExp::cantexp;
@ -5715,7 +5804,7 @@ public:
if (exceptionOrCant(e1))
return;
assert(e1->op == TOKvector);
e1 = ((VectorExp *)e1)->e1;
e1 = interpretVectorToArray(pue, (VectorExp *)e1);
}
if (e->to->ty == Tarray && e1->op == TOKslice)
{
@ -6165,6 +6254,18 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
return ex;
aae->type = toBuiltinAAType(aae->type);
}
else if (e->op == TOKvector)
{
VectorExp *ve = (VectorExp *)e;
ve->ownedByCtfe = OWNEDcode;
if (ve->e1->op == TOKarrayliteral)
{
ArrayLiteralExp *ale = (ArrayLiteralExp *)ve->e1;
ale->ownedByCtfe = OWNEDcode;
if (Expression *ex = scrubArray(loc, ale->elements))
return ex;
}
}
return e;
}
@ -6282,6 +6383,18 @@ Expression *scrubCacheValue(Expression *e)
if (Expression *ex = scrubArrayCache(aae->values))
return ex;
}
else if (e->op == TOKvector)
{
VectorExp *ve = (VectorExp *)e;
ve->ownedByCtfe = OWNEDcache;
if (ve->e1->op == TOKarrayliteral)
{
ArrayLiteralExp *ale = (ArrayLiteralExp *)ve->e1;
ale->ownedByCtfe = OWNEDcache;
if (Expression *ex = scrubArrayCache(ale->elements))
return ex;
}
}
return e;
}

View File

@ -5744,6 +5744,7 @@ VectorExp::VectorExp(Loc loc, Expression *e, Type *t)
assert(t->ty == Tvector);
to = (TypeVector *)t;
dim = ~0;
ownedByCtfe = OWNEDcode;
}
VectorExp *VectorExp::create(Loc loc, Expression *e, Type *t)
@ -5758,6 +5759,24 @@ Expression *VectorExp::syntaxCopy()
/************************************************************/
VectorArrayExp::VectorArrayExp(Loc loc, Expression *e1)
: UnaExp(loc, TOKvectorarray, sizeof(VectorExp), e1)
{
}
bool VectorArrayExp::isLvalue()
{
return e1->isLvalue();
}
Expression *VectorArrayExp::toLvalue(Scope *sc, Expression *e)
{
e1 = e1->toLvalue(sc, e);
return this;
}
/************************************************************/
SliceExp::SliceExp(Loc loc, Expression *e1, IntervalExp *ie)
: UnaExp(loc, TOKslice, sizeof(SliceExp), e1)
{

View File

@ -959,6 +959,7 @@ class VectorExp : public UnaExp
public:
TypeVector *to; // the target vector type before semantic()
unsigned dim; // number of elements in the vector
OwnedBy ownedByCtfe;
VectorExp(Loc loc, Expression *e, Type *t);
static VectorExp *create(Loc loc, Expression *e, Type *t);
@ -966,6 +967,15 @@ public:
void accept(Visitor *v) { v->visit(this); }
};
class VectorArrayExp : public UnaExp
{
public:
VectorArrayExp(Loc loc, Expression *e1);
bool isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
void accept(Visitor *v) { v->visit(this); }
};
class SliceExp : public UnaExp
{
public:
@ -1515,6 +1525,7 @@ private:
char addrexp [sizeof(AddrExp)];
char indexexp [sizeof(IndexExp)];
char sliceexp [sizeof(SliceExp)];
char vectorexp [sizeof(VectorExp)];
} u;
#if defined(__DMC__)
#pragma pack()

View File

@ -4299,6 +4299,25 @@ public:
result = e;
}
void visit(VectorArrayExp *e)
{
if (!e->type)
{
unaSemantic(e, sc);
e->e1 = resolveProperties(sc, e->e1);
if (e->e1->op == TOKerror)
{
result = e->e1;
return;
}
assert(e->e1->type->ty == Tvector);
TypeVector *tv = (TypeVector *)e->e1->type;
e->type = tv->basetype;
}
result = e;
}
void visit(SliceExp *exp)
{
if (exp->type)

View File

@ -2833,6 +2833,12 @@ public:
expToBuffer(e->e1, precedence[e->op]);
}
void visit(VectorArrayExp *e)
{
expToBuffer(e->e1, PREC_primary);
buf->writestring(".array");
}
void visit(SliceExp *e)
{
expToBuffer(e->e1, precedence[e->op]);

View File

@ -3766,8 +3766,8 @@ Expression *TypeVector::dotExp(Scope *sc, Expression *e, Identifier *ident, int
{
//e = e->castTo(sc, basetype);
// Keep lvalue-ness
e = e->copy();
e->type = basetype;
e = new VectorArrayExp(e->loc, e);
e = ::semantic(e, sc);
return e;
}
if (ident == Id::_init || ident == Id::offsetof || ident == Id::stringof || ident == Id::__xalignof)

View File

@ -7929,6 +7929,7 @@ PrecedenceInitializer::PrecedenceInitializer()
precedence[TOKdefault] = PREC_primary;
precedence[TOKoverloadset] = PREC_primary;
precedence[TOKvoid] = PREC_primary;
precedence[TOKvectorarray] = PREC_primary;
// post
precedence[TOKdotti] = PREC_primary;

View File

@ -472,4 +472,5 @@ TokenInitializer::TokenInitializer()
Token::tochars[TOKon_scope_success] = "scope(success)";
Token::tochars[TOKon_scope_failure] = "scope(failure)";
Token::tochars[TOKdelegateptr] = "delegateptr";
Token::tochars[TOKvectorarray] = "vectorarray";
}

View File

@ -179,6 +179,8 @@ enum TOK
TOKvoidexp,
TOKcantexp,
TOKvectorarray,
TOKMAX
};

View File

@ -226,6 +226,7 @@ class NotExp;
class DeleteExp;
class CastExp;
class VectorExp;
class VectorArrayExp;
class SliceExp;
class ArrayLengthExp;
class IntervalExp;
@ -517,6 +518,7 @@ public:
virtual void visit(DeleteExp *e) { visit((UnaExp *)e); }
virtual void visit(CastExp *e) { visit((UnaExp *)e); }
virtual void visit(VectorExp *e) { visit((UnaExp *)e); }
virtual void visit(VectorArrayExp *e) { visit((UnaExp *)e); }
virtual void visit(SliceExp *e) { visit((UnaExp *)e); }
virtual void visit(ArrayLengthExp *e) { visit((UnaExp *)e); }
virtual void visit(IntervalExp *e) { visit((Expression *)e); }

View File

@ -2992,6 +2992,14 @@ public:
}
}
/* Build a static array representation of a vector expression. */
void visit (VectorArrayExp *e)
{
this->result_ = convert_expr (build_expr (e->e1, this->constp_),
e->e1->type, e->type);
}
/* Build a static class literal, return its reference. */
void visit (ClassReferenceExp *e)

View File

@ -1,3 +1,9 @@
2019-03-13 Iain Buclaw <ibuclaw@gdcproject.org>
PR d/88957
* gdc.dg/pr88957.d: New test.
* gdc.dg/simd.d: Add new vector tests.
2019-03-12 Uroš Bizjak <ubizjak@gmail.com>
PR d/87824

View File

@ -0,0 +1,18 @@
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88957
// { dg-do compile }
// { dg-additional-options "-fsanitize=undefined" }
alias int4 = __vector(int[4]);
int fn(const int[4] x)
{
int sum = 0;
foreach (i; x) sum += i;
return sum;
}
void pr88957()
{
auto x = fn(int4.init.array);
auto y = fn(int4(2).array);
}

View File

@ -1108,7 +1108,6 @@ float bug8060(float x) {
}
/*****************************************/
/+
// https://issues.dlang.org/show_bug.cgi?id=9200
void bar9200(double[2] a)
@ -1130,7 +1129,6 @@ void test9200()
bar9200(a.array);
}
+/
/*****************************************/
// https://issues.dlang.org/show_bug.cgi?id=9304
@ -1686,7 +1684,6 @@ void test17720()
}
/*****************************************/
// https://issues.dlang.org/show_bug.cgi?id=17695
void test17695(__vector(ubyte[16]) a)
@ -1694,6 +1691,217 @@ void test17695(__vector(ubyte[16]) a)
auto b = -a;
}
/*****************************************/
// https://issues.dlang.org/show_bug.cgi?id=19223
int test19223a(const int[4] x)
{
int sum = 0;
foreach (i; x) sum += i;
return sum;
}
void test19223()
{
int4 v1 = int4.init;
assert(test19223a(v1.array) == 0);
assert(test19223a(int4.init.array) == 0);
}
/*****************************************/
// https://issues.dlang.org/show_bug.cgi?id=19224
float test19224(const float[4] val)
{
float sum = 0;
foreach (x; val) sum += x;
return sum;
}
enum x19224 = test19224(float4.init.array);
static assert(x19224 is float.nan);
enum y19224 = test19224(float4(1).array);
static assert(y19224 == 4);
/*****************************************/
// https://issues.dlang.org/show_bug.cgi?id=19607
int test19607a(const int[4] x)
{
int sum = 0;
foreach (i; x) sum += i;
return sum;
}
void test19607()
{
int4 v1 = 1;
assert(test19607a(v1.array) == 4);
assert(test19607a(int4(2).array) == 8);
}
/*****************************************/
// https://issues.dlang.org/show_bug.cgi?id=19627
enum int[4] fail19627 = cast(int[4])int4(0);
/*****************************************/
// https://issues.dlang.org/show_bug.cgi?id=19628
enum ice19628a = int4.init[0];
enum ice19628b = int4.init.array[0];
enum ice19628c = (cast(int[4])int4.init.array)[0];
enum ice19628d = (cast(int[4])int4.init)[0];
enum int4 v19628a = int4.init;
enum idx19628a = v19628a[0];
static assert(idx19628a == 0);
enum int[4] v19628b = int4.init.array;
enum idx19628b = v19628b[0];
static assert(idx19628b == 0);
enum int[4] v19628c = cast(int[4])int4.init.array;
enum idx19628c = v19628c[0];
static assert(idx19628c == 0);
enum int[4] v19628d = cast(int[4])int4.init;
enum idx19628d = v19628d[0];
static assert(idx19628d == 0);
immutable int4 v19628e = int4.init;
immutable idx19628e = v19628e[0];
static assert(idx19628e == 0);
immutable int[4] v19628f = int4.init.array;
immutable idx19628f = v19628f[0];
static assert(idx19628f == 0);
immutable int[4] v19628g = cast(int[4])int4.init.array;
immutable idx19628g = v19628g[0];
static assert(idx19628g == 0);
immutable idx19628h = v19628h[0];
immutable int[4] v19628h = cast(int[4])int4.init;
static assert(idx19628h == 0);
/*****************************************/
// https://issues.dlang.org/show_bug.cgi?id=19629
enum fail19629a = int4(0)[0];
enum fail19629b = int4(0).array[0];
enum fail19629c = (cast(int[4])int4(0).array)[0];
enum fail19628d = (cast(int[4])int4(0))[0];
enum int4 v19629a = int4(0);
enum idx19629a = v19629a[0];
static assert(idx19629a == 0);
enum int[4] v19629b = int4(0).array;
enum idx19629b = v19629b[0];
static assert(idx19629b == 0);
enum int[4] v19629c = cast(int[4])int4(0).array;
enum idx19629c = v19629c[0];
static assert(idx19629c == 0);
enum int[4] v19629d = cast(int[4])int4(0);
enum idx19629d = v19629d[0];
static assert(idx19629d == 0);
immutable int4 v19629e = int4(0);
immutable idx19629e = v19629e[0];
static assert(idx19629e == 0);
immutable int[4] v19629f = int4(0).array;
immutable idx19629f = v19629f[0];
static assert(idx19629f == 0);
immutable int[4] v19629g = cast(int[4])int4(0).array;
immutable idx19629g = v19629g[0];
static assert(idx19629g == 0);
immutable int[4] v19629h = cast(int[4])int4(0);
immutable idx19629h = v19629h[0];
static assert(idx19629h == 0);
/*****************************************/
// https://issues.dlang.org/show_bug.cgi?id=19630
enum fail19630a = int4.init[1..2];
enum fail19630b = int4.init.array[1..2];
enum fail19630c = (cast(int[4])int4.init.array)[1..2];
enum fail19630d = (cast(int[4])int4.init)[1..2];
enum fail19630e = int4(0)[1..2];
enum fail19630f = int4(0).array[1..2];
enum fail19630g = (cast(int[4])int4(0).array)[1..2];
enum fail19630h = (cast(int[4])int4(0))[1..2];
enum int4 v19630a = int4.init;
enum slice19630a = v19630a[1..2];
static assert(slice19630a == [0]);
enum int[4] v19630b = int4.init.array;
enum slice19630b = v19630b[1..2];
static assert(slice19630b == [0]);
enum int[4] v19630c = cast(int[4])int4.init.array;
enum slice19630c = v19630c[1..2];
static assert(slice19630c == [0]);
enum int[4] v19630d = cast(int[4])int4.init;
enum slice19630d = v19630d[1..2];
static assert(slice19630d == [0]);
enum int4 v19630e = int4(0);
enum slice19630e = v19630e[1..2];
static assert(slice19630e == [0]);
enum int[4] v19630f = int4(0).array;
enum slice19630f = v19630f[1..2];
static assert(slice19630f == [0]);
enum int[4] v19630g = cast(int[4])int4(0).array;
enum slice19630g = v19630g[1..2];
static assert(slice19630g == [0]);
enum int[4] v19630h = cast(int[4])int4(0);
enum slice19630h = v19630h[1..2];
static assert(slice19630h == [0]);
immutable int4 v19630i = int4.init;
immutable slice19630i = v19630i[1..2];
static assert(slice19630i == [0]);
immutable int[4] v19630j = int4.init.array;
immutable slice19630j = v19630j[1..2];
static assert(slice19630j == [0]);
immutable int[4] v19630k = cast(int[4])int4.init.array;
immutable slice19630k = v19630k[1..2];
static assert(slice19630k == [0]);
immutable int[4] v19630l = cast(int[4])int4.init;
immutable slice19630l = v19630l[1..2];
static assert(slice19630l == [0]);
immutable int4 v19630m = int4(0);
immutable slice19630m = v19630m[1..2];
static assert(slice19630m == [0]);
immutable int[4] v19630n = int4(0).array;
immutable slice19630n = v19630n[1..2];
static assert(slice19630n == [0]);
immutable int[4] v19630o = cast(int[4])int4(0).array;
immutable slice19630o = v19630o[1..2];
static assert(slice19630o == [0]);
immutable int[4] v19630p = cast(int[4])int4(0);
immutable slice19630p = v19630p[1..2];
static assert(slice19630p == [0]);
/*****************************************/
int main()
@ -1718,7 +1926,7 @@ int main()
test7414();
test7413();
test7413_2();
// test9200();
test9200();
test9304();
test9910();
test12852();
@ -1731,5 +1939,8 @@ int main()
testOPvecunsto();
test10447();
test19223();
test19607();
return 0;
}