Skip to content

Commit

Permalink
make array.length work with op=
Browse files Browse the repository at this point in the history
  • Loading branch information
Walter Bright committed Nov 12, 2009
1 parent 597640a commit c1fa00a
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 73 deletions.
103 changes: 32 additions & 71 deletions src/e2ir.c
Expand Up @@ -1926,11 +1926,9 @@ elem *AssertExp::toElem(IRState *irs)
}

elem *PostExp::toElem(IRState *irs)
{ elem *e;
elem *einc;

e = e1->toElem(irs);
einc = e2->toElem(irs);
{
elem *e = e1->toElem(irs);
elem *einc = e2->toElem(irs);
e = el_bin((op == TOKplusplus) ? OPpostinc : OPpostdec,
e->Ety,e,einc);
el_setLoc(e,loc);
Expand Down Expand Up @@ -2449,10 +2447,7 @@ elem *RemoveExp::toElem(IRState *irs)
*/

elem *AssignExp::toElem(IRState *irs)
{ elem *e;
IndexExp *ae;
int r;

{
//printf("AssignExp::toElem('%s')\n", toChars());
Type *t1b = e1->type->toBasetype();

Expand All @@ -2463,45 +2458,25 @@ elem *AssignExp::toElem(IRState *irs)
// _d_arraysetlength(e2, sizeelem, &ale->e1);

ArrayLengthExp *ale = (ArrayLengthExp *)e1;
elem *p1;
elem *p2;
elem *p3;
elem *ep;
Type *t1;

p1 = e2->toElem(irs);
p3 = ale->e1->toElem(irs);
elem *p1 = e2->toElem(irs);
elem *p3 = ale->e1->toElem(irs);
p3 = addressElem(p3, NULL);
t1 = ale->e1->type->toBasetype();
Type *t1 = ale->e1->type->toBasetype();

#if 1
// call _d_arraysetlengthT(ti, e2, &ale->e1);
p2 = t1->getTypeInfo(NULL)->toElem(irs);
ep = el_params(p3, p1, p2, NULL); // c function
r = t1->nextOf()->isZeroInit() ? RTLSYM_ARRAYSETLENGTHT : RTLSYM_ARRAYSETLENGTHIT;
#else
if (t1->next->isZeroInit())
{ p2 = t1->getTypeInfo(NULL)->toElem(irs);
ep = el_params(p3, p1, p2, NULL); // c function
r = RTLSYM_ARRAYSETLENGTHT;
}
else
{
p2 = el_long(TYint, t1->next->size());
ep = el_params(p3, p2, p1, NULL); // c function
Expression *init = t1->next->defaultInit();
ep = el_param(el_long(TYint, init->type->size()), ep);
elem *ei = init->toElem(irs);
ep = el_param(ei, ep);
r = RTLSYM_ARRAYSETLENGTH3;
}
#endif
elem *p2 = t1->getTypeInfo(NULL)->toElem(irs);
elem *ep = el_params(p3, p1, p2, NULL); // c function
int r = t1->nextOf()->isZeroInit() ? RTLSYM_ARRAYSETLENGTHT : RTLSYM_ARRAYSETLENGTHIT;

e = el_bin(OPcall, type->totym(), el_var(rtlsym[r]), ep);
elem *e = el_bin(OPcall, type->totym(), el_var(rtlsym[r]), ep);
el_setLoc(e, loc);
return e;
}

elem *e;
IndexExp *ae;

// Look for array[]=n
if (e1->op == TOKslice)
{
Expand Down Expand Up @@ -2687,16 +2662,13 @@ elem *AssignExp::toElem(IRState *irs)
/* It's array1[]=array2[]
* which is a memcpy
*/
elem *eto;
elem *efrom;
elem *esize;
elem *ep;

eto = e1->toElem(irs);
efrom = e2->toElem(irs);
elem *eto = e1->toElem(irs);
elem *efrom = e2->toElem(irs);

unsigned size = t1->nextOf()->size();
esize = el_long(TYint, size);
elem *esize = el_long(TYint, size);

/* Determine if we need to do postblit
*/
Expand All @@ -2707,14 +2679,11 @@ elem *AssignExp::toElem(IRState *irs)
assert(e2->type->ty != Tpointer);

if (!postblit && !global.params.useArrayBounds)
{ elem *epto;
elem *epfr;
elem *elen;
elem *ex;

ex = el_same(&eto);
{
elem *ex = el_same(&eto);

// Determine if elen is a constant
elem *elen;
if (eto->Eoper == OPpair &&
eto->E1->Eoper == OPconst)
{
Expand All @@ -2727,8 +2696,8 @@ elem *AssignExp::toElem(IRState *irs)
}

esize = el_bin(OPmul, TYint, elen, esize);
epto = array_toPtr(e1->type, ex);
epfr = array_toPtr(e2->type, efrom);
elem *epto = array_toPtr(e1->type, ex);
elem *epfr = array_toPtr(e2->type, efrom);
#if 1
// memcpy() is faster, so if we can't beat 'em, join 'em
e = el_params(esize, epfr, epto, NULL);
Expand Down Expand Up @@ -4236,28 +4205,20 @@ elem *ArrayLengthExp::toElem(IRState *irs)
}

elem *SliceExp::toElem(IRState *irs)
{ elem *e;
Type *t1;

{
//printf("SliceExp::toElem()\n");
t1 = e1->type->toBasetype();
e = e1->toElem(irs);
Type *t1 = e1->type->toBasetype();
elem *e = e1->toElem(irs);
if (lwr)
{ elem *elwr;
elem *elwr2;
elem *eupr;
elem *eptr;
elem *einit;
int sz;

einit = resolveLengthVar(lengthVar, &e, t1);
{
elem *einit = resolveLengthVar(lengthVar, &e, t1);

sz = t1->nextOf()->size();
int sz = t1->nextOf()->size();

elwr = lwr->toElem(irs);
eupr = upr->toElem(irs);
elem *elwr = lwr->toElem(irs);
elem *eupr = upr->toElem(irs);

elwr2 = el_same(&elwr);
elem *elwr2 = el_same(&elwr);

// Create an array reference where:
// length is (upr - lwr)
Expand Down Expand Up @@ -4325,7 +4286,7 @@ elem *SliceExp::toElem(IRState *irs)
}
}

eptr = array_toPtr(e1->type, e);
elem *eptr = array_toPtr(e1->type, e);

elem *elength = el_bin(OPmin, TYint, eupr, elwr2);
eptr = el_bin(OPadd, TYnptr, eptr, el_bin(OPmul, TYint, el_copytree(elwr2), el_long(TYint, sz)));
Expand Down
124 changes: 122 additions & 2 deletions src/expression.c
Expand Up @@ -5190,6 +5190,13 @@ Expression *BinExp::commonSemanticAssign(Scope *sc)
if (e)
return e;

if (e1->op == TOKarraylength)
{
e = ArrayLengthExp::rewriteOpAssign(this);
e = e->semantic(sc);
return e;
}

if (e1->op == TOKslice)
{ // T[] op= ...
typeCombine(sc);
Expand Down Expand Up @@ -5228,6 +5235,13 @@ Expression *BinExp::commonSemanticAssignIntegral(Scope *sc)
if (e)
return e;

if (e1->op == TOKarraylength)
{
e = ArrayLengthExp::rewriteOpAssign(this);
e = e->semantic(sc);
return e;
}

if (e1->op == TOKslice)
{ // T[] op= ...
typeCombine(sc);
Expand Down Expand Up @@ -7902,8 +7916,7 @@ ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1)
}

Expression *ArrayLengthExp::semantic(Scope *sc)
{ Expression *e;

{
#if LOGSEMANTIC
printf("ArrayLengthExp::semantic('%s')\n", toChars());
#endif
Expand All @@ -7917,6 +7930,64 @@ Expression *ArrayLengthExp::semantic(Scope *sc)
return this;
}

Expression *opAssignToOp(Loc loc, enum TOK op, Expression *e1, Expression *e2)
{ Expression *e;

switch (op)
{
case TOKaddass: e = new AddExp(loc, e1, e2); break;
case TOKminass: e = new MinExp(loc, e1, e2); break;
case TOKmulass: e = new MulExp(loc, e1, e2); break;
case TOKdivass: e = new DivExp(loc, e1, e2); break;
case TOKmodass: e = new ModExp(loc, e1, e2); break;
case TOKandass: e = new AndExp(loc, e1, e2); break;
case TOKorass: e = new OrExp (loc, e1, e2); break;
case TOKxorass: e = new XorExp(loc, e1, e2); break;
case TOKshlass: e = new ShlExp(loc, e1, e2); break;
case TOKshrass: e = new ShrExp(loc, e1, e2); break;
case TOKushrass: e = new UshrExp(loc, e1, e2); break;
default: assert(0);
}
return e;
}

/*********************
* Rewrite:
* array.length op= e2
* as:
* array.length = array.length op e2
* or:
* auto tmp = &array;
* (*tmp).length = (*tmp).length op e2
*/

Expression *ArrayLengthExp::rewriteOpAssign(BinExp *exp)
{ Expression *e;

assert(exp->e1->op == TOKarraylength);
ArrayLengthExp *ale = (ArrayLengthExp *)exp->e1;
if (ale->e1->op == TOKvar)
{ e = opAssignToOp(exp->loc, exp->op, ale, exp->e2);
e = new AssignExp(exp->loc, ale->syntaxCopy(), e);
}
else
{
/* auto tmp = &array;
* (*tmp).length = (*tmp).length op e2
*/
Identifier *id = Lexer::uniqueId("__arraylength");
ExpInitializer *ei = new ExpInitializer(ale->loc, new AddrExp(ale->loc, ale->e1));
VarDeclaration *tmp = new VarDeclaration(ale->loc, ale->e1->type->pointerTo(), id, ei);

Expression *e1 = new ArrayLengthExp(ale->loc, new PtrExp(ale->loc, new VarExp(ale->loc, tmp)));
Expression *elvalue = e1->syntaxCopy();
e = opAssignToOp(exp->loc, exp->op, e1, exp->e2);
e = new AssignExp(exp->loc, elvalue, e);
e = new CommaExp(exp->loc, new DeclarationExp(ale->loc, tmp), e);
}
return e;
}

void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
expToCBuffer(buf, hgs, e1, PREC_primary);
Expand Down Expand Up @@ -8644,6 +8715,13 @@ Expression *AddAssignExp::semantic(Scope *sc)
Type *tb1 = e1->type->toBasetype();
Type *tb2 = e2->type->toBasetype();

if (e1->op == TOKarraylength)
{
e = ArrayLengthExp::rewriteOpAssign(this);
e = e->semantic(sc);
return e;
}

if (e1->op == TOKslice)
{
typeCombine(sc);
Expand Down Expand Up @@ -8748,6 +8826,13 @@ Expression *MinAssignExp::semantic(Scope *sc)
if (e)
return e;

if (e1->op == TOKarraylength)
{
e = ArrayLengthExp::rewriteOpAssign(this);
e = e->semantic(sc);
return e;
}

if (e1->op == TOKslice)
{ // T[] -= ...
typeCombine(sc);
Expand Down Expand Up @@ -8852,6 +8937,13 @@ Expression *MulAssignExp::semantic(Scope *sc)
if (e)
return e;

if (e1->op == TOKarraylength)
{
e = ArrayLengthExp::rewriteOpAssign(this);
e = e->semantic(sc);
return e;
}

if (e1->op == TOKslice)
{ // T[] -= ...
typeCombine(sc);
Expand Down Expand Up @@ -8916,6 +9008,13 @@ Expression *DivAssignExp::semantic(Scope *sc)
if (e)
return e;

if (e1->op == TOKarraylength)
{
e = ArrayLengthExp::rewriteOpAssign(this);
e = e->semantic(sc);
return e;
}

if (e1->op == TOKslice)
{ // T[] -= ...
typeCombine(sc);
Expand Down Expand Up @@ -8997,6 +9096,13 @@ Expression *ShlAssignExp::semantic(Scope *sc)
if (e)
return e;

if (e1->op == TOKarraylength)
{
e = ArrayLengthExp::rewriteOpAssign(this);
e = e->semantic(sc);
return e;
}

e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
Expand Down Expand Up @@ -9025,6 +9131,13 @@ Expression *ShrAssignExp::semantic(Scope *sc)
if (e)
return e;

if (e1->op == TOKarraylength)
{
e = ArrayLengthExp::rewriteOpAssign(this);
e = e->semantic(sc);
return e;
}

e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
Expand Down Expand Up @@ -9053,6 +9166,13 @@ Expression *UshrAssignExp::semantic(Scope *sc)
if (e)
return e;

if (e1->op == TOKarraylength)
{
e = ArrayLengthExp::rewriteOpAssign(this);
e = e->semantic(sc);
return e;
}

e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
Expand Down
2 changes: 2 additions & 0 deletions src/expression.h
Expand Up @@ -1070,6 +1070,8 @@ struct ArrayLengthExp : UnaExp
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
elem *toElem(IRState *irs);

static Expression *rewriteOpAssign(BinExp *exp);
};

// e1[a0,a1,a2,a3,...]
Expand Down

0 comments on commit c1fa00a

Please sign in to comment.