Skip to content

Commit

Permalink
Merge pull request #5034 from 9rnsr/fix13652
Browse files Browse the repository at this point in the history
Issue 13652 - 2D Static Array Init produces wrong result (-m64/-m32)
  • Loading branch information
WalterBright committed Sep 4, 2015
2 parents 3edecbc + 83372fa commit 30c6741
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 93 deletions.
173 changes: 80 additions & 93 deletions src/e2ir.c
Expand Up @@ -1663,7 +1663,7 @@ elem *toElem(Expression *e, IRState *irs)
}

// Allocate array of dimensions on the stack
Symbol *sdata;
Symbol *sdata = NULL;
elem *earray = ExpressionsToStaticArray(ne->loc, ne->arguments, &sdata);

e = el_pair(TYdarray, el_long(TYsize_t, ne->arguments->dim), el_ptr(sdata));
Expand Down Expand Up @@ -2860,62 +2860,19 @@ elem *toElem(Expression *e, IRState *irs)
ae->e2->op == TOKarrayliteral)
{
ArrayLiteralExp *ale = (ArrayLiteralExp *)ae->e2;
size_t dim = ale->elements->dim;
if (dim == 0)
if (ale->elements->dim == 0)
{
// Eliminate _d_arrayliteralTX call in ae->e2.
e = e1;
goto Lret;
}

// TODO: This part is very similar to ExpressionsToStaticArray.

Type *tn = t1b->nextOf()->toBasetype();
if (tn->ty == Tvoid)
tn = Type::tuns8;
tym_t ty = totym(tn);

symbol *stmp = symbol_genauto(TYnptr);
e = e1;
e = addressElem(e, t1b);
e = el_bin(OPeq, TYnptr, el_var(stmp), e);

size_t esz = tn->size();
for (size_t i = 0; i < dim; )
else
{
Expression *en = (*ale->elements)[i];
size_t j = i + 1;
if (!postblit)
{
// If the elements are same literal and elaborate copy
// is not necessary, do memcpy.
while (j < dim && en->equals((*ale->elements)[j])) { j++; }
}
symbol *stmp = symbol_genauto(TYnptr);
e1 = addressElem(e1, t1b);
e1 = el_bin(OPeq, TYnptr, el_var(stmp), e1);

elem *e1 = el_var(stmp);
if (i > 0)
e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, i * esz));
elem *ex;
if (j == i + 1)
{
e1 = el_una(OPind, ty, e1);
if (tybasic(ty) == TYstruct)
e1->ET = Type_toCtype(tn);
ex = el_bin(OPeq, e1->Ety, e1, toElem(en, irs));
if (tybasic(ty) == TYstruct)
{
ex->Eoper = OPstreq;
ex->ET = Type_toCtype(tn);
}
}
else
{
assert(j - i >= 2);
elem *edim = el_long(TYsize_t, j - i);
ex = setArray(e1, edim, tn, toElem(en, irs), irs, ae->op);
}
e = el_combine(e, ex);
i = j;
// Eliminate _d_arrayliteralTX call in ae->e2.
e = ExpressionsToStaticArray(ale->loc, ale->elements, &stmp, 0);
e = el_combine(e1, e);
}
goto Lret;
}
Expand Down Expand Up @@ -4884,7 +4841,7 @@ elem *toElem(Expression *e, IRState *irs)
}
if (tb->ty == Tsarray && ale->elements && ale->elements->dim)
{
Symbol *sdata;
Symbol *sdata = NULL;
e = ExpressionsToStaticArray(ale->loc, ale->elements, &sdata);
e = el_combine(e, el_ptr(sdata));
}
Expand Down Expand Up @@ -5072,15 +5029,14 @@ elem *toElem(Expression *e, IRState *irs)
size_t dim = elems->dim;
assert(dim);

Type *tsarray = telem->sarrayOf(dim);;
symbol *stmp = symbol_genauto(Type_toCtype(tsarray));
Type *tsarray = telem->sarrayOf(dim);
targ_size_t szelem = telem->size();
::type *te = Type_toCtype(telem); // stmp[] element type
*psym = stmp;
::type *te = Type_toCtype(telem); // stmp[] element type

Elems eset;
eset.setDim(dim);
symbol *stmp = symbol_genauto(Type_toCtype(tsarray));
*psym = stmp;

