xref: /plan9/sys/src/cmd/kc/sgen.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include "gc.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier void
43e12c5d1SDavid du Colombier codgen(Node *n, Node *nn)
53e12c5d1SDavid du Colombier {
63e12c5d1SDavid du Colombier 	Prog *sp;
73e12c5d1SDavid du Colombier 	Node *n1, nod, nod1;
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier 	cursafe = 0;
103e12c5d1SDavid du Colombier 	curarg = 0;
113e12c5d1SDavid du Colombier 	maxargsafe = 0;
123e12c5d1SDavid du Colombier 
133e12c5d1SDavid du Colombier 	/*
143e12c5d1SDavid du Colombier 	 * isolate name
153e12c5d1SDavid du Colombier 	 */
163e12c5d1SDavid du Colombier 	for(n1 = nn;; n1 = n1->left) {
173e12c5d1SDavid du Colombier 		if(n1 == Z) {
183e12c5d1SDavid du Colombier 			diag(nn, "cant find function name");
193e12c5d1SDavid du Colombier 			return;
203e12c5d1SDavid du Colombier 		}
213e12c5d1SDavid du Colombier 		if(n1->op == ONAME)
223e12c5d1SDavid du Colombier 			break;
233e12c5d1SDavid du Colombier 	}
243e12c5d1SDavid du Colombier 	nearln = nn->lineno;
253e12c5d1SDavid du Colombier 	gpseudo(ATEXT, n1->sym, nodconst(stkoff));
263e12c5d1SDavid du Colombier 	sp = p;
273e12c5d1SDavid du Colombier 
283e12c5d1SDavid du Colombier 	/*
293e12c5d1SDavid du Colombier 	 * isolate first argument
303e12c5d1SDavid du Colombier 	 */
313e12c5d1SDavid du Colombier 	if(REGARG) {
32*219b2ee8SDavid du Colombier 		if(typesu[thisfn->link->etype] || typev[thisfn->link->etype]) {
333e12c5d1SDavid du Colombier 			nod1 = *nodret->left;
343e12c5d1SDavid du Colombier 			nodreg(&nod, &nod1, REGARG);
353e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, &nod1);
363e12c5d1SDavid du Colombier 		} else
373e12c5d1SDavid du Colombier 		if(firstarg && typechlp[firstargtype->etype]) {
383e12c5d1SDavid du Colombier 			nod1 = *nodret->left;
393e12c5d1SDavid du Colombier 			nod1.sym = firstarg;
403e12c5d1SDavid du Colombier 			nod1.type = firstargtype;
413e12c5d1SDavid du Colombier 			if(firstargtype->width < tint->width)
42*219b2ee8SDavid du Colombier 				nod1.xoffset += endian(firstargtype->width);
433e12c5d1SDavid du Colombier 			nod1.etype = firstargtype->etype;
443e12c5d1SDavid du Colombier 			nodreg(&nod, &nod1, REGARG);
453e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, &nod1);
463e12c5d1SDavid du Colombier 		}
473e12c5d1SDavid du Colombier 	}
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier 	retok = 0;
503e12c5d1SDavid du Colombier 	gen(n);
513e12c5d1SDavid du Colombier 	if(!retok)
523e12c5d1SDavid du Colombier 		if(thisfn->link->etype != TVOID)
533e12c5d1SDavid du Colombier 			warn(Z, "no return at end of function: %s", n1->sym->name);
543e12c5d1SDavid du Colombier 	noretval(3);
553e12c5d1SDavid du Colombier 	gbranch(ORETURN);
563e12c5d1SDavid du Colombier 
573e12c5d1SDavid du Colombier 	if(!debug['N'] || debug['R'] || debug['P'])
583e12c5d1SDavid du Colombier 		regopt(sp);
593e12c5d1SDavid du Colombier 
603e12c5d1SDavid du Colombier 	sp->to.offset += maxargsafe;
613e12c5d1SDavid du Colombier }
623e12c5d1SDavid du Colombier 
633e12c5d1SDavid du Colombier void
643e12c5d1SDavid du Colombier gen(Node *n)
653e12c5d1SDavid du Colombier {
663e12c5d1SDavid du Colombier 	Node *l, nod;
673e12c5d1SDavid du Colombier 	Prog *sp, *spc, *spb;
683e12c5d1SDavid du Colombier 	Case *cn;
693e12c5d1SDavid du Colombier 	long sbc, scc;
703e12c5d1SDavid du Colombier 	int o;
713e12c5d1SDavid du Colombier 
723e12c5d1SDavid du Colombier loop:
733e12c5d1SDavid du Colombier 	if(n == Z)
743e12c5d1SDavid du Colombier 		return;
753e12c5d1SDavid du Colombier 	nearln = n->lineno;
763e12c5d1SDavid du Colombier 	o = n->op;
773e12c5d1SDavid du Colombier 	if(debug['G'])
783e12c5d1SDavid du Colombier 		if(o != OLIST)
793e12c5d1SDavid du Colombier 			print("%L %O\n", nearln, o);
803e12c5d1SDavid du Colombier 	retok = 0;
813e12c5d1SDavid du Colombier 	switch(o) {
823e12c5d1SDavid du Colombier 
833e12c5d1SDavid du Colombier 	default:
843e12c5d1SDavid du Colombier 		complex(n);
853e12c5d1SDavid du Colombier 		cgen(n, Z);
863e12c5d1SDavid du Colombier 		break;
873e12c5d1SDavid du Colombier 
883e12c5d1SDavid du Colombier 	case OLIST:
893e12c5d1SDavid du Colombier 		gen(n->left);
903e12c5d1SDavid du Colombier 
913e12c5d1SDavid du Colombier 	rloop:
923e12c5d1SDavid du Colombier 		n = n->right;
933e12c5d1SDavid du Colombier 		goto loop;
943e12c5d1SDavid du Colombier 
953e12c5d1SDavid du Colombier 	case ORETURN:
963e12c5d1SDavid du Colombier 		retok = 1;
973e12c5d1SDavid du Colombier 		complex(n);
983e12c5d1SDavid du Colombier 		if(n->type == T)
993e12c5d1SDavid du Colombier 			break;
1003e12c5d1SDavid du Colombier 		l = n->left;
1013e12c5d1SDavid du Colombier 		if(l == Z) {
1023e12c5d1SDavid du Colombier 			noretval(3);
1033e12c5d1SDavid du Colombier 			gbranch(ORETURN);
1043e12c5d1SDavid du Colombier 			break;
1053e12c5d1SDavid du Colombier 		}
106*219b2ee8SDavid du Colombier 		if(typesu[n->type->etype] || typev[n->type->etype]) {
1073e12c5d1SDavid du Colombier 			sugen(l, nodret, n->type->width);
1083e12c5d1SDavid du Colombier 			noretval(3);
1093e12c5d1SDavid du Colombier 			gbranch(ORETURN);
1103e12c5d1SDavid du Colombier 			break;
1113e12c5d1SDavid du Colombier 		}
1123e12c5d1SDavid du Colombier 		regret(&nod, n);
1133e12c5d1SDavid du Colombier 		cgen(l, &nod);
1143e12c5d1SDavid du Colombier 		regfree(&nod);
115*219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
1163e12c5d1SDavid du Colombier 			noretval(1);
1173e12c5d1SDavid du Colombier 		else
1183e12c5d1SDavid du Colombier 			noretval(2);
1193e12c5d1SDavid du Colombier 		gbranch(ORETURN);
1203e12c5d1SDavid du Colombier 		break;
1213e12c5d1SDavid du Colombier 
1223e12c5d1SDavid du Colombier 	case OLABEL:
1233e12c5d1SDavid du Colombier 		l = n->left;
1243e12c5d1SDavid du Colombier 		if(l) {
125*219b2ee8SDavid du Colombier 			l->xoffset = pc;
1263e12c5d1SDavid du Colombier 			if(l->label)
1273e12c5d1SDavid du Colombier 				patch(l->label, pc);
1283e12c5d1SDavid du Colombier 		}
1293e12c5d1SDavid du Colombier 		gbranch(OGOTO);	/* prevent self reference in reg */
1303e12c5d1SDavid du Colombier 		patch(p, pc);
1313e12c5d1SDavid du Colombier 		goto rloop;
1323e12c5d1SDavid du Colombier 
1333e12c5d1SDavid du Colombier 	case OGOTO:
1343e12c5d1SDavid du Colombier 		retok = 1;
1353e12c5d1SDavid du Colombier 		n = n->left;
1363e12c5d1SDavid du Colombier 		if(n == Z)
1373e12c5d1SDavid du Colombier 			return;
1383e12c5d1SDavid du Colombier 		if(n->complex == 0) {
1393e12c5d1SDavid du Colombier 			diag(Z, "label undefined: %s", n->sym->name);
1403e12c5d1SDavid du Colombier 			return;
1413e12c5d1SDavid du Colombier 		}
1423e12c5d1SDavid du Colombier 		gbranch(OGOTO);
143*219b2ee8SDavid du Colombier 		if(n->xoffset) {
144*219b2ee8SDavid du Colombier 			patch(p, n->xoffset);
1453e12c5d1SDavid du Colombier 			return;
1463e12c5d1SDavid du Colombier 		}
1473e12c5d1SDavid du Colombier 		if(n->label)
1483e12c5d1SDavid du Colombier 			patch(n->label, pc-1);
1493e12c5d1SDavid du Colombier 		n->label = p;
1503e12c5d1SDavid du Colombier 		return;
1513e12c5d1SDavid du Colombier 
1523e12c5d1SDavid du Colombier 	case OCASE:
1533e12c5d1SDavid du Colombier 		l = n->left;
1543e12c5d1SDavid du Colombier 		if(cases == C)
1553e12c5d1SDavid du Colombier 			diag(n, "case/default outside a switch");
1563e12c5d1SDavid du Colombier 		if(l == Z) {
1573e12c5d1SDavid du Colombier 			cas();
1583e12c5d1SDavid du Colombier 			cases->val = 0;
1593e12c5d1SDavid du Colombier 			cases->def = 1;
1603e12c5d1SDavid du Colombier 			cases->label = pc;
1613e12c5d1SDavid du Colombier 			goto rloop;
1623e12c5d1SDavid du Colombier 		}
1633e12c5d1SDavid du Colombier 		complex(l);
1643e12c5d1SDavid du Colombier 		if(l->type == T)
1653e12c5d1SDavid du Colombier 			goto rloop;
1663e12c5d1SDavid du Colombier 		if(l->op == OCONST)
1673e12c5d1SDavid du Colombier 		if(typechl[l->type->etype]) {
1683e12c5d1SDavid du Colombier 			cas();
169*219b2ee8SDavid du Colombier 			cases->val = l->vconst;
1703e12c5d1SDavid du Colombier 			cases->def = 0;
1713e12c5d1SDavid du Colombier 			cases->label = pc;
1723e12c5d1SDavid du Colombier 			goto rloop;
1733e12c5d1SDavid du Colombier 		}
1743e12c5d1SDavid du Colombier 		diag(n, "case expression must be integer constant");
1753e12c5d1SDavid du Colombier 		goto rloop;
1763e12c5d1SDavid du Colombier 
1773e12c5d1SDavid du Colombier 	case OSWITCH:
1783e12c5d1SDavid du Colombier 		l = n->left;
1793e12c5d1SDavid du Colombier 		complex(l);
1803e12c5d1SDavid du Colombier 		if(l->type == T)
1813e12c5d1SDavid du Colombier 			break;
1823e12c5d1SDavid du Colombier 		if(!typechl[l->type->etype]) {
1833e12c5d1SDavid du Colombier 			diag(n, "switch expression must be integer");
1843e12c5d1SDavid du Colombier 			break;
1853e12c5d1SDavid du Colombier 		}
1863e12c5d1SDavid du Colombier 
1873e12c5d1SDavid du Colombier 		gbranch(OGOTO);		/* entry */
1883e12c5d1SDavid du Colombier 		sp = p;
1893e12c5d1SDavid du Colombier 
1903e12c5d1SDavid du Colombier 		cn = cases;
1913e12c5d1SDavid du Colombier 		cases = C;
1923e12c5d1SDavid du Colombier 		cas();
1933e12c5d1SDavid du Colombier 
1943e12c5d1SDavid du Colombier 		sbc = breakpc;
1953e12c5d1SDavid du Colombier 		breakpc = pc;
1963e12c5d1SDavid du Colombier 		gbranch(OGOTO);
1973e12c5d1SDavid du Colombier 		spb = p;
1983e12c5d1SDavid du Colombier 
1993e12c5d1SDavid du Colombier 		gen(n->right);
2003e12c5d1SDavid du Colombier 		gbranch(OGOTO);
2013e12c5d1SDavid du Colombier 		patch(p, breakpc);
2023e12c5d1SDavid du Colombier 
2033e12c5d1SDavid du Colombier 		patch(sp, pc);
2043e12c5d1SDavid du Colombier 		regalloc(&nod, l, Z);
2053e12c5d1SDavid du Colombier 		nod.type = types[TLONG];
2063e12c5d1SDavid du Colombier 		cgen(l, &nod);
2073e12c5d1SDavid du Colombier 		doswit(&nod);
2083e12c5d1SDavid du Colombier 		regfree(&nod);
2093e12c5d1SDavid du Colombier 		patch(spb, pc);
2103e12c5d1SDavid du Colombier 
2113e12c5d1SDavid du Colombier 		cases = cn;
2123e12c5d1SDavid du Colombier 		breakpc = sbc;
2133e12c5d1SDavid du Colombier 		break;
2143e12c5d1SDavid du Colombier 
2153e12c5d1SDavid du Colombier 	case OWHILE:
2163e12c5d1SDavid du Colombier 	case ODWHILE:
2173e12c5d1SDavid du Colombier 		l = n->left;
2183e12c5d1SDavid du Colombier 		gbranch(OGOTO);		/* entry */
2193e12c5d1SDavid du Colombier 		sp = p;
2203e12c5d1SDavid du Colombier 
2213e12c5d1SDavid du Colombier 		scc = continpc;
2223e12c5d1SDavid du Colombier 		continpc = pc;
2233e12c5d1SDavid du Colombier 		gbranch(OGOTO);
2243e12c5d1SDavid du Colombier 		spc = p;
2253e12c5d1SDavid du Colombier 
2263e12c5d1SDavid du Colombier 		sbc = breakpc;
2273e12c5d1SDavid du Colombier 		breakpc = pc;
2283e12c5d1SDavid du Colombier 		gbranch(OGOTO);
2293e12c5d1SDavid du Colombier 		spb = p;
2303e12c5d1SDavid du Colombier 
2313e12c5d1SDavid du Colombier 		patch(spc, pc);
2323e12c5d1SDavid du Colombier 		if(n->op == OWHILE)
2333e12c5d1SDavid du Colombier 			patch(sp, pc);
2343e12c5d1SDavid du Colombier 		bcomplex(l);		/* test */
2353e12c5d1SDavid du Colombier 		patch(p, breakpc);
2363e12c5d1SDavid du Colombier 
2373e12c5d1SDavid du Colombier 		if(n->op == ODWHILE)
2383e12c5d1SDavid du Colombier 			patch(sp, pc);
2393e12c5d1SDavid du Colombier 		gen(n->right);		/* body */
2403e12c5d1SDavid du Colombier 		gbranch(OGOTO);
2413e12c5d1SDavid du Colombier 		patch(p, continpc);
2423e12c5d1SDavid du Colombier 
2433e12c5d1SDavid du Colombier 		patch(spb, pc);
2443e12c5d1SDavid du Colombier 		continpc = scc;
2453e12c5d1SDavid du Colombier 		breakpc = sbc;
2463e12c5d1SDavid du Colombier 		break;
2473e12c5d1SDavid du Colombier 
2483e12c5d1SDavid du Colombier 	case OFOR:
2493e12c5d1SDavid du Colombier 		l = n->left;
2503e12c5d1SDavid du Colombier 		gen(l->right->left);	/* init */
2513e12c5d1SDavid du Colombier 		gbranch(OGOTO);		/* entry */
2523e12c5d1SDavid du Colombier 		sp = p;
2533e12c5d1SDavid du Colombier 
2543e12c5d1SDavid du Colombier 		scc = continpc;
2553e12c5d1SDavid du Colombier 		continpc = pc;
2563e12c5d1SDavid du Colombier 		gbranch(OGOTO);
2573e12c5d1SDavid du Colombier 		spc = p;
2583e12c5d1SDavid du Colombier 
2593e12c5d1SDavid du Colombier 		sbc = breakpc;
2603e12c5d1SDavid du Colombier 		breakpc = pc;
2613e12c5d1SDavid du Colombier 		gbranch(OGOTO);
2623e12c5d1SDavid du Colombier 		spb = p;
2633e12c5d1SDavid du Colombier 
2643e12c5d1SDavid du Colombier 		patch(spc, pc);
2653e12c5d1SDavid du Colombier 		gen(l->right->right);	/* inc */
2663e12c5d1SDavid du Colombier 		patch(sp, pc);
2673e12c5d1SDavid du Colombier 		if(l->left != Z) {	/* test */
2683e12c5d1SDavid du Colombier 			bcomplex(l->left);
2693e12c5d1SDavid du Colombier 			patch(p, breakpc);
2703e12c5d1SDavid du Colombier 		}
2713e12c5d1SDavid du Colombier 		gen(n->right);		/* body */
2723e12c5d1SDavid du Colombier 		gbranch(OGOTO);
2733e12c5d1SDavid du Colombier 		patch(p, continpc);
2743e12c5d1SDavid du Colombier 
2753e12c5d1SDavid du Colombier 		patch(spb, pc);
2763e12c5d1SDavid du Colombier 		continpc = scc;
2773e12c5d1SDavid du Colombier 		breakpc = sbc;
2783e12c5d1SDavid du Colombier 		break;
2793e12c5d1SDavid du Colombier 
2803e12c5d1SDavid du Colombier 	case OCONTINUE:
2813e12c5d1SDavid du Colombier 		if(continpc < 0) {
2823e12c5d1SDavid du Colombier 			diag(n, "continue not in a loop");
2833e12c5d1SDavid du Colombier 			break;
2843e12c5d1SDavid du Colombier 		}
2853e12c5d1SDavid du Colombier 		gbranch(OGOTO);
2863e12c5d1SDavid du Colombier 		patch(p, continpc);
2873e12c5d1SDavid du Colombier 		break;
2883e12c5d1SDavid du Colombier 
2893e12c5d1SDavid du Colombier 	case OBREAK:
2903e12c5d1SDavid du Colombier 		if(breakpc < 0) {
2913e12c5d1SDavid du Colombier 			diag(n, "break not in a loop");
2923e12c5d1SDavid du Colombier 			break;
2933e12c5d1SDavid du Colombier 		}
2943e12c5d1SDavid du Colombier 		gbranch(OGOTO);
2953e12c5d1SDavid du Colombier 		patch(p, breakpc);
2963e12c5d1SDavid du Colombier 		break;
2973e12c5d1SDavid du Colombier 
2983e12c5d1SDavid du Colombier 	case OIF:
2993e12c5d1SDavid du Colombier 		l = n->left;
3003e12c5d1SDavid du Colombier 		bcomplex(l);
3013e12c5d1SDavid du Colombier 		sp = p;
3023e12c5d1SDavid du Colombier 		if(n->right->left != Z)
3033e12c5d1SDavid du Colombier 			gen(n->right->left);
3043e12c5d1SDavid du Colombier 		if(n->right->right != Z) {
3053e12c5d1SDavid du Colombier 			gbranch(OGOTO);
3063e12c5d1SDavid du Colombier 			patch(sp, pc);
3073e12c5d1SDavid du Colombier 			sp = p;
3083e12c5d1SDavid du Colombier 			gen(n->right->right);
3093e12c5d1SDavid du Colombier 		}
3103e12c5d1SDavid du Colombier 		patch(sp, pc);
3113e12c5d1SDavid du Colombier 		break;
3123e12c5d1SDavid du Colombier 
3133e12c5d1SDavid du Colombier 	case OSET:
3143e12c5d1SDavid du Colombier 	case OUSED:
3153e12c5d1SDavid du Colombier 		n = n->left;
3163e12c5d1SDavid du Colombier 		for(;;) {
3173e12c5d1SDavid du Colombier 			if(n->op == OLIST) {
3183e12c5d1SDavid du Colombier 				l = n->right;
3193e12c5d1SDavid du Colombier 				n = n->left;
3203e12c5d1SDavid du Colombier 				complex(l);
3213e12c5d1SDavid du Colombier 				if(l->op == ONAME) {
3223e12c5d1SDavid du Colombier 					if(o == OSET)
3233e12c5d1SDavid du Colombier 						gins(ANOP, Z, l);
3243e12c5d1SDavid du Colombier 					else
3253e12c5d1SDavid du Colombier 						gins(ANOP, l, Z);
3263e12c5d1SDavid du Colombier 				}
3273e12c5d1SDavid du Colombier 			} else {
3283e12c5d1SDavid du Colombier 				complex(n);
3293e12c5d1SDavid du Colombier 				if(n->op == ONAME) {
3303e12c5d1SDavid du Colombier 					if(o == OSET)
3313e12c5d1SDavid du Colombier 						gins(ANOP, Z, n);
3323e12c5d1SDavid du Colombier 					else
3333e12c5d1SDavid du Colombier 						gins(ANOP, n, Z);
3343e12c5d1SDavid du Colombier 				}
3353e12c5d1SDavid du Colombier 				break;
3363e12c5d1SDavid du Colombier 			}
3373e12c5d1SDavid du Colombier 		}
3383e12c5d1SDavid du Colombier 		break;
3393e12c5d1SDavid du Colombier 	}
3403e12c5d1SDavid du Colombier }
3413e12c5d1SDavid du Colombier 
3423e12c5d1SDavid du Colombier void
3433e12c5d1SDavid du Colombier noretval(int n)
3443e12c5d1SDavid du Colombier {
3453e12c5d1SDavid du Colombier 
3463e12c5d1SDavid du Colombier 	if(n & 1) {
3473e12c5d1SDavid du Colombier 		gins(ANOP, Z, Z);
3483e12c5d1SDavid du Colombier 		p->to.type = D_REG;
3493e12c5d1SDavid du Colombier 		p->to.reg = REGRET;
3503e12c5d1SDavid du Colombier 	}
3513e12c5d1SDavid du Colombier 	if(n & 2) {
3523e12c5d1SDavid du Colombier 		gins(ANOP, Z, Z);
3533e12c5d1SDavid du Colombier 		p->to.type = D_FREG;
3543e12c5d1SDavid du Colombier 		p->to.reg = FREGRET;
3553e12c5d1SDavid du Colombier 	}
3563e12c5d1SDavid du Colombier }
3573e12c5d1SDavid du Colombier 
3583e12c5d1SDavid du Colombier /*
3593e12c5d1SDavid du Colombier  *	calculate addressability as follows
3603e12c5d1SDavid du Colombier  *		CONST ==> 20		$value
3613e12c5d1SDavid du Colombier  *		NAME ==> 10		name
3623e12c5d1SDavid du Colombier  *		REGISTER ==> 11		register
3633e12c5d1SDavid du Colombier  *		INDREG ==> 12		*[(reg)+offset]
3643e12c5d1SDavid du Colombier  *		&10 ==> 2		$name
3653e12c5d1SDavid du Colombier  *		ADD(2, 20) ==> 2	$name+offset
3663e12c5d1SDavid du Colombier  *		ADD(3, 20) ==> 3	$(reg)+offset
3673e12c5d1SDavid du Colombier  *		&12 ==> 3		$(reg)+offset
3683e12c5d1SDavid du Colombier  *		*11 ==> 11		??
3693e12c5d1SDavid du Colombier  *		*2 ==> 10		name
3703e12c5d1SDavid du Colombier  *		*3 ==> 12		*(reg)+offset
3713e12c5d1SDavid du Colombier  *	calculate complexity (number of registers)
3723e12c5d1SDavid du Colombier  */
3733e12c5d1SDavid du Colombier void
3743e12c5d1SDavid du Colombier xcom(Node *n)
3753e12c5d1SDavid du Colombier {
3763e12c5d1SDavid du Colombier 	Node *l, *r;
3773e12c5d1SDavid du Colombier 	int v;
3783e12c5d1SDavid du Colombier 
3793e12c5d1SDavid du Colombier 	if(n == Z)
3803e12c5d1SDavid du Colombier 		return;
3813e12c5d1SDavid du Colombier 	l = n->left;
3823e12c5d1SDavid du Colombier 	r = n->right;
3833e12c5d1SDavid du Colombier 	n->addable = 0;
3843e12c5d1SDavid du Colombier 	n->complex = 0;
3853e12c5d1SDavid du Colombier 	switch(n->op) {
3863e12c5d1SDavid du Colombier 	case OCONST:
3873e12c5d1SDavid du Colombier 		n->addable = 20;
3883e12c5d1SDavid du Colombier 		return;
3893e12c5d1SDavid du Colombier 
3903e12c5d1SDavid du Colombier 	case OREGISTER:
3913e12c5d1SDavid du Colombier 		n->addable = 11;
3923e12c5d1SDavid du Colombier 		return;
3933e12c5d1SDavid du Colombier 
3943e12c5d1SDavid du Colombier 	case OINDREG:
3953e12c5d1SDavid du Colombier 		n->addable = 12;
3963e12c5d1SDavid du Colombier 		return;
3973e12c5d1SDavid du Colombier 
3983e12c5d1SDavid du Colombier 	case ONAME:
3993e12c5d1SDavid du Colombier 		n->addable = 10;
4003e12c5d1SDavid du Colombier 		return;
4013e12c5d1SDavid du Colombier 
4023e12c5d1SDavid du Colombier 	case OADDR:
4033e12c5d1SDavid du Colombier 		xcom(l);
4043e12c5d1SDavid du Colombier 		if(l->addable == 10)
4053e12c5d1SDavid du Colombier 			n->addable = 2;
4063e12c5d1SDavid du Colombier 		if(l->addable == 12)
4073e12c5d1SDavid du Colombier 			n->addable = 3;
4083e12c5d1SDavid du Colombier 		break;
4093e12c5d1SDavid du Colombier 
4103e12c5d1SDavid du Colombier 	case OIND:
4113e12c5d1SDavid du Colombier 		xcom(l);
4123e12c5d1SDavid du Colombier 		if(l->addable == 11)
4133e12c5d1SDavid du Colombier 			n->addable = 12;
4143e12c5d1SDavid du Colombier 		if(l->addable == 3)
4153e12c5d1SDavid du Colombier 			n->addable = 12;
4163e12c5d1SDavid du Colombier 		if(l->addable == 2)
4173e12c5d1SDavid du Colombier 			n->addable = 10;
4183e12c5d1SDavid du Colombier 		break;
4193e12c5d1SDavid du Colombier 
4203e12c5d1SDavid du Colombier 	case OADD:
4213e12c5d1SDavid du Colombier 		xcom(l);
4223e12c5d1SDavid du Colombier 		xcom(r);
4233e12c5d1SDavid du Colombier 		if(l->addable == 20) {
4243e12c5d1SDavid du Colombier 			if(r->addable == 2)
4253e12c5d1SDavid du Colombier 				n->addable = 2;
4263e12c5d1SDavid du Colombier 			if(r->addable == 3)
4273e12c5d1SDavid du Colombier 				n->addable = 3;
4283e12c5d1SDavid du Colombier 		}
4293e12c5d1SDavid du Colombier 		if(r->addable == 20) {
4303e12c5d1SDavid du Colombier 			if(l->addable == 2)
4313e12c5d1SDavid du Colombier 				n->addable = 2;
4323e12c5d1SDavid du Colombier 			if(l->addable == 3)
4333e12c5d1SDavid du Colombier 				n->addable = 3;
4343e12c5d1SDavid du Colombier 		}
4353e12c5d1SDavid du Colombier 		break;
4363e12c5d1SDavid du Colombier 
4373e12c5d1SDavid du Colombier 	case OASMUL:
4383e12c5d1SDavid du Colombier 	case OASLMUL:
4393e12c5d1SDavid du Colombier 		xcom(l);
4403e12c5d1SDavid du Colombier 		xcom(r);
4413e12c5d1SDavid du Colombier 		v = vlog(r);
4423e12c5d1SDavid du Colombier 		if(v >= 0) {
4433e12c5d1SDavid du Colombier 			n->op = OASASHL;
444*219b2ee8SDavid du Colombier 			r->vconst = v;
445*219b2ee8SDavid du Colombier 			r->type = tint;
4463e12c5d1SDavid du Colombier 		}
4473e12c5d1SDavid du Colombier 		break;
4483e12c5d1SDavid du Colombier 
4493e12c5d1SDavid du Colombier 	case OMUL:
4503e12c5d1SDavid du Colombier 	case OLMUL:
4513e12c5d1SDavid du Colombier 		xcom(l);
4523e12c5d1SDavid du Colombier 		xcom(r);
4533e12c5d1SDavid du Colombier 		v = vlog(r);
4543e12c5d1SDavid du Colombier 		if(v >= 0) {
4553e12c5d1SDavid du Colombier 			n->op = OASHL;
456*219b2ee8SDavid du Colombier 			r->vconst = v;
457*219b2ee8SDavid du Colombier 			r->type = tint;
4583e12c5d1SDavid du Colombier 		}
4593e12c5d1SDavid du Colombier 		v = vlog(l);
4603e12c5d1SDavid du Colombier 		if(v >= 0) {
4613e12c5d1SDavid du Colombier 			n->op = OASHL;
4623e12c5d1SDavid du Colombier 			n->left = r;
4633e12c5d1SDavid du Colombier 			n->right = l;
4643e12c5d1SDavid du Colombier 			r = l;
4653e12c5d1SDavid du Colombier 			l = n->left;
466*219b2ee8SDavid du Colombier 			r->vconst = v;
467*219b2ee8SDavid du Colombier 			r->type = tint;
4683e12c5d1SDavid du Colombier 		}
4693e12c5d1SDavid du Colombier 		break;
4703e12c5d1SDavid du Colombier 
4713e12c5d1SDavid du Colombier 	case OASLDIV:
4723e12c5d1SDavid du Colombier 		xcom(l);
4733e12c5d1SDavid du Colombier 		xcom(r);
4743e12c5d1SDavid du Colombier 		v = vlog(r);
4753e12c5d1SDavid du Colombier 		if(v >= 0) {
4763e12c5d1SDavid du Colombier 			n->op = OASLSHR;
477*219b2ee8SDavid du Colombier 			r->vconst = v;
478*219b2ee8SDavid du Colombier 			r->type = tint;
4793e12c5d1SDavid du Colombier 		}
4803e12c5d1SDavid du Colombier 		break;
4813e12c5d1SDavid du Colombier 
4823e12c5d1SDavid du Colombier 	case OLDIV:
4833e12c5d1SDavid du Colombier 		xcom(l);
4843e12c5d1SDavid du Colombier 		xcom(r);
4853e12c5d1SDavid du Colombier 		v = vlog(r);
4863e12c5d1SDavid du Colombier 		if(v >= 0) {
4873e12c5d1SDavid du Colombier 			n->op = OLSHR;
488*219b2ee8SDavid du Colombier 			r->vconst = v;
489*219b2ee8SDavid du Colombier 			r->type = tint;
4903e12c5d1SDavid du Colombier 		}
4913e12c5d1SDavid du Colombier 		break;
4923e12c5d1SDavid du Colombier 
4933e12c5d1SDavid du Colombier 	case OASLMOD:
4943e12c5d1SDavid du Colombier 		xcom(l);
4953e12c5d1SDavid du Colombier 		xcom(r);
4963e12c5d1SDavid du Colombier 		v = vlog(r);
4973e12c5d1SDavid du Colombier 		if(v >= 0) {
4983e12c5d1SDavid du Colombier 			n->op = OASAND;
499*219b2ee8SDavid du Colombier 			r->vconst--;
5003e12c5d1SDavid du Colombier 		}
5013e12c5d1SDavid du Colombier 		break;
5023e12c5d1SDavid du Colombier 
5033e12c5d1SDavid du Colombier 	case OLMOD:
5043e12c5d1SDavid du Colombier 		xcom(l);
5053e12c5d1SDavid du Colombier 		xcom(r);
5063e12c5d1SDavid du Colombier 		v = vlog(r);
5073e12c5d1SDavid du Colombier 		if(v >= 0) {
5083e12c5d1SDavid du Colombier 			n->op = OAND;
509*219b2ee8SDavid du Colombier 			r->vconst--;
5103e12c5d1SDavid du Colombier 		}
5113e12c5d1SDavid du Colombier 		break;
5123e12c5d1SDavid du Colombier 
5133e12c5d1SDavid du Colombier 	default:
5143e12c5d1SDavid du Colombier 		if(l != Z)
5153e12c5d1SDavid du Colombier 			xcom(l);
5163e12c5d1SDavid du Colombier 		if(r != Z)
5173e12c5d1SDavid du Colombier 			xcom(r);
5183e12c5d1SDavid du Colombier 		break;
5193e12c5d1SDavid du Colombier 	}
5203e12c5d1SDavid du Colombier 	if(n->addable >= 10)
5213e12c5d1SDavid du Colombier 		return;
5223e12c5d1SDavid du Colombier 	if(l != Z)
5233e12c5d1SDavid du Colombier 		n->complex = l->complex;
5243e12c5d1SDavid du Colombier 	if(r != Z) {
5253e12c5d1SDavid du Colombier 		if(r->complex == n->complex)
5263e12c5d1SDavid du Colombier 			n->complex = r->complex+1;
5273e12c5d1SDavid du Colombier 		else
5283e12c5d1SDavid du Colombier 		if(r->complex > n->complex)
5293e12c5d1SDavid du Colombier 			n->complex = r->complex;
5303e12c5d1SDavid du Colombier 	}
5313e12c5d1SDavid du Colombier 	if(n->complex == 0)
5323e12c5d1SDavid du Colombier 		n->complex++;
533*219b2ee8SDavid du Colombier 
534*219b2ee8SDavid du Colombier 	if(com64(n))
535*219b2ee8SDavid du Colombier 		return;
536*219b2ee8SDavid du Colombier 
5373e12c5d1SDavid du Colombier 	switch(n->op) {
5383e12c5d1SDavid du Colombier 
5393e12c5d1SDavid du Colombier 	case OFUNC:
5403e12c5d1SDavid du Colombier 		n->complex = FNX;
5413e12c5d1SDavid du Colombier 		break;
5423e12c5d1SDavid du Colombier 
5433e12c5d1SDavid du Colombier 	case OEQ:
5443e12c5d1SDavid du Colombier 	case ONE:
5453e12c5d1SDavid du Colombier 	case OLE:
5463e12c5d1SDavid du Colombier 	case OLT:
5473e12c5d1SDavid du Colombier 	case OGE:
5483e12c5d1SDavid du Colombier 	case OGT:
5493e12c5d1SDavid du Colombier 	case OHI:
5503e12c5d1SDavid du Colombier 	case OHS:
5513e12c5d1SDavid du Colombier 	case OLO:
5523e12c5d1SDavid du Colombier 	case OLS:
5533e12c5d1SDavid du Colombier 		/*
5543e12c5d1SDavid du Colombier 		 * immediate operators, make const on right
5553e12c5d1SDavid du Colombier 		 */
5563e12c5d1SDavid du Colombier 		if(l->op == OCONST) {
5573e12c5d1SDavid du Colombier 			n->left = r;
5583e12c5d1SDavid du Colombier 			n->right = l;
5593e12c5d1SDavid du Colombier 			n->op = invrel[relindex(n->op)];
5603e12c5d1SDavid du Colombier 		}
5613e12c5d1SDavid du Colombier 		break;
5623e12c5d1SDavid du Colombier 
5633e12c5d1SDavid du Colombier 	case OADD:
5643e12c5d1SDavid du Colombier 	case OXOR:
5653e12c5d1SDavid du Colombier 	case OAND:
5663e12c5d1SDavid du Colombier 	case OOR:
5673e12c5d1SDavid du Colombier 		/*
5683e12c5d1SDavid du Colombier 		 * immediate operators, make const on right
5693e12c5d1SDavid du Colombier 		 */
5703e12c5d1SDavid du Colombier 		if(l->op == OCONST) {
5713e12c5d1SDavid du Colombier 			n->left = r;
5723e12c5d1SDavid du Colombier 			n->right = l;
5733e12c5d1SDavid du Colombier 		}
5743e12c5d1SDavid du Colombier 		break;
5753e12c5d1SDavid du Colombier 	}
5763e12c5d1SDavid du Colombier }
5773e12c5d1SDavid du Colombier 
5783e12c5d1SDavid du Colombier void
5793e12c5d1SDavid du Colombier bcomplex(Node *n)
5803e12c5d1SDavid du Colombier {
5813e12c5d1SDavid du Colombier 
5823e12c5d1SDavid du Colombier 	complex(n);
5833e12c5d1SDavid du Colombier 	if(n->type != T)
5843e12c5d1SDavid du Colombier 	if(tcompat(n, T, n->type, tnot))
5853e12c5d1SDavid du Colombier 		n->type = T;
5863e12c5d1SDavid du Colombier 	if(n->type != T) {
587*219b2ee8SDavid du Colombier 		bool64(n);
5883e12c5d1SDavid du Colombier 		boolgen(n, 1, Z);
5893e12c5d1SDavid du Colombier 	} else
5903e12c5d1SDavid du Colombier 		gbranch(OGOTO);
5913e12c5d1SDavid du Colombier }
592