Skip to content

Commit

Permalink
Merge pull request #4151 from WalterBright/unionexp3
Browse files Browse the repository at this point in the history
more UnionExp interface work
  • Loading branch information
9rnsr committed Nov 19, 2014
2 parents 91ba90b + cad39f8 commit 48049ea
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 58 deletions.
112 changes: 66 additions & 46 deletions src/constfold.c
Expand Up @@ -411,7 +411,6 @@ UnionExp Div(Type *type, Expression *e1, Expression *e2)
if (n2 == 0)
{
e2->error("divide by 0");
e2 = new IntegerExp(loc, 1, e2->type);
n2 = 1;
}
if (e1->type->isunsigned() || e2->type->isunsigned())
Expand Down Expand Up @@ -467,7 +466,6 @@ UnionExp Mod(Type *type, Expression *e1, Expression *e2)
if (n2 == 0)
{
e2->error("divide by 0");
e2 = new IntegerExp(loc, 1, e2->type);
n2 = 1;
}
if (n2 == -1 && !type->isunsigned())
Expand All @@ -476,13 +474,11 @@ UnionExp Mod(Type *type, Expression *e1, Expression *e2)
if (n1 == 0xFFFFFFFF80000000ULL && type->toBasetype()->ty != Tint64)
{
e2->error("integer overflow: int.min % -1");
e2 = new IntegerExp(loc, 1, e2->type);
n2 = 1;
}
else if (n1 == 0x8000000000000000LL) // long.min % -1
{
e2->error("integer overflow: long.min % -1");
e2 = new IntegerExp(loc, 1, e2->type);
n2 = 1;
}
}
Expand All @@ -503,8 +499,6 @@ UnionExp Pow(Type *type, Expression *e1, Expression *e2)
// Handle integer power operations.
if (e2->type->isintegral())
{
Expression * r;
Expression * v;
dinteger_t n = e2->toInteger();
bool neg;

Expand All @@ -523,32 +517,44 @@ UnionExp Pow(Type *type, Expression *e1, Expression *e2)
else
neg = false;

UnionExp ur, uv;
if (e1->type->iscomplex())
{
r = new ComplexExp(loc, e1->toComplex(), e1->type);
v = new ComplexExp(loc, complex_t(1.0, 0.0), e1->type);
new(&ur) ComplexExp(loc, e1->toComplex(), e1->type);
new(&uv) ComplexExp(loc, complex_t(1.0, 0.0), e1->type);
}
else if (e1->type->isfloating())
{
r = new RealExp(loc, e1->toReal(), e1->type);
v = new RealExp(loc, ldouble(1.0), e1->type);
new(&ur) RealExp(loc, e1->toReal(), e1->type);
new(&uv) RealExp(loc, ldouble(1.0), e1->type);
}
else
{
r = new IntegerExp(loc, e1->toInteger(), e1->type);
v = new IntegerExp(loc, 1, e1->type);
new(&ur) IntegerExp(loc, e1->toInteger(), e1->type);
new(&uv) IntegerExp(loc, 1, e1->type);
}

Expression* r = ur.exp();
Expression* v = uv.exp();
while (n != 0)
{
if (n & 1)
v = Mul(v->type, v, r).copy();
{
// v = v * r;
uv = Mul(v->type, v, r);
}
n >>= 1;
r = Mul(r->type, r, r).copy();
// r = r * r
ur = Mul(r->type, r, r);
}

if (neg)
v = Div(v->type, new RealExp(loc, ldouble(1.0), v->type), v).copy();
{
// ue = 1.0 / v
UnionExp one;
new(&one) RealExp(loc, ldouble(1.0), v->type);
uv = Div(v->type, one.exp(), v);
}

if (type->iscomplex())
new(&ue) ComplexExp(loc, v->toComplex(), type);
Expand All @@ -559,7 +565,7 @@ UnionExp Pow(Type *type, Expression *e1, Expression *e2)
}
else if (e2->type->isfloating())
{
// x ^^ y for x < 0 and y not an integer is not defined
// x ^^ y for x < 0 and y not an integer is not defined; so set result as NaN
if (e1->toReal() < 0.0)
{
new(&ue) RealExp(loc, Port::ldbl_nan, type);
Expand Down Expand Up @@ -1277,8 +1283,9 @@ UnionExp Cast(Type *type, Type *to, Expression *e1)
for (size_t i = 0; i < sd->fields.dim; i++)
{
VarDeclaration *v = sd->fields[i];
Expression *exp = new IntegerExp(0);
ue = Cast(v->type, v->type, exp);
UnionExp zero;
new(&zero) IntegerExp(0);
ue = Cast(v->type, v->type, zero.exp());
if (ue.exp()->op == TOKcantexp)
return ue;
elements->push(ue.exp()->copy());
Expand All @@ -1296,46 +1303,46 @@ UnionExp Cast(Type *type, Type *to, Expression *e1)
}


Expression *ArrayLength(Type *type, Expression *e1)
UnionExp ArrayLength(Type *type, Expression *e1)
{
Expression *e;
UnionExp ue;
Loc loc = e1->loc;

if (e1->op == TOKstring)
{
StringExp *es1 = (StringExp *)e1;

e = new IntegerExp(loc, es1->len, type);
new(&ue) IntegerExp(loc, es1->len, type);
}
else if (e1->op == TOKarrayliteral)
{
ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
size_t dim;
size_t dim = ale->elements ? ale->elements->dim : 0;

dim = ale->elements ? ale->elements->dim : 0;
e = new IntegerExp(loc, dim, type);
new(&ue) IntegerExp(loc, dim, type);
}
else if (e1->op == TOKassocarrayliteral)
{
AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e1;
size_t dim = ale->keys->dim;

e = new IntegerExp(loc, dim, type);
new(&ue) IntegerExp(loc, dim, type);
}
else if (e1->type->toBasetype()->ty == Tsarray)
{
e = ((TypeSArray *)e1->type->toBasetype())->dim;
Expression *e = ((TypeSArray *)e1->type->toBasetype())->dim;
memcpy(&ue, e, e->size);
}
else
e = CTFEExp::cantexp;
return e;
new(&ue) CTFEExp(TOKcantexp);
return ue;
}

/* Also return TOKcantexp if this fails
*/
Expression *Index(Type *type, Expression *e1, Expression *e2)
UnionExp Index(Type *type, Expression *e1, Expression *e2)
{
Expression *e = CTFEExp::cantexp;
UnionExp ue;
Loc loc = e1->loc;

//printf("Index(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
Expand All @@ -1348,11 +1355,11 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
if (i >= es1->len)
{
e1->error("string index %llu is out of bounds [0 .. %llu]", i, (ulonglong)es1->len);
e = new ErrorExp();
new(&ue) ErrorExp();
}
else
{
e = new IntegerExp(loc, es1->charAt(i), type);
new(&ue) IntegerExp(loc, es1->charAt(i), type);
}
}
else if (e1->type->toBasetype()->ty == Tsarray && e2->op == TOKint64)
Expand All @@ -1364,17 +1371,21 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
if (i >= length)
{
e1->error("array index %llu is out of bounds %s[0 .. %llu]", i, e1->toChars(), length);
e = new ErrorExp();
new(&ue) ErrorExp();
}
else if (e1->op == TOKarrayliteral)
{
ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
e = (*ale->elements)[(size_t)i];
Expression *e = (*ale->elements)[(size_t)i];
e->type = type;
e->loc = loc;
if (hasSideEffect(e))
e = CTFEExp::cantexp;
new(&ue) CTFEExp(TOKcantexp);
else
memcpy(&ue, e, e->size);
}
else
new(&ue) CTFEExp(TOKcantexp);
}
else if (e1->type->toBasetype()->ty == Tarray && e2->op == TOKint64)
{
Expand All @@ -1386,17 +1397,21 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
if (i >= ale->elements->dim)
{
e1->error("array index %llu is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim);
e = new ErrorExp();
new(&ue) ErrorExp();
}
else
{
e = (*ale->elements)[(size_t)i];
Expression *e = (*ale->elements)[(size_t)i];
e->type = type;
e->loc = loc;
if (hasSideEffect(e))
e = CTFEExp::cantexp;
new(&ue) CTFEExp(TOKcantexp);
else
memcpy(&ue, e, e->size);
}
}
else
new(&ue) CTFEExp(TOKcantexp);
}
else if (e1->op == TOKassocarrayliteral)
{
Expand All @@ -1407,21 +1422,26 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
{
i--;
Expression *ekey = (*ae->keys)[i];
Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2).copy();
if (CTFEExp::isCantExp(ex))
return ex;
if (ex->isBool(true))
ue = Equal(TOKequal, Type::tbool, ekey, e2);
if (CTFEExp::isCantExp(ue.exp()))
return ue;
if (ue.exp()->isBool(true))
{
e = (*ae->values)[i];
Expression *e = (*ae->values)[i];
e->type = type;
e->loc = loc;
if (hasSideEffect(e))
e = CTFEExp::cantexp;
break;
new(&ue) CTFEExp(TOKcantexp);
else
memcpy(&ue, e, e->size);
return ue;;
}
}
new(&ue) CTFEExp(TOKcantexp);
}
return e;
else
new(&ue) CTFEExp(TOKcantexp);
return ue;
}

