I got to wondering why the code was so complicated and realized it was coded in a backwards fashion. It worked but sheez, it could be better. I had a look at the code for a couple of other compilers and ended up re-writing it to be much simpler. No need for all the fancy factoring and division. Part of the problem now might be that it uses more registers. The way I had it written I think IIRC it interspersed multiplies and adds so registers could be reused. The way it is now it does a whole bunch of multiplies placing the results in different registers, then does a whole bunch of adds.
The way it was written, it calculated the amount to multiply by taking the total size and dividing it by the product of all the sizes that made up the type. It's difficult to explain so I'll post some of the code.
This bit of code determined the values of the all indicies by parsing the expressions inside the []. It collected up all the expressions into expression nodes (rnode). A thing to note is it found the total size of the array at that point in the indexing and stored it in a size array sz[].
Code:
for (na = 0; na < 20 && p; na++) {
sz[na] = p->size;
if (lastst== openbr) {
NextToken();
expression(&rnode[na]);
if (rnode[na]==nullptr) {
dfs.printf("rnode[] is null\n");
goto j1;
}
needpunc(closebr,9);
}
else {
rnode[na] = makeinode(en_icon, 0);
}
p = p->GetBtp();
}
na--;
if (na>19) {
error(ERR_TOOMANYDIMEN);
This bit of code then took the sizes determined above based on the indicies, and created multiply nodes that ultimately resulted in the generation of code. Note it has to calculate multiplication factors by dividing one size by the subsequent one.
Code:
default:
fact[0] = sz[na];
for (ii = 1,nn = na-1; nn >= 0; nn--, ii++) {
fact[ii] = sz[nn]/sz[nn+1];
}
for (ii = 0; ii < na; ii++) {
cnode[ii] = makeinode(en_icon,size/MultiplyFact(ii+1,fact)); // MultiplyFact multiples all the factors together
cnode[ii]->constflag = TRUE;
cnode[ii]->isUnsigned = tp1->isUnsigned;
qnode[ii] = makenode(en_mulu,rnode[ii],cnode[ii]);
qnode[ii]->constflag = rnode[ii]->constflag;
}
cnode[ii] = makeinode(en_icon,fact[0]);
cnode[ii]->constflag = TRUE;
cnode[ii]->isUnsigned = tp1->isUnsigned;
qnode[ii] = makenode(en_mulu,rnode[ii],cnode[ii]);
qnode[ii]->constflag = rnode[ii]->constflag;
This last little bit linked all the qnodes together with adds.
Code:
for (ii = 1; ii <= na; ii++) {
ep2 = makenode(en_add,ep2,qnode[ii]);
ep2->constflag = ep2->p[0]->constflag && qnode[ii]->constflag;
ep2->isUnsigned = ep2->p[0]->isUnsigned && qnode[ii]->isUnsigned;
}