elem *e = NULL;
for (size_t i = 0; i < dim; i++)
{
/* Generate: *(&stmp + i * szelem) = element[i]
Expand All @@ -5089,7 +5045,7 @@ elem *toElem(Expression *e, IRState *irs)
elem *ev = el_ptr(stmp);
ev = el_bin(OPadd, TYnptr, ev, el_long(TYsize_t, i * szelem));
ev = el_una(OPind, te->Tty, ev);
elem *eeq = el_bin(OPeq,te->Tty,ev,ep);
elem *eeq = el_bin(OPeq, te->Tty, ev, ep);

if (tybasic(te->Tty) == TYstruct)
{
Expand All @@ -5102,68 +5058,99 @@ elem *toElem(Expression *e, IRState *irs)
eeq->Ejty = eeq->Ety = TYstruct;
eeq->ET = te;
}
eset[i] = eeq;
e = el_combine(e, eeq);
}

return el_combines((void **)eset.tdata(), dim);
return e;
}

/*************************************************
* Allocate a static array, and initialize its members with
* exps[].
* Return the initialization expression, and the symbol for the static array in *psym.
*/
elem *ExpressionsToStaticArray(Loc loc, Expressions *exps, symbol **psym)
elem *ExpressionsToStaticArray(Loc loc, Expressions *exps, symbol **psym, size_t offset = 0)
{
// Create a static array of type telem[dim]
size_t dim = exps->dim;
assert(dim);

Elems elems;
elems.setDim(dim);
Type *telem = (*exps)[0]->type;
Type *tsarray = telem->sarrayOf(dim);
targ_size_t szelem = telem->size();
::type *te = Type_toCtype(telem); // stmp[] element type

Type *telem;
Type *tsarray;
symbol *stmp;
targ_size_t szelem;
::type *te; // stmp[] element type
if (!*psym)
{
Type *tsarray = telem->sarrayOf(dim);
*psym = symbol_genauto(Type_toCtype(tsarray));
offset = 0;
}
symbol *stmp = *psym;

for (size_t i = 0; i < dim; i++)
elem *e = NULL;
for (size_t i = 0; i < dim; )
{
Expression *el = (*exps)[i];
if (i == 0)
if (el->op == TOKarrayliteral &&
el->type->toBasetype()->ty == Tsarray)
{
telem = el->type;
szelem = telem->size();
te = Type_toCtype(telem);
ArrayLiteralExp *ale = (ArrayLiteralExp *)el;
if (ale->elements && ale->elements->dim)
{
elem *ex = ExpressionsToStaticArray(
ale->loc, ale->elements, &stmp, offset + i * szelem);
e = el_combine(e, ex);
}
i++;
continue;
}

tsarray = telem->sarrayOf(dim);
stmp = symbol_genauto(Type_toCtype(tsarray));
*psym = stmp;
size_t j = i + 1;
if (el->isConst() || el->op == TOKnull)
{
// If the trivial elements are same values, do memcpy.
while (j < dim)
{
Expression *en = (*exps)[j];
if (!el->equals(en))
break;
j++;
}
}

/* Generate: *(&stmp + i * szelem) = element[i]
*/
elem *ep = toElem(el, irs);
elem *ev = el_ptr(stmp);
ev = el_bin(OPadd, TYnptr, ev, el_long(TYsize_t, i * szelem));
ev = el_una(OPind, te->Tty, ev);
elem *eeq = el_bin(OPeq,te->Tty,ev,ep);
elem *ev = tybasic(stmp->Stype->Tty) == TYnptr ? el_var(stmp) : el_ptr(stmp);
ev = el_bin(OPadd, TYnptr, ev, el_long(TYsize_t, offset + i * szelem));

if (tybasic(te->Tty) == TYstruct)
elem *eeq;
if (j == i + 1)
{
eeq->Eoper = OPstreq;
eeq->ET = te;
ev = el_una(OPind, te->Tty, ev);
eeq = el_bin(OPeq, te->Tty, ev, ep);

if (tybasic(te->Tty) == TYstruct)
{
eeq->Eoper = OPstreq;
eeq->ET = te;
}
else if (tybasic(te->Tty) == TYarray)
{
eeq->Eoper = OPstreq;
eeq->Ejty = eeq->Ety = TYstruct;
eeq->ET = te;
}
}
else if (tybasic(te->Tty) == TYarray)
else
{
eeq->Eoper = OPstreq;
eeq->Ejty = eeq->Ety = TYstruct;
eeq->ET = te;
elem *edim = el_long(TYsize_t, j - i);
eeq = setArray(ev, edim, telem, ep, NULL, TOKblit);
}
elems[i] = eeq;
e = el_combine(e, eeq);
i = j;
}

return el_combines((void **)elems.tdata(), dim);
return e;
}

void visit(AssocArrayLiteralExp *aale)
Expand Down
69 changes: 69 additions & 0 deletions test/runnable/xtest46.d
Expand Up @@ -3529,6 +3529,74 @@ void test2356()
bar() = [];
}

/***************************************************/
// 13652