/* Also return TOKcantexp if this fails
Expand Down
6 changes: 3 additions & 3 deletions src/ctfeexpr.c
Expand Up @@ -378,13 +378,13 @@ Expression *paintTypeOntoLiteral(Type *type, Expression *lit)
else if (lit->op == TOKarrayliteral)
{
e = new SliceExp(lit->loc, lit,
new IntegerExp(Loc(), 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit));
new IntegerExp(Loc(), 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit).copy());
}
else if (lit->op == TOKstring)
{
// For strings, we need to introduce another level of indirection
e = new SliceExp(lit->loc, lit,
new IntegerExp(Loc(), 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit));
new IntegerExp(Loc(), 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit).copy());
}
else if (lit->op == TOKassocarrayliteral)
{
Expand Down Expand Up @@ -725,7 +725,7 @@ Expression *pointerArithmetic(Loc loc, TOK op, Type *type,
}
else
{
dollar = ArrayLength(Type::tsize_t, agg1);
dollar = ArrayLength(Type::tsize_t, agg1).copy();
assert(!CTFEExp::isCantExp(dollar));
}
dinteger_t len = dollar->toInteger();
Expand Down
6 changes: 3 additions & 3 deletions src/expression.h
Expand Up @@ -1571,6 +1571,7 @@ struct UnionExp
Expression *copy()
{
Expression *e = exp();
//if (e->size > sizeof(u)) printf("%s\n", Token::toChars(e->op));
assert(e->size <= sizeof(u));
return e->copy();
}
Expand Down Expand Up @@ -1609,8 +1610,7 @@ UnionExp Com(Type *type, Expression *e1);
UnionExp Not(Type *type, Expression *e1);
UnionExp Bool(Type *type, Expression *e1);
UnionExp Cast(Type *type, Type *to, Expression *e1);
Expression *Castx(Type *type, Type *to, Expression *e1);
Expression *ArrayLength(Type *type, Expression *e1);
UnionExp ArrayLength(Type *type, Expression *e1);
UnionExp Ptr(Type *type, Expression *e1);

UnionExp Add(Type *type, Expression *e1, Expression *e2);
Expand All @@ -1625,7 +1625,7 @@ UnionExp Ushr(Type *type, Expression *e1, Expression *e2);
UnionExp And(Type *type, Expression *e1, Expression *e2);
UnionExp Or(Type *type, Expression *e1, Expression *e2);
UnionExp Xor(Type *type, Expression *e1, Expression *e2);
Expression *Index(Type *type, Expression *e1, Expression *e2);
UnionExp Index(Type *type, Expression *e1, Expression *e2);
UnionExp Cat(Type *type, Expression *e1, Expression *e2);

UnionExp Equal(TOK op, Type *type, Expression *e1, Expression *e2);
Expand Down
8 changes: 4 additions & 4 deletions src/interpret.c
Expand Up @@ -3572,7 +3572,7 @@ class Interpreter : public Visitor
// Convert into arr[0..arr.length] = e2
e1 = new SliceExp(e->loc, e1,
new IntegerExp(e->loc, 0, Type::tsize_t),
ArrayLength(Type::tsize_t, e1));
ArrayLength(Type::tsize_t, e1).copy());
e1->type = e->type;
}
}
Expand Down Expand Up @@ -5513,7 +5513,7 @@ class Interpreter : public Visitor
}
if (agg->op == TOKarrayliteral || agg->op == TOKstring)
{
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
dinteger_t len = ArrayLength(Type::tsize_t, agg).exp()->toInteger();
//Type *pointee = ((TypePointer *)agg->type)->next;
if ((sinteger_t)(indx + ofs) < 0 || (indx+ofs) > len)
{
Expand Down Expand Up @@ -5734,7 +5734,7 @@ class Interpreter : public Visitor
return;
}
assert(agg->op == TOKarrayliteral || agg->op == TOKstring);
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
dinteger_t len = ArrayLength(Type::tsize_t, agg).exp()->toInteger();
//Type *pointee = ((TypePointer *)agg->type)->next;
if (iupr > (len + 1) || iupr < ilwr)
{
Expand Down Expand Up @@ -6285,7 +6285,7 @@ class Interpreter : public Visitor
if ((ie->e1->op == TOKarrayliteral || ie->e1->op == TOKstring) &&
ie->e2->op == TOKint64)
{
Expression *dollar = ArrayLength(Type::tsize_t, ie->e1);
Expression *dollar = ArrayLength(Type::tsize_t, ie->e1).copy();
dinteger_t len = dollar->toInteger();
dinteger_t indx = ie->e2->toInteger();
assert(indx >=0 && indx <= len); // invalid pointer
Expand Down
4 changes: 2 additions & 2 deletions src/optimize.c
Expand Up @@ -989,7 +989,7 @@ Expression *Expression_optimize(Expression *e, int result, bool keepLvalue)
if (e->e1->op == TOKstring || e->e1->op == TOKarrayliteral || e->e1->op == TOKassocarrayliteral ||
e->e1->type->toBasetype()->ty == Tsarray)
{
ret = ArrayLength(e->type, e->e1);
ret = ArrayLength(e->type, e->e1).copy();
}
}

Expand Down Expand Up @@ -1085,7 +1085,7 @@ Expression *Expression_optimize(Expression *e, int result, bool keepLvalue)
e->e2 = e->e2->optimize(WANTvalue);
if (keepLvalue)
return;
ret = Index(e->type, ex, e->e2);
ret = Index(e->type, ex, e->e2).copy();
if (CTFEExp::isCantExp(ret))
ret = e;
}
Expand Down

0 comments on commit 48049ea

Please sign in to comment.