#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 t; 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 OASLMUL: case OASMUL: xcom(l); xcom(r); t = vlog(r); if(t >= 0) { n->op = OASASHL; r->vconst = t; r->type = types[TINT]; } break; case OMUL: case OLMUL: if(typev[n->type->etype]){ /* try to lift 32->64 bit cast */ if(typev[l->type->etype] && l->op == OCAST && typeil[l->left->type->etype] && typeu[n->type->etype] == typeu[l->left->type->etype]) l = l->left; if(typev[r->type->etype] && r->op == OCAST && typeil[r->left->type->etype] && typeu[n->type->etype] == typeu[r->left->type->etype]) r = r->left; if(typeil[l->type->etype] && typeil[r->type->etype]){ n->left = l; n->right = r; xcom(l); xcom(r); break; } l = n->left; r = n->right; } xcom(l); xcom(r); t = vlog(r); if(t >= 0) { n->op = OASHL; r->vconst = t; r->type = types[TINT]; } t = vlog(l); if(t >= 0) { n->op = OASHL; n->left = r; n->right = l; r = l; r->vconst = t; r->type = types[TINT]; } break; case OASLDIV: xcom(l); xcom(r); t = vlog(r); if(t >= 0) { n->op = OASLSHR; r->vconst = t; r->type = types[TINT]; } break; case OLDIV: xcom(l); xcom(r); t = vlog(r); if(t >= 0) { n->op = OLSHR; r->vconst = t; r->type = types[TINT]; } break; case OASLMOD: xcom(l); xcom(r); t = vlog(r); if(t >= 0) { n->op = OASAND; r->vconst--; } break; case OLMOD: xcom(l); xcom(r); t = vlog(r); if(t >= 0) { n->op = OAND; r->vconst--; } break; case OOR: xcom(l); xcom(r); if(typeil[n->type->etype]) rolor(n); break; default: if(l != Z) xcom(l); if(r != Z) xcom(r); break; } if(n->addable >= 10) return; l = n->left; r = n->right; if(l != Z) n->complex = l->complex; if(r != Z) { if(r->complex == n->complex) n->complex = r->complex+1; else if(r->complex > n->complex) n->complex = r->complex; } if(n->complex == 0) n->complex++; if(com64(n)) return; switch(n->op) { case OFUNC: n->complex = FNX; break; case OADD: case OXOR: case OAND: case OOR: case OEQ: case ONE: /* * immediate operators, make const on right */ if(l->op == OCONST) { n->left = r; n->right = l; } break; } }