void test13652()
{
// reduced case
uint[9][5] arr =
[[0, 0, 0, 0, 1, 5, 8, 0, 7],
[0, 3, 8, 0, 2, 0, 0, 6, 0],
[0, 0, 7, 0, 6, 8, 9, 4, 0],
[0, 0, 0, 0, 0, 1, 2, 9, 0],
[9, 7, 0, 0, 0, 0, 0, 8, 3]];
assert(arr[0][0] == 0 && arr[0][1] == 0 && arr[0][2] == 0 &&
arr[0][3] == 0 && arr[0][4] == 1 && arr[0][5] == 5 &&
arr[0][6] == 8 && arr[0][7] == 0 && arr[0][8] == 7);
assert(arr[1][0] == 0 && arr[1][1] == 3 && arr[1][2] == 8 &&
arr[1][3] == 0 && arr[1][4] == 2 && arr[1][5] == 0 &&
arr[1][6] == 0 && arr[1][7] == 6 && arr[1][8] == 0);
assert(arr[2][0] == 0 && arr[2][1] == 0 && arr[2][2] == 7 &&
arr[2][3] == 0 && arr[2][4] == 6 && arr[2][5] == 8 &&
arr[2][6] == 9 && arr[2][7] == 4 && arr[2][8] == 0);
assert(arr[3][0] == 0 && arr[3][1] == 0 && arr[3][2] == 0 &&
arr[3][3] == 0 && arr[3][4] == 0 && arr[3][5] == 1 &&
arr[3][6] == 2 && arr[3][7] == 9 && arr[3][8] == 0);
assert(arr[4][0] == 9 && arr[4][1] == 7 && arr[4][2] == 0 &&
arr[4][3] == 0 && arr[4][4] == 0 && arr[4][5] == 0 &&
arr[4][6] == 0 && arr[4][7] == 8 && arr[4][8] == 3);

// original case
uint[9][9] tbl =
[[0, 0, 0, 0, 1, 5, 8, 0, 7],
[0, 3, 8, 0, 2, 0, 0, 6, 0],
[0, 0, 7, 0, 6, 8, 9, 4, 0],
[0, 0, 0, 0, 0, 1, 2, 9, 0],
[9, 7, 0, 0, 0, 0, 0, 8, 3],
[0, 2, 1, 6, 0, 0, 0, 0, 0],
[0, 6, 9, 5, 4, 0, 3, 0, 0],
[0, 4, 0, 0, 8, 0, 6, 5, 0],
[2, 0, 5, 9, 3, 0, 0, 0, 0]];
assert(tbl[0][0] == 0 && tbl[0][1] == 0 && tbl[0][2] == 0 &&
tbl[0][3] == 0 && tbl[0][4] == 1 && tbl[0][5] == 5 &&
tbl[0][6] == 8 && tbl[0][7] == 0 && tbl[0][8] == 7);
assert(tbl[1][0] == 0 && tbl[1][1] == 3 && tbl[1][2] == 8 &&
tbl[1][3] == 0 && tbl[1][4] == 2 && tbl[1][5] == 0 &&
tbl[1][6] == 0 && tbl[1][7] == 6 && tbl[1][8] == 0);
assert(tbl[2][0] == 0 && tbl[2][1] == 0 && tbl[2][2] == 7 &&
tbl[2][3] == 0 && tbl[2][4] == 6 && tbl[2][5] == 8 &&
tbl[2][6] == 9 && tbl[2][7] == 4 && tbl[2][8] == 0);
assert(tbl[3][0] == 0 && tbl[3][1] == 0 && tbl[3][2] == 0 &&
tbl[3][3] == 0 && tbl[3][4] == 0 && tbl[3][5] == 1 &&
tbl[3][6] == 2 && tbl[3][7] == 9 && tbl[3][8] == 0);
assert(tbl[4][0] == 9 && tbl[4][1] == 7 && tbl[4][2] == 0 &&
tbl[4][3] == 0 && tbl[4][4] == 0 && tbl[4][5] == 0 &&
tbl[4][6] == 0 && tbl[4][7] == 8 && tbl[4][8] == 3);
assert(tbl[5][0] == 0 && tbl[5][1] == 2 && tbl[5][2] == 1 &&
tbl[5][3] == 6 && tbl[5][4] == 0 && tbl[5][5] == 0 &&
tbl[5][6] == 0 && tbl[5][7] == 0 && tbl[5][8] == 0);
assert(tbl[6][0] == 0 && tbl[6][1] == 6 && tbl[6][2] == 9 &&
tbl[6][3] == 5 && tbl[6][4] == 4 && tbl[6][5] == 0 &&
tbl[6][6] == 3 && tbl[6][7] == 0 && tbl[6][8] == 0);
assert(tbl[7][0] == 0 && tbl[7][1] == 4 && tbl[7][2] == 0 &&
tbl[7][3] == 0 && tbl[7][4] == 8 && tbl[7][5] == 0 &&
tbl[7][6] == 6 && tbl[7][7] == 5 && tbl[7][8] == 0);
assert(tbl[8][0] == 2 && tbl[8][1] == 0 && tbl[8][2] == 5 &&
tbl[8][3] == 9 && tbl[8][4] == 3 && tbl[8][5] == 0 &&
tbl[8][6] == 0 && tbl[8][6] == 0 && tbl[8][8] == 0);
}

/***************************************************/
// 11238

Expand Down Expand Up @@ -7689,6 +7757,7 @@ int main()
test148();
test149();
test2356();
test13652();
test11238();
test2540();
test14348();
Expand Down

0 comments on commit 30c6741

Please sign in to comment.