174a4d8c2SCharles.Forsyth #include "gc.h"
274a4d8c2SCharles.Forsyth
374a4d8c2SCharles.Forsyth void
codgen(Node * n,Node * nn)474a4d8c2SCharles.Forsyth codgen(Node *n, Node *nn)
574a4d8c2SCharles.Forsyth {
674a4d8c2SCharles.Forsyth Prog *sp;
774a4d8c2SCharles.Forsyth Node *n1, nod, nod1;
874a4d8c2SCharles.Forsyth
974a4d8c2SCharles.Forsyth cursafe = 0;
1074a4d8c2SCharles.Forsyth curarg = 0;
1174a4d8c2SCharles.Forsyth maxargsafe = 0;
1274a4d8c2SCharles.Forsyth
1374a4d8c2SCharles.Forsyth /*
1474a4d8c2SCharles.Forsyth * isolate name
1574a4d8c2SCharles.Forsyth */
1674a4d8c2SCharles.Forsyth for(n1 = nn;; n1 = n1->left) {
1774a4d8c2SCharles.Forsyth if(n1 == Z) {
1874a4d8c2SCharles.Forsyth diag(nn, "cant find function name");
1974a4d8c2SCharles.Forsyth return;
2074a4d8c2SCharles.Forsyth }
2174a4d8c2SCharles.Forsyth if(n1->op == ONAME)
2274a4d8c2SCharles.Forsyth break;
2374a4d8c2SCharles.Forsyth }
2474a4d8c2SCharles.Forsyth nearln = nn->lineno;
2574a4d8c2SCharles.Forsyth gpseudo(ATEXT, n1->sym, nodconst(stkoff));
2674a4d8c2SCharles.Forsyth sp = p;
2774a4d8c2SCharles.Forsyth
2874a4d8c2SCharles.Forsyth /*
2974a4d8c2SCharles.Forsyth * isolate first argument
3074a4d8c2SCharles.Forsyth */
3174a4d8c2SCharles.Forsyth if(REGARG) {
3274a4d8c2SCharles.Forsyth if(typesu[thisfn->link->etype]) {
3374a4d8c2SCharles.Forsyth nod1 = *nodret->left;
3474a4d8c2SCharles.Forsyth nodreg(&nod, &nod1, REGARG);
3574a4d8c2SCharles.Forsyth gopcode(OAS, &nod, Z, &nod1);
3674a4d8c2SCharles.Forsyth } else
3774a4d8c2SCharles.Forsyth if(firstarg && typechlp[firstargtype->etype]) {
3874a4d8c2SCharles.Forsyth nod1 = *nodret->left;
3974a4d8c2SCharles.Forsyth nod1.sym = firstarg;
4074a4d8c2SCharles.Forsyth nod1.type = firstargtype;
4174a4d8c2SCharles.Forsyth nod1.xoffset = align(0, firstargtype, Aarg1);
4274a4d8c2SCharles.Forsyth nod1.etype = firstargtype->etype;
4374a4d8c2SCharles.Forsyth nodreg(&nod, &nod1, REGARG);
4474a4d8c2SCharles.Forsyth gopcode(OAS, &nod, Z, &nod1);
4574a4d8c2SCharles.Forsyth }
4674a4d8c2SCharles.Forsyth }
4774a4d8c2SCharles.Forsyth
4874a4d8c2SCharles.Forsyth retok = 0;
4974a4d8c2SCharles.Forsyth gen(n);
5074a4d8c2SCharles.Forsyth if(!retok)
5174a4d8c2SCharles.Forsyth if(thisfn->link->etype != TVOID)
5274a4d8c2SCharles.Forsyth warn(Z, "no return at end of function: %s", n1->sym->name);
5374a4d8c2SCharles.Forsyth noretval(3);
5474a4d8c2SCharles.Forsyth gbranch(ORETURN);
5574a4d8c2SCharles.Forsyth
5674a4d8c2SCharles.Forsyth if(!debug['N'] || debug['R'] || debug['P'])
5774a4d8c2SCharles.Forsyth regopt(sp);
5874a4d8c2SCharles.Forsyth
5974a4d8c2SCharles.Forsyth sp->to.offset += maxargsafe;
6074a4d8c2SCharles.Forsyth }
6174a4d8c2SCharles.Forsyth
6274a4d8c2SCharles.Forsyth void
gen(Node * n)6374a4d8c2SCharles.Forsyth gen(Node *n)
6474a4d8c2SCharles.Forsyth {
6574a4d8c2SCharles.Forsyth Node *l, nod;
6674a4d8c2SCharles.Forsyth Prog *sp, *spc, *spb;
6774a4d8c2SCharles.Forsyth Case *cn;
6874a4d8c2SCharles.Forsyth long sbc, scc;
6974a4d8c2SCharles.Forsyth int o;
7074a4d8c2SCharles.Forsyth
7174a4d8c2SCharles.Forsyth loop:
7274a4d8c2SCharles.Forsyth if(n == Z)
7374a4d8c2SCharles.Forsyth return;
7474a4d8c2SCharles.Forsyth nearln = n->lineno;
7574a4d8c2SCharles.Forsyth o = n->op;
7674a4d8c2SCharles.Forsyth if(debug['G'])
7774a4d8c2SCharles.Forsyth if(o != OLIST)
7874a4d8c2SCharles.Forsyth print("%L %O\n", nearln, o);
7974a4d8c2SCharles.Forsyth
8074a4d8c2SCharles.Forsyth retok = 0;
8174a4d8c2SCharles.Forsyth switch(o) {
8274a4d8c2SCharles.Forsyth
8374a4d8c2SCharles.Forsyth default:
8474a4d8c2SCharles.Forsyth complex(n);
8574a4d8c2SCharles.Forsyth cgen(n, Z);
8674a4d8c2SCharles.Forsyth break;
8774a4d8c2SCharles.Forsyth
8874a4d8c2SCharles.Forsyth case OLIST:
8974a4d8c2SCharles.Forsyth gen(n->left);
9074a4d8c2SCharles.Forsyth
9174a4d8c2SCharles.Forsyth rloop:
9274a4d8c2SCharles.Forsyth n = n->right;
9374a4d8c2SCharles.Forsyth goto loop;
9474a4d8c2SCharles.Forsyth
9574a4d8c2SCharles.Forsyth case ORETURN:
9674a4d8c2SCharles.Forsyth retok = 1;
9774a4d8c2SCharles.Forsyth complex(n);
9874a4d8c2SCharles.Forsyth if(n->type == T)
9974a4d8c2SCharles.Forsyth break;
10074a4d8c2SCharles.Forsyth l = n->left;
10174a4d8c2SCharles.Forsyth if(l == Z) {
10274a4d8c2SCharles.Forsyth noretval(3);
10374a4d8c2SCharles.Forsyth gbranch(ORETURN);
10474a4d8c2SCharles.Forsyth break;
10574a4d8c2SCharles.Forsyth }
10674a4d8c2SCharles.Forsyth if(typesu[n->type->etype]) {
10774a4d8c2SCharles.Forsyth sugen(l, nodret, n->type->width);
10874a4d8c2SCharles.Forsyth noretval(3);
10974a4d8c2SCharles.Forsyth gbranch(ORETURN);
11074a4d8c2SCharles.Forsyth break;
11174a4d8c2SCharles.Forsyth }
11274a4d8c2SCharles.Forsyth regret(&nod, n);
11374a4d8c2SCharles.Forsyth cgen(l, &nod);
11474a4d8c2SCharles.Forsyth regfree(&nod);
11574a4d8c2SCharles.Forsyth if(typefd[n->type->etype])
11674a4d8c2SCharles.Forsyth noretval(1);
11774a4d8c2SCharles.Forsyth else
11874a4d8c2SCharles.Forsyth noretval(2);
11974a4d8c2SCharles.Forsyth gbranch(ORETURN);
12074a4d8c2SCharles.Forsyth break;
12174a4d8c2SCharles.Forsyth
12274a4d8c2SCharles.Forsyth case OLABEL:
12374a4d8c2SCharles.Forsyth l = n->left;
12474a4d8c2SCharles.Forsyth if(l) {
12574a4d8c2SCharles.Forsyth l->pc = pc;
12674a4d8c2SCharles.Forsyth if(l->label)
12774a4d8c2SCharles.Forsyth patch(l->label, pc);
12874a4d8c2SCharles.Forsyth }
12974a4d8c2SCharles.Forsyth gbranch(OGOTO); /* prevent self reference in reg */
13074a4d8c2SCharles.Forsyth patch(p, pc);
13174a4d8c2SCharles.Forsyth goto rloop;
13274a4d8c2SCharles.Forsyth
13374a4d8c2SCharles.Forsyth case OGOTO:
13474a4d8c2SCharles.Forsyth retok = 1;
13574a4d8c2SCharles.Forsyth n = n->left;
13674a4d8c2SCharles.Forsyth if(n == Z)
13774a4d8c2SCharles.Forsyth return;
13874a4d8c2SCharles.Forsyth if(n->complex == 0) {
13974a4d8c2SCharles.Forsyth diag(Z, "label undefined: %s", n->sym->name);
14074a4d8c2SCharles.Forsyth return;
14174a4d8c2SCharles.Forsyth }
14274a4d8c2SCharles.Forsyth gbranch(OGOTO);
14374a4d8c2SCharles.Forsyth if(n->pc) {
14474a4d8c2SCharles.Forsyth patch(p, n->pc);
14574a4d8c2SCharles.Forsyth return;
14674a4d8c2SCharles.Forsyth }
14774a4d8c2SCharles.Forsyth if(n->label)
14874a4d8c2SCharles.Forsyth patch(n->label, pc-1);
14974a4d8c2SCharles.Forsyth n->label = p;
15074a4d8c2SCharles.Forsyth return;
15174a4d8c2SCharles.Forsyth
15274a4d8c2SCharles.Forsyth case OCASE:
15374a4d8c2SCharles.Forsyth l = n->left;
15474a4d8c2SCharles.Forsyth if(cases == C)
15574a4d8c2SCharles.Forsyth diag(n, "case/default outside a switch");
15674a4d8c2SCharles.Forsyth if(l == Z) {
157*d67b7dadSforsyth casf();
15874a4d8c2SCharles.Forsyth cases->val = 0;
15974a4d8c2SCharles.Forsyth cases->def = 1;
16074a4d8c2SCharles.Forsyth cases->label = pc;
16174a4d8c2SCharles.Forsyth goto rloop;
16274a4d8c2SCharles.Forsyth }
16374a4d8c2SCharles.Forsyth complex(l);
16474a4d8c2SCharles.Forsyth if(l->type == T)
16574a4d8c2SCharles.Forsyth goto rloop;
16674a4d8c2SCharles.Forsyth if(l->op == OCONST)
16774a4d8c2SCharles.Forsyth if(typechl[l->type->etype]) {
168*d67b7dadSforsyth casf();
16974a4d8c2SCharles.Forsyth cases->val = l->vconst;
17074a4d8c2SCharles.Forsyth cases->def = 0;
17174a4d8c2SCharles.Forsyth cases->label = pc;
17274a4d8c2SCharles.Forsyth goto rloop;
17374a4d8c2SCharles.Forsyth }
17474a4d8c2SCharles.Forsyth diag(n, "case expression must be integer constant");
17574a4d8c2SCharles.Forsyth goto rloop;
17674a4d8c2SCharles.Forsyth
17774a4d8c2SCharles.Forsyth case OSWITCH:
17874a4d8c2SCharles.Forsyth l = n->left;
17974a4d8c2SCharles.Forsyth complex(l);
18074a4d8c2SCharles.Forsyth if(l->type == T)
18174a4d8c2SCharles.Forsyth break;
18274a4d8c2SCharles.Forsyth if(!typechl[l->type->etype]) {
18374a4d8c2SCharles.Forsyth diag(n, "switch expression must be integer");
18474a4d8c2SCharles.Forsyth break;
18574a4d8c2SCharles.Forsyth }
18674a4d8c2SCharles.Forsyth
18774a4d8c2SCharles.Forsyth gbranch(OGOTO); /* entry */
18874a4d8c2SCharles.Forsyth sp = p;
18974a4d8c2SCharles.Forsyth
19074a4d8c2SCharles.Forsyth cn = cases;
19174a4d8c2SCharles.Forsyth cases = C;
192*d67b7dadSforsyth casf();
19374a4d8c2SCharles.Forsyth
19474a4d8c2SCharles.Forsyth sbc = breakpc;
19574a4d8c2SCharles.Forsyth breakpc = pc;
19674a4d8c2SCharles.Forsyth gbranch(OGOTO);
19774a4d8c2SCharles.Forsyth spb = p;
19874a4d8c2SCharles.Forsyth
19974a4d8c2SCharles.Forsyth gen(n->right);
20074a4d8c2SCharles.Forsyth gbranch(OGOTO);
20174a4d8c2SCharles.Forsyth patch(p, breakpc);
20274a4d8c2SCharles.Forsyth
20374a4d8c2SCharles.Forsyth patch(sp, pc);
20474a4d8c2SCharles.Forsyth regalloc(&nod, l, Z);
20574a4d8c2SCharles.Forsyth nod.type = types[TLONG];
20674a4d8c2SCharles.Forsyth cgen(l, &nod);
20774a4d8c2SCharles.Forsyth doswit(&nod);
20874a4d8c2SCharles.Forsyth regfree(&nod);
20974a4d8c2SCharles.Forsyth patch(spb, pc);
21074a4d8c2SCharles.Forsyth
21174a4d8c2SCharles.Forsyth cases = cn;
21274a4d8c2SCharles.Forsyth breakpc = sbc;
21374a4d8c2SCharles.Forsyth break;
21474a4d8c2SCharles.Forsyth
21574a4d8c2SCharles.Forsyth case OWHILE:
21674a4d8c2SCharles.Forsyth case ODWHILE:
21774a4d8c2SCharles.Forsyth l = n->left;
21874a4d8c2SCharles.Forsyth gbranch(OGOTO); /* entry */
21974a4d8c2SCharles.Forsyth sp = p;
22074a4d8c2SCharles.Forsyth
22174a4d8c2SCharles.Forsyth scc = continpc;
22274a4d8c2SCharles.Forsyth continpc = pc;
22374a4d8c2SCharles.Forsyth gbranch(OGOTO);
22474a4d8c2SCharles.Forsyth spc = p;
22574a4d8c2SCharles.Forsyth
22674a4d8c2SCharles.Forsyth sbc = breakpc;
22774a4d8c2SCharles.Forsyth breakpc = pc;
22874a4d8c2SCharles.Forsyth gbranch(OGOTO);
22974a4d8c2SCharles.Forsyth spb = p;
23074a4d8c2SCharles.Forsyth
23174a4d8c2SCharles.Forsyth patch(spc, pc);
23274a4d8c2SCharles.Forsyth if(n->op == OWHILE)
23374a4d8c2SCharles.Forsyth patch(sp, pc);
23474a4d8c2SCharles.Forsyth bcomplex(l); /* test */
23574a4d8c2SCharles.Forsyth patch(p, breakpc);
23674a4d8c2SCharles.Forsyth
23774a4d8c2SCharles.Forsyth if(n->op == ODWHILE)
23874a4d8c2SCharles.Forsyth patch(sp, pc);
23974a4d8c2SCharles.Forsyth gen(n->right); /* body */
24074a4d8c2SCharles.Forsyth gbranch(OGOTO);
24174a4d8c2SCharles.Forsyth patch(p, continpc);
24274a4d8c2SCharles.Forsyth
24374a4d8c2SCharles.Forsyth patch(spb, pc);
24474a4d8c2SCharles.Forsyth continpc = scc;
24574a4d8c2SCharles.Forsyth breakpc = sbc;
24674a4d8c2SCharles.Forsyth break;
24774a4d8c2SCharles.Forsyth
24874a4d8c2SCharles.Forsyth case OFOR:
24974a4d8c2SCharles.Forsyth l = n->left;
25074a4d8c2SCharles.Forsyth gen(l->right->left); /* init */
25174a4d8c2SCharles.Forsyth gbranch(OGOTO); /* entry */
25274a4d8c2SCharles.Forsyth sp = p;
25374a4d8c2SCharles.Forsyth
25474a4d8c2SCharles.Forsyth scc = continpc;
25574a4d8c2SCharles.Forsyth continpc = pc;
25674a4d8c2SCharles.Forsyth gbranch(OGOTO);
25774a4d8c2SCharles.Forsyth spc = p;
25874a4d8c2SCharles.Forsyth
25974a4d8c2SCharles.Forsyth sbc = breakpc;
26074a4d8c2SCharles.Forsyth breakpc = pc;
26174a4d8c2SCharles.Forsyth gbranch(OGOTO);
26274a4d8c2SCharles.Forsyth spb = p;
26374a4d8c2SCharles.Forsyth
26474a4d8c2SCharles.Forsyth patch(spc, pc);
26574a4d8c2SCharles.Forsyth gen(l->right->right); /* inc */
26674a4d8c2SCharles.Forsyth patch(sp, pc);
26774a4d8c2SCharles.Forsyth if(l->left != Z) { /* test */
26874a4d8c2SCharles.Forsyth bcomplex(l->left);
26974a4d8c2SCharles.Forsyth patch(p, breakpc);
27074a4d8c2SCharles.Forsyth }
27174a4d8c2SCharles.Forsyth gen(n->right); /* body */
27274a4d8c2SCharles.Forsyth gbranch(OGOTO);
27374a4d8c2SCharles.Forsyth patch(p, continpc);
27474a4d8c2SCharles.Forsyth
27574a4d8c2SCharles.Forsyth patch(spb, pc);
27674a4d8c2SCharles.Forsyth continpc = scc;
27774a4d8c2SCharles.Forsyth breakpc = sbc;
27874a4d8c2SCharles.Forsyth break;
27974a4d8c2SCharles.Forsyth
28074a4d8c2SCharles.Forsyth case OCONTINUE:
28174a4d8c2SCharles.Forsyth if(continpc < 0) {
28274a4d8c2SCharles.Forsyth diag(n, "continue not in a loop");
28374a4d8c2SCharles.Forsyth break;
28474a4d8c2SCharles.Forsyth }
28574a4d8c2SCharles.Forsyth gbranch(OGOTO);
28674a4d8c2SCharles.Forsyth patch(p, continpc);
28774a4d8c2SCharles.Forsyth break;
28874a4d8c2SCharles.Forsyth
28974a4d8c2SCharles.Forsyth case OBREAK:
29074a4d8c2SCharles.Forsyth if(breakpc < 0) {
29174a4d8c2SCharles.Forsyth diag(n, "break not in a loop");
29274a4d8c2SCharles.Forsyth break;
29374a4d8c2SCharles.Forsyth }
29474a4d8c2SCharles.Forsyth gbranch(OGOTO);
29574a4d8c2SCharles.Forsyth patch(p, breakpc);
29674a4d8c2SCharles.Forsyth break;
29774a4d8c2SCharles.Forsyth
29874a4d8c2SCharles.Forsyth case OIF:
29974a4d8c2SCharles.Forsyth l = n->left;
30074a4d8c2SCharles.Forsyth bcomplex(l);
30174a4d8c2SCharles.Forsyth sp = p;
30274a4d8c2SCharles.Forsyth if(n->right->left != Z)
30374a4d8c2SCharles.Forsyth gen(n->right->left);
30474a4d8c2SCharles.Forsyth if(n->right->right != Z) {
30574a4d8c2SCharles.Forsyth gbranch(OGOTO);
30674a4d8c2SCharles.Forsyth patch(sp, pc);
30774a4d8c2SCharles.Forsyth sp = p;
30874a4d8c2SCharles.Forsyth gen(n->right->right);
30974a4d8c2SCharles.Forsyth }
31074a4d8c2SCharles.Forsyth patch(sp, pc);
31174a4d8c2SCharles.Forsyth break;
31274a4d8c2SCharles.Forsyth
31374a4d8c2SCharles.Forsyth case OSET:
31474a4d8c2SCharles.Forsyth case OUSED:
31574a4d8c2SCharles.Forsyth usedset(n->left, o);
31674a4d8c2SCharles.Forsyth break;
31774a4d8c2SCharles.Forsyth }
31874a4d8c2SCharles.Forsyth }
31974a4d8c2SCharles.Forsyth
32074a4d8c2SCharles.Forsyth void
usedset(Node * n,int o)32174a4d8c2SCharles.Forsyth usedset(Node *n, int o)
32274a4d8c2SCharles.Forsyth {
32374a4d8c2SCharles.Forsyth if(n->op == OLIST) {
32474a4d8c2SCharles.Forsyth usedset(n->left, o);
32574a4d8c2SCharles.Forsyth usedset(n->right, o);
32674a4d8c2SCharles.Forsyth return;
32774a4d8c2SCharles.Forsyth }
32874a4d8c2SCharles.Forsyth complex(n);
32974a4d8c2SCharles.Forsyth switch(n->op) {
33074a4d8c2SCharles.Forsyth case OADDR: /* volatile */
33174a4d8c2SCharles.Forsyth gins(ANOP, n, Z);
33274a4d8c2SCharles.Forsyth break;
33374a4d8c2SCharles.Forsyth case ONAME:
33474a4d8c2SCharles.Forsyth if(o == OSET)
33574a4d8c2SCharles.Forsyth gins(ANOP, Z, n);
33674a4d8c2SCharles.Forsyth else
33774a4d8c2SCharles.Forsyth gins(ANOP, n, Z);
33874a4d8c2SCharles.Forsyth break;
33974a4d8c2SCharles.Forsyth }
34074a4d8c2SCharles.Forsyth }
34174a4d8c2SCharles.Forsyth
34274a4d8c2SCharles.Forsyth void
noretval(int n)34374a4d8c2SCharles.Forsyth noretval(int n)
34474a4d8c2SCharles.Forsyth {
34574a4d8c2SCharles.Forsyth
34674a4d8c2SCharles.Forsyth if(n & 1) {
34774a4d8c2SCharles.Forsyth gins(ANOP, Z, Z);
34874a4d8c2SCharles.Forsyth p->to.type = D_REG;
34974a4d8c2SCharles.Forsyth p->to.reg = REGRET;
35074a4d8c2SCharles.Forsyth }
35174a4d8c2SCharles.Forsyth if(n & 2) {
35274a4d8c2SCharles.Forsyth gins(ANOP, Z, Z);
35374a4d8c2SCharles.Forsyth p->to.type = D_FREG;
35474a4d8c2SCharles.Forsyth p->to.reg = FREGRET;
35574a4d8c2SCharles.Forsyth }
35674a4d8c2SCharles.Forsyth }
35774a4d8c2SCharles.Forsyth
35874a4d8c2SCharles.Forsyth /*
35974a4d8c2SCharles.Forsyth * calculate addressability as follows
36074a4d8c2SCharles.Forsyth * CONST ==> 20 $value
36174a4d8c2SCharles.Forsyth * NAME ==> 10 name
36274a4d8c2SCharles.Forsyth * REGISTER ==> 11 register
36374a4d8c2SCharles.Forsyth * INDREG ==> 12 *[(reg)+offset]
36474a4d8c2SCharles.Forsyth * &10 ==> 2 $name
36574a4d8c2SCharles.Forsyth * ADD(2, 20) ==> 2 $name+offset
36674a4d8c2SCharles.Forsyth * ADD(3, 20) ==> 3 $(reg)+offset
36774a4d8c2SCharles.Forsyth * &12 ==> 3 $(reg)+offset
36874a4d8c2SCharles.Forsyth * *11 ==> 11 ??
36974a4d8c2SCharles.Forsyth * *2 ==> 10 name
37074a4d8c2SCharles.Forsyth * *3 ==> 12 *(reg)+offset
37174a4d8c2SCharles.Forsyth * calculate complexity (number of registers)
37274a4d8c2SCharles.Forsyth */
37374a4d8c2SCharles.Forsyth void
xcom(Node * n)37474a4d8c2SCharles.Forsyth xcom(Node *n)
37574a4d8c2SCharles.Forsyth {
37674a4d8c2SCharles.Forsyth Node *l, *r;
37774a4d8c2SCharles.Forsyth int t;
37874a4d8c2SCharles.Forsyth
37974a4d8c2SCharles.Forsyth if(n == Z)
38074a4d8c2SCharles.Forsyth return;
38174a4d8c2SCharles.Forsyth l = n->left;
38274a4d8c2SCharles.Forsyth r = n->right;
38374a4d8c2SCharles.Forsyth n->addable = 0;
38474a4d8c2SCharles.Forsyth n->complex = 0;
38574a4d8c2SCharles.Forsyth switch(n->op) {
38674a4d8c2SCharles.Forsyth case OCONST:
38774a4d8c2SCharles.Forsyth n->addable = 20;
38874a4d8c2SCharles.Forsyth return;
38974a4d8c2SCharles.Forsyth
39074a4d8c2SCharles.Forsyth case OREGISTER:
39174a4d8c2SCharles.Forsyth n->addable = 11;
39274a4d8c2SCharles.Forsyth return;
39374a4d8c2SCharles.Forsyth
39474a4d8c2SCharles.Forsyth case OINDREG:
39574a4d8c2SCharles.Forsyth n->addable = 12;
39674a4d8c2SCharles.Forsyth return;
39774a4d8c2SCharles.Forsyth
39874a4d8c2SCharles.Forsyth case ONAME:
39974a4d8c2SCharles.Forsyth n->addable = 10;
40074a4d8c2SCharles.Forsyth return;
40174a4d8c2SCharles.Forsyth
40274a4d8c2SCharles.Forsyth case OADDR:
40374a4d8c2SCharles.Forsyth xcom(l);
40474a4d8c2SCharles.Forsyth if(l->addable == 10)
40574a4d8c2SCharles.Forsyth n->addable = 2;
40674a4d8c2SCharles.Forsyth if(l->addable == 12)
40774a4d8c2SCharles.Forsyth n->addable = 3;
40874a4d8c2SCharles.Forsyth break;
40974a4d8c2SCharles.Forsyth
41074a4d8c2SCharles.Forsyth case OIND:
41174a4d8c2SCharles.Forsyth xcom(l);
41274a4d8c2SCharles.Forsyth if(l->addable == 11)
41374a4d8c2SCharles.Forsyth n->addable = 12;
41474a4d8c2SCharles.Forsyth if(l->addable == 3)
41574a4d8c2SCharles.Forsyth n->addable = 12;
41674a4d8c2SCharles.Forsyth if(l->addable == 2)
41774a4d8c2SCharles.Forsyth n->addable = 10;
41874a4d8c2SCharles.Forsyth break;
41974a4d8c2SCharles.Forsyth
42074a4d8c2SCharles.Forsyth case OADD:
42174a4d8c2SCharles.Forsyth xcom(l);
42274a4d8c2SCharles.Forsyth xcom(r);
42374a4d8c2SCharles.Forsyth if(l->addable == 20) {
42474a4d8c2SCharles.Forsyth if(r->addable == 2)
42574a4d8c2SCharles.Forsyth n->addable = 2;
42674a4d8c2SCharles.Forsyth if(r->addable == 3)
42774a4d8c2SCharles.Forsyth n->addable = 3;
42874a4d8c2SCharles.Forsyth }
42974a4d8c2SCharles.Forsyth if(r->addable == 20) {
43074a4d8c2SCharles.Forsyth if(l->addable == 2)
43174a4d8c2SCharles.Forsyth n->addable = 2;
43274a4d8c2SCharles.Forsyth if(l->addable == 3)
43374a4d8c2SCharles.Forsyth n->addable = 3;
43474a4d8c2SCharles.Forsyth }
43574a4d8c2SCharles.Forsyth break;
43674a4d8c2SCharles.Forsyth
43774a4d8c2SCharles.Forsyth case OASLMUL:
43874a4d8c2SCharles.Forsyth case OASMUL:
43974a4d8c2SCharles.Forsyth xcom(l);
44074a4d8c2SCharles.Forsyth xcom(r);
44174a4d8c2SCharles.Forsyth t = vlog(r);
44274a4d8c2SCharles.Forsyth if(t >= 0) {
44374a4d8c2SCharles.Forsyth n->op = OASASHL;
44474a4d8c2SCharles.Forsyth r->vconst = t;
44574a4d8c2SCharles.Forsyth r->type = types[TINT];
44674a4d8c2SCharles.Forsyth }
44774a4d8c2SCharles.Forsyth break;
44874a4d8c2SCharles.Forsyth
44974a4d8c2SCharles.Forsyth case OMUL:
45074a4d8c2SCharles.Forsyth case OLMUL:
45174a4d8c2SCharles.Forsyth xcom(l);
45274a4d8c2SCharles.Forsyth xcom(r);
45374a4d8c2SCharles.Forsyth t = vlog(r);
45474a4d8c2SCharles.Forsyth if(t >= 0) {
45574a4d8c2SCharles.Forsyth n->op = OASHL;
45674a4d8c2SCharles.Forsyth r->vconst = t;
45774a4d8c2SCharles.Forsyth r->type = types[TINT];
45874a4d8c2SCharles.Forsyth }
45974a4d8c2SCharles.Forsyth t = vlog(l);
46074a4d8c2SCharles.Forsyth if(t >= 0) {
46174a4d8c2SCharles.Forsyth n->op = OASHL;
46274a4d8c2SCharles.Forsyth n->left = r;
46374a4d8c2SCharles.Forsyth n->right = l;
46474a4d8c2SCharles.Forsyth r = l;
46574a4d8c2SCharles.Forsyth l = n->left;
46674a4d8c2SCharles.Forsyth r->vconst = t;
46774a4d8c2SCharles.Forsyth r->type = types[TINT];
46874a4d8c2SCharles.Forsyth }
46974a4d8c2SCharles.Forsyth break;
47074a4d8c2SCharles.Forsyth
47174a4d8c2SCharles.Forsyth case OASLDIV:
47274a4d8c2SCharles.Forsyth xcom(l);
47374a4d8c2SCharles.Forsyth xcom(r);
47474a4d8c2SCharles.Forsyth t = vlog(r);
47574a4d8c2SCharles.Forsyth if(t >= 0) {
47674a4d8c2SCharles.Forsyth n->op = OASLSHR;
47774a4d8c2SCharles.Forsyth r->vconst = t;
47874a4d8c2SCharles.Forsyth r->type = types[TINT];
47974a4d8c2SCharles.Forsyth }
48074a4d8c2SCharles.Forsyth break;
48174a4d8c2SCharles.Forsyth
48274a4d8c2SCharles.Forsyth case OLDIV:
48374a4d8c2SCharles.Forsyth xcom(l);
48474a4d8c2SCharles.Forsyth xcom(r);
48574a4d8c2SCharles.Forsyth t = vlog(r);
48674a4d8c2SCharles.Forsyth if(t >= 0) {
48774a4d8c2SCharles.Forsyth n->op = OLSHR;
48874a4d8c2SCharles.Forsyth r->vconst = t;
48974a4d8c2SCharles.Forsyth r->type = types[TINT];
49074a4d8c2SCharles.Forsyth }
49174a4d8c2SCharles.Forsyth break;
49274a4d8c2SCharles.Forsyth
49374a4d8c2SCharles.Forsyth case OASLMOD:
49474a4d8c2SCharles.Forsyth xcom(l);
49574a4d8c2SCharles.Forsyth xcom(r);
49674a4d8c2SCharles.Forsyth t = vlog(r);
49774a4d8c2SCharles.Forsyth if(t >= 0) {
49874a4d8c2SCharles.Forsyth n->op = OASAND;
49974a4d8c2SCharles.Forsyth r->vconst--;
50074a4d8c2SCharles.Forsyth }
50174a4d8c2SCharles.Forsyth break;
50274a4d8c2SCharles.Forsyth
50374a4d8c2SCharles.Forsyth case OLMOD:
50474a4d8c2SCharles.Forsyth xcom(l);
50574a4d8c2SCharles.Forsyth xcom(r);
50674a4d8c2SCharles.Forsyth t = vlog(r);
50774a4d8c2SCharles.Forsyth if(t >= 0) {
50874a4d8c2SCharles.Forsyth n->op = OAND;
50974a4d8c2SCharles.Forsyth r->vconst--;
51074a4d8c2SCharles.Forsyth }
51174a4d8c2SCharles.Forsyth break;
51274a4d8c2SCharles.Forsyth
51374a4d8c2SCharles.Forsyth default:
51474a4d8c2SCharles.Forsyth if(l != Z)
51574a4d8c2SCharles.Forsyth xcom(l);
51674a4d8c2SCharles.Forsyth if(r != Z)
51774a4d8c2SCharles.Forsyth xcom(r);
51874a4d8c2SCharles.Forsyth break;
51974a4d8c2SCharles.Forsyth }
52074a4d8c2SCharles.Forsyth if(n->addable >= 10)
52174a4d8c2SCharles.Forsyth return;
52274a4d8c2SCharles.Forsyth
52374a4d8c2SCharles.Forsyth if(l != Z)
52474a4d8c2SCharles.Forsyth n->complex = l->complex;
52574a4d8c2SCharles.Forsyth if(r != Z) {
52674a4d8c2SCharles.Forsyth if(r->complex == n->complex)
52774a4d8c2SCharles.Forsyth n->complex = r->complex+1;
52874a4d8c2SCharles.Forsyth else
52974a4d8c2SCharles.Forsyth if(r->complex > n->complex)
53074a4d8c2SCharles.Forsyth n->complex = r->complex;
53174a4d8c2SCharles.Forsyth }
53274a4d8c2SCharles.Forsyth if(n->complex == 0)
53374a4d8c2SCharles.Forsyth n->complex++;
53474a4d8c2SCharles.Forsyth
53574a4d8c2SCharles.Forsyth switch(n->op) {
53674a4d8c2SCharles.Forsyth case OFUNC:
53774a4d8c2SCharles.Forsyth n->complex = FNX;
53874a4d8c2SCharles.Forsyth break;
53974a4d8c2SCharles.Forsyth
54074a4d8c2SCharles.Forsyth case OADD:
54174a4d8c2SCharles.Forsyth case OXOR:
54274a4d8c2SCharles.Forsyth case OAND:
54374a4d8c2SCharles.Forsyth case OOR:
54474a4d8c2SCharles.Forsyth case OEQ:
54574a4d8c2SCharles.Forsyth case ONE:
54674a4d8c2SCharles.Forsyth /*
54774a4d8c2SCharles.Forsyth * immediate operators, make const on right
54874a4d8c2SCharles.Forsyth */
54974a4d8c2SCharles.Forsyth if(l->op == OCONST) {
55074a4d8c2SCharles.Forsyth n->left = r;
55174a4d8c2SCharles.Forsyth n->right = l;
55274a4d8c2SCharles.Forsyth }
55374a4d8c2SCharles.Forsyth break;
55474a4d8c2SCharles.Forsyth }
55574a4d8c2SCharles.Forsyth }
55674a4d8c2SCharles.Forsyth
55774a4d8c2SCharles.Forsyth void
bcomplex(Node * n)55874a4d8c2SCharles.Forsyth bcomplex(Node *n)
55974a4d8c2SCharles.Forsyth {
56074a4d8c2SCharles.Forsyth
56174a4d8c2SCharles.Forsyth complex(n);
56274a4d8c2SCharles.Forsyth if(n->type != T)
56374a4d8c2SCharles.Forsyth if(tcompat(n, T, n->type, tnot))
56474a4d8c2SCharles.Forsyth n->type = T;
56574a4d8c2SCharles.Forsyth if(n->type != T)
56674a4d8c2SCharles.Forsyth boolgen(n, 1, Z);
56774a4d8c2SCharles.Forsyth else
56874a4d8c2SCharles.Forsyth gbranch(OGOTO);
56974a4d8c2SCharles.Forsyth }
570