258 lines
3.6 KiB
C
258 lines
3.6 KiB
C
|
#include "gc.h"
|
||
|
|
||
|
void
|
||
|
noretval(int n)
|
||
|
{
|
||
|
|
||
|
if(n & 1) {
|
||
|
gins(ANOP, Z, Z);
|
||
|
p->to.type = D_REG;
|
||
|
p->to.reg = REGRET;
|
||
|
}
|
||
|
if(n & 2) {
|
||
|
gins(ANOP, Z, Z);
|
||
|
p->to.type = D_FREG;
|
||
|
p->to.reg = FREGRET;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* calculate addressability as follows
|
||
|
* CONST ==> 20 $value
|
||
|
* NAME ==> 10 name
|
||
|
* REGISTER ==> 11 register
|
||
|
* INDREG ==> 12 *[(reg)+offset]
|
||
|
* &10 ==> 2 $name
|
||
|
* ADD(2, 20) ==> 2 $name+offset
|
||
|
* ADD(3, 20) ==> 3 $(reg)+offset
|
||
|
* &12 ==> 3 $(reg)+offset
|
||
|
* *11 ==> 11 ??
|
||
|
* *2 ==> 10 name
|
||
|
* *3 ==> 12 *(reg)+offset
|
||
|
* calculate complexity (number of registers)
|
||
|
*/
|
||
|
void
|
||
|
xcom(Node *n)
|
||
|
{
|
||
|
Node *l, *r;
|
||
|
int v, nr;
|
||
|
|
||
|
if(n == Z)
|
||
|
return;
|
||
|
l = n->left;
|
||
|
r = n->right;
|
||
|
n->addable = 0;
|
||
|
n->complex = 0;
|
||
|
switch(n->op) {
|
||
|
case OCONST:
|
||
|
n->addable = 20;
|
||
|
return;
|
||
|
|
||
|
case OREGISTER:
|
||
|
n->addable = 11;
|
||
|
return;
|
||
|
|
||
|
case OINDREG:
|
||
|
n->addable = 12;
|
||
|
return;
|
||
|
|
||
|
case ONAME:
|
||
|
n->addable = 10;
|
||
|
return;
|
||
|
|
||
|
case OADDR:
|
||
|
xcom(l);
|
||
|
if(l->addable == 10)
|
||
|
n->addable = 2;
|
||
|
if(l->addable == 12)
|
||
|
n->addable = 3;
|
||
|
break;
|
||
|
|
||
|
case OIND:
|
||
|
xcom(l);
|
||
|
if(l->addable == 11)
|
||
|
n->addable = 12;
|
||
|
if(l->addable == 3)
|
||
|
n->addable = 12;
|
||
|
if(l->addable == 2)
|
||
|
n->addable = 10;
|
||
|
break;
|
||
|
|
||
|
case OADD:
|
||
|
xcom(l);
|
||
|
xcom(r);
|
||
|
if(l->addable == 20) {
|
||
|
if(r->addable == 2)
|
||
|
n->addable = 2;
|
||
|
if(r->addable == 3)
|
||
|
n->addable = 3;
|
||
|
}
|
||
|
if(r->addable == 20) {
|
||
|
if(l->addable == 2)
|
||
|
n->addable = 2;
|
||
|
if(l->addable == 3)
|
||
|
n->addable = 3;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case OASMUL:
|
||
|
case OASLMUL:
|
||
|
xcom(l);
|
||
|
xcom(r);
|
||
|
v = vlog(r);
|
||
|
if(v >= 0) {
|
||
|
n->op = OASASHL;
|
||
|
r->vconst = v;
|
||
|
r->type = types[TINT];
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case OMUL:
|
||
|
case OLMUL:
|
||
|
xcom(l);
|
||
|
xcom(r);
|
||
|
v = vlog(r);
|
||
|
if(v >= 0) {
|
||
|
n->op = OASHL;
|
||
|
r->vconst = v;
|
||
|
r->type = types[TINT];
|
||
|
}
|
||
|
v = vlog(l);
|
||
|
if(v >= 0) {
|
||
|
n->op = OASHL;
|
||
|
n->left = r;
|
||
|
n->right = l;
|
||
|
r = l;
|
||
|
l = n->left;
|
||
|
r->vconst = v;
|
||
|
r->type = types[TINT];
|
||
|
simplifyshift(n);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case OASLDIV:
|
||
|
xcom(l);
|
||
|
xcom(r);
|
||
|
v = vlog(r);
|
||
|
if(v >= 0) {
|
||
|
n->op = OASLSHR;
|
||
|
r->vconst = v;
|
||
|
r->type = types[TINT];
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case OLDIV:
|
||
|
xcom(l);
|
||
|
xcom(r);
|
||
|
v = vlog(r);
|
||
|
if(v >= 0) {
|
||
|
n->op = OLSHR;
|
||
|
r->vconst = v;
|
||
|
r->type = types[TINT];
|
||
|
simplifyshift(n);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case OASLMOD:
|
||
|
xcom(l);
|
||
|
xcom(r);
|
||
|
v = vlog(r);
|
||
|
if(v >= 0) {
|
||
|
n->op = OASAND;
|
||
|
r->vconst--;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case OLMOD:
|
||
|
xcom(l);
|
||
|
xcom(r);
|
||
|
v = vlog(r);
|
||
|
if(v >= 0) {
|
||
|
n->op = OAND;
|
||
|
r->vconst--;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case OLSHR:
|
||
|
case OASHL:
|
||
|
case OASHR:
|
||
|
xcom(l);
|
||
|
xcom(r);
|
||
|
simplifyshift(n);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
if(l != Z)
|
||
|
xcom(l);
|
||
|
if(r != Z)
|
||
|
xcom(r);
|
||
|
break;
|
||
|
}
|
||
|
if(n->addable >= 10)
|
||
|
return;
|
||
|
if(l != Z)
|
||
|
n->complex = l->complex;
|
||
|
if(r != Z) {
|
||
|
nr = 1;
|
||
|
if(r->type != T && typev[r->type->etype] || n->type != T && typev[n->type->etype]) {
|
||
|
nr = 2;
|
||
|
if(n->op == OMUL || n->op == OLMUL)
|
||
|
nr += 3;
|
||
|
}
|
||
|
if(r->complex == n->complex)
|
||
|
n->complex = r->complex+nr;
|
||
|
else
|
||
|
if(r->complex > n->complex)
|
||
|
n->complex = r->complex;
|
||
|
}
|
||
|
if(n->complex == 0){
|
||
|
n->complex++;
|
||
|
if(n->type != T && typev[n->type->etype])
|
||
|
n->complex++;
|
||
|
}
|
||
|
|
||
|
if(com64(n))
|
||
|
return;
|
||
|
|
||
|
switch(n->op) {
|
||
|
|
||
|
case OFUNC:
|
||
|
n->complex = FNX;
|
||
|
break;
|
||
|
|
||
|
case OEQ:
|
||
|
case ONE:
|
||
|
case OLE:
|
||
|
case OLT:
|
||
|
case OGE:
|
||
|
case OGT:
|
||
|
case OHI:
|
||
|
case OHS:
|
||
|
case OLO:
|
||
|
case OLS:
|
||
|
/*
|
||
|
* immediate operators, make const on right
|
||
|
*/
|
||
|
if(l->op == OCONST) {
|
||
|
n->left = r;
|
||
|
n->right = l;
|
||
|
n->op = invrel[relindex(n->op)];
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case OADD:
|
||
|
case OXOR:
|
||
|
case OAND:
|
||
|
case OOR:
|
||
|
/*
|
||
|
* immediate operators, make const on right
|
||
|
*/
|
||
|
if(l->op == OCONST) {
|
||
|
n->left = r;
|
||
|
n->right = l;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|