xref: /plan9/sys/src/cmd/8c/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, *n2, nod;
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(n2 = nn;; n2 = n2->left) {
173e12c5d1SDavid du Colombier 		if(n2 == Z) {
183e12c5d1SDavid du Colombier 			diag(nn, "cant find function name");
193e12c5d1SDavid du Colombier 			return;
203e12c5d1SDavid du Colombier 		}
213e12c5d1SDavid du Colombier 		if(n2->op == ONAME)
223e12c5d1SDavid du Colombier 			break;
233e12c5d1SDavid du Colombier 	}
243e12c5d1SDavid du Colombier 	nearln = nn->lineno;
253e12c5d1SDavid du Colombier 	gpseudo(ATEXT, n2->sym, nodconst(stkoff));
263e12c5d1SDavid du Colombier 
273e12c5d1SDavid du Colombier 	/*
283e12c5d1SDavid du Colombier 	 * isolate first argument
293e12c5d1SDavid du Colombier 	 */
303e12c5d1SDavid du Colombier 	if(REGARG) {
313e12c5d1SDavid du Colombier 		n1 = nn;
323e12c5d1SDavid du Colombier 		if(n1 != Z)
333e12c5d1SDavid du Colombier 			n1 = n1->right;
343e12c5d1SDavid du Colombier 		if(n1 != Z && n1->op == OLIST)
353e12c5d1SDavid du Colombier 			n1 = n1->left;
363e12c5d1SDavid du Colombier 		if(n1 != Z && n1->op == OPROTO)
373e12c5d1SDavid du Colombier 			n1 = n1->left;
383e12c5d1SDavid du Colombier 		if(n1 != Z && typelp[n1->type->etype]) {
393e12c5d1SDavid du Colombier 			nodreg(&nod, n1, REGARG);
403e12c5d1SDavid du Colombier 			gmove(&nod, n1);
413e12c5d1SDavid du Colombier 		}
423e12c5d1SDavid du Colombier 	}
433e12c5d1SDavid du Colombier 
443e12c5d1SDavid du Colombier 	sp = p;
453e12c5d1SDavid du Colombier 	retok = 0;
463e12c5d1SDavid du Colombier 	gen(n);
473e12c5d1SDavid du Colombier 	if(!retok)
483e12c5d1SDavid du Colombier 		if(thisfn->link->etype != TVOID)
493e12c5d1SDavid du Colombier 			warn(Z, "no return at end of function: %s", n2->sym->name);
503e12c5d1SDavid du Colombier 	noretval(3);
51*219b2ee8SDavid du Colombier 	if(thisfn && thisfn->link && typefd[thisfn->link->etype])
523e12c5d1SDavid du Colombier 		gins(AFLDZ, Z, Z);
533e12c5d1SDavid du Colombier 	gbranch(ORETURN);
543e12c5d1SDavid du Colombier 
553e12c5d1SDavid du Colombier 	if(!debug['N'] || debug['R'] || debug['P'])
563e12c5d1SDavid du Colombier 		regopt(sp);
573e12c5d1SDavid du Colombier 	sp->to.offset += maxargsafe;
583e12c5d1SDavid du Colombier }
593e12c5d1SDavid du Colombier 
603e12c5d1SDavid du Colombier void
613e12c5d1SDavid du Colombier gen(Node *n)
623e12c5d1SDavid du Colombier {
633e12c5d1SDavid du Colombier 	Node *l, nod;
643e12c5d1SDavid du Colombier 	Prog *sp, *spc, *spb;
653e12c5d1SDavid du Colombier 	Case *cn;
663e12c5d1SDavid du Colombier 	long sbc, scc;
673e12c5d1SDavid du Colombier 	int o;
683e12c5d1SDavid du Colombier 
693e12c5d1SDavid du Colombier loop:
703e12c5d1SDavid du Colombier 	if(n == Z)
713e12c5d1SDavid du Colombier 		return;
723e12c5d1SDavid du Colombier 	nearln = n->lineno;
733e12c5d1SDavid du Colombier 	o = n->op;
743e12c5d1SDavid du Colombier 	if(debug['G'])
753e12c5d1SDavid du Colombier 		if(o != OLIST)
763e12c5d1SDavid du Colombier 			print("%L %O\n", nearln, o);
773e12c5d1SDavid du Colombier 
783e12c5d1SDavid du Colombier 	retok = 0;
793e12c5d1SDavid du Colombier 	switch(o) {
803e12c5d1SDavid du Colombier 
813e12c5d1SDavid du Colombier 	default:
823e12c5d1SDavid du Colombier 		complex(n);
833e12c5d1SDavid du Colombier 		cgen(n, Z);
843e12c5d1SDavid du Colombier 		break;
853e12c5d1SDavid du Colombier 
863e12c5d1SDavid du Colombier 	case OLIST:
873e12c5d1SDavid du Colombier 		gen(n->left);
883e12c5d1SDavid du Colombier 
893e12c5d1SDavid du Colombier 	rloop:
903e12c5d1SDavid du Colombier 		n = n->right;
913e12c5d1SDavid du Colombier 		goto loop;
923e12c5d1SDavid du Colombier 
933e12c5d1SDavid du Colombier 	case ORETURN:
943e12c5d1SDavid du Colombier 		retok = 1;
953e12c5d1SDavid du Colombier 		complex(n);
963e12c5d1SDavid du Colombier 		if(n->type == T)
973e12c5d1SDavid du Colombier 			break;
983e12c5d1SDavid du Colombier 		l = n->left;
993e12c5d1SDavid du Colombier 		if(l == Z) {
1003e12c5d1SDavid du Colombier 			noretval(3);
101*219b2ee8SDavid du Colombier 			if(typefd[n->type->etype])
1023e12c5d1SDavid du Colombier 				gins(AFLDZ, Z, Z);
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 = REGRET;
3493e12c5d1SDavid du Colombier 	}
3503e12c5d1SDavid du Colombier 	if(n & 2) {
3513e12c5d1SDavid du Colombier 		gins(ANOP, Z, Z);
3523e12c5d1SDavid du Colombier 		p->to.type = FREGRET;
3533e12c5d1SDavid du Colombier 	}
3543e12c5d1SDavid du Colombier }
3553e12c5d1SDavid du Colombier 
3563e12c5d1SDavid du Colombier /*
3573e12c5d1SDavid du Colombier  *	calculate addressability as follows
3583e12c5d1SDavid du Colombier  *		NAME ==> 10/11		name+value(SB/SP)
3593e12c5d1SDavid du Colombier  *		REGISTER ==> 12		register
3603e12c5d1SDavid du Colombier  *		CONST ==> 20		$value
3613e12c5d1SDavid du Colombier  *		*(20) ==> 21		value
3623e12c5d1SDavid du Colombier  *		&(10) ==> 13		$name+value(SB)
3633e12c5d1SDavid du Colombier  *		&(11) ==> 1		$name+value(SP)
3643e12c5d1SDavid du Colombier  *		(13) + (20) ==> 13	fold constants
3653e12c5d1SDavid du Colombier  *		(1) + (20) ==> 1	fold constants
3663e12c5d1SDavid du Colombier  *		*(13) ==> 10		back to name
3673e12c5d1SDavid du Colombier  *		*(1) ==> 11		back to name
3683e12c5d1SDavid du Colombier  *
3693e12c5d1SDavid du Colombier  *		(20) * (X) ==> 7	multiplier in indexing
3703e12c5d1SDavid du Colombier  *		(X,7) + (13,1) ==> 8	adder in indexing (addresses)
3713e12c5d1SDavid du Colombier  *		(8) ==> &9(OINDEX)	index, almost addressable
3723e12c5d1SDavid du Colombier  *
3733e12c5d1SDavid du Colombier  *	calculate complexity (number of registers)
3743e12c5d1SDavid du Colombier  */
3753e12c5d1SDavid du Colombier void
3763e12c5d1SDavid du Colombier xcom(Node *n)
3773e12c5d1SDavid du Colombier {
3783e12c5d1SDavid du Colombier 	Node *l, *r;
3793e12c5d1SDavid du Colombier 	int g;
3803e12c5d1SDavid du Colombier 
3813e12c5d1SDavid du Colombier 	if(n == Z)
3823e12c5d1SDavid du Colombier 		return;
3833e12c5d1SDavid du Colombier 	l = n->left;
3843e12c5d1SDavid du Colombier 	r = n->right;
3853e12c5d1SDavid du Colombier 	n->complex = 0;
3863e12c5d1SDavid du Colombier 	n->addable = 0;
3873e12c5d1SDavid du Colombier 	switch(n->op) {
3883e12c5d1SDavid du Colombier 	case OCONST:
3893e12c5d1SDavid du Colombier 		n->addable = 20;
3903e12c5d1SDavid du Colombier 		break;
3913e12c5d1SDavid du Colombier 
3923e12c5d1SDavid du Colombier 	case ONAME:
3933e12c5d1SDavid du Colombier 		n->addable = 10;
3943e12c5d1SDavid du Colombier 		if(n->class == CPARAM || n->class == CAUTO)
3953e12c5d1SDavid du Colombier 			n->addable = 11;
3963e12c5d1SDavid du Colombier 		break;
3973e12c5d1SDavid du Colombier 
3983e12c5d1SDavid du Colombier 	case OREGISTER:
3993e12c5d1SDavid du Colombier 		n->addable = 12;
4003e12c5d1SDavid du Colombier 		break;
4013e12c5d1SDavid du Colombier 
4023e12c5d1SDavid du Colombier 	case OINDREG:
4033e12c5d1SDavid du Colombier 		n->addable = 12;
4043e12c5d1SDavid du Colombier 		break;
4053e12c5d1SDavid du Colombier 
4063e12c5d1SDavid du Colombier 	case OADDR:
4073e12c5d1SDavid du Colombier 		xcom(l);
4083e12c5d1SDavid du Colombier 		if(l->addable == 10)
4093e12c5d1SDavid du Colombier 			n->addable = 13;
4103e12c5d1SDavid du Colombier 		else
4113e12c5d1SDavid du Colombier 		if(l->addable == 11)
4123e12c5d1SDavid du Colombier 			n->addable = 1;
4133e12c5d1SDavid du Colombier 		break;
4143e12c5d1SDavid du Colombier 
4153e12c5d1SDavid du Colombier 	case OADD:
4163e12c5d1SDavid du Colombier 		xcom(l);
4173e12c5d1SDavid du Colombier 		xcom(r);
4183e12c5d1SDavid du Colombier 		if(n->type->etype != TIND)
4193e12c5d1SDavid du Colombier 			break;
4203e12c5d1SDavid du Colombier 
4213e12c5d1SDavid du Colombier 		if(l->addable == 20)
4223e12c5d1SDavid du Colombier 		switch(r->addable) {
4233e12c5d1SDavid du Colombier 		case 13:
4243e12c5d1SDavid du Colombier 		case 1:
4253e12c5d1SDavid du Colombier 			n->addable = r->addable;
4263e12c5d1SDavid du Colombier 			goto brk;
4273e12c5d1SDavid du Colombier 		}
4283e12c5d1SDavid du Colombier 		if(r->addable == 20)
4293e12c5d1SDavid du Colombier 		switch(l->addable) {
4303e12c5d1SDavid du Colombier 		case 13:
4313e12c5d1SDavid du Colombier 		case 1:
4323e12c5d1SDavid du Colombier 			n->addable = l->addable;
4333e12c5d1SDavid du Colombier 			goto brk;
4343e12c5d1SDavid du Colombier 		}
4353e12c5d1SDavid du Colombier 
4363e12c5d1SDavid du Colombier 		switch(r->addable) {
4373e12c5d1SDavid du Colombier 		case 13:
4383e12c5d1SDavid du Colombier 		case 1:
4393e12c5d1SDavid du Colombier 			n->addable = 8;
4403e12c5d1SDavid du Colombier 		}
4413e12c5d1SDavid du Colombier 		switch(l->addable) {
4423e12c5d1SDavid du Colombier 		case 13:
4433e12c5d1SDavid du Colombier 		case 1:
4443e12c5d1SDavid du Colombier 			n->addable = 8;
4453e12c5d1SDavid du Colombier 		}
4463e12c5d1SDavid du Colombier 		if(n->addable == 8) {
4473e12c5d1SDavid du Colombier 			indx(n);
4483e12c5d1SDavid du Colombier 			l = new1(OINDEX, idx.basetree, idx.regtree);
4493e12c5d1SDavid du Colombier 			l->scale = idx.scale;
4503e12c5d1SDavid du Colombier 			l->addable = 9;
4513e12c5d1SDavid du Colombier 			l->complex = l->right->complex;
4523e12c5d1SDavid du Colombier 			l->type = l->left->type;
4533e12c5d1SDavid du Colombier 			n->op = OADDR;
4543e12c5d1SDavid du Colombier 			n->left = l;
4553e12c5d1SDavid du Colombier 			n->right = Z;
4563e12c5d1SDavid du Colombier 			n->addable = 0;
4573e12c5d1SDavid du Colombier 			break;
4583e12c5d1SDavid du Colombier 		}
4593e12c5d1SDavid du Colombier 		break;
4603e12c5d1SDavid du Colombier 
461bd389b36SDavid du Colombier 	case OINDEX:
462bd389b36SDavid du Colombier 		xcom(l);
463bd389b36SDavid du Colombier 		xcom(r);
464bd389b36SDavid du Colombier 		n->addable = 9;
465bd389b36SDavid du Colombier 		break;
466bd389b36SDavid du Colombier 
4673e12c5d1SDavid du Colombier 	case OIND:
4683e12c5d1SDavid du Colombier 		xcom(l);
4693e12c5d1SDavid du Colombier 		if(l->op == OADDR) {
4703e12c5d1SDavid du Colombier 			l = l->left;
4713e12c5d1SDavid du Colombier 			l->type = n->type;
4723e12c5d1SDavid du Colombier 			*n = *l;
4733e12c5d1SDavid du Colombier 			return;
4743e12c5d1SDavid du Colombier 		}
4753e12c5d1SDavid du Colombier 		switch(l->addable) {
4763e12c5d1SDavid du Colombier 		case 20:
4773e12c5d1SDavid du Colombier 			n->addable = 21;
4783e12c5d1SDavid du Colombier 			break;
4793e12c5d1SDavid du Colombier 		case 1:
4803e12c5d1SDavid du Colombier 			n->addable = 11;
4813e12c5d1SDavid du Colombier 			break;
4823e12c5d1SDavid du Colombier 		case 13:
4833e12c5d1SDavid du Colombier 			n->addable = 10;
4843e12c5d1SDavid du Colombier 			break;
4853e12c5d1SDavid du Colombier 		}
4863e12c5d1SDavid du Colombier 		break;
4873e12c5d1SDavid du Colombier 
4883e12c5d1SDavid du Colombier 	case OASHL:
4893e12c5d1SDavid du Colombier 		xcom(l);
4903e12c5d1SDavid du Colombier 		xcom(r);
4913e12c5d1SDavid du Colombier 		g = vconst(r);
4923e12c5d1SDavid du Colombier 		if(g >= 0 && g < 4)
4933e12c5d1SDavid du Colombier 			n->addable = 7;
4943e12c5d1SDavid du Colombier 		break;
4953e12c5d1SDavid du Colombier 
4963e12c5d1SDavid du Colombier 	case OMUL:
4973e12c5d1SDavid du Colombier 	case OLMUL:
4983e12c5d1SDavid du Colombier 		xcom(l);
4993e12c5d1SDavid du Colombier 		xcom(r);
5003e12c5d1SDavid du Colombier 		g = vlog(r);
5013e12c5d1SDavid du Colombier 		if(g >= 0) {
5023e12c5d1SDavid du Colombier 			n->op = OASHL;
503*219b2ee8SDavid du Colombier 			r->vconst = g;
5043e12c5d1SDavid du Colombier 			if(g < 4)
5053e12c5d1SDavid du Colombier 				n->addable = 7;
5063e12c5d1SDavid du Colombier 			break;
5073e12c5d1SDavid du Colombier 		}
5083e12c5d1SDavid du Colombier 		g = vlog(l);
5093e12c5d1SDavid du Colombier 		if(g >= 0) {
5103e12c5d1SDavid du Colombier 			n->left = r;
5113e12c5d1SDavid du Colombier 			n->right = l;
5123e12c5d1SDavid du Colombier 			l = r;
5133e12c5d1SDavid du Colombier 			r = n->right;
5143e12c5d1SDavid du Colombier 			n->op = OASHL;
515*219b2ee8SDavid du Colombier 			r->vconst = g;
5163e12c5d1SDavid du Colombier 			if(g < 4)
5173e12c5d1SDavid du Colombier 				n->addable = 7;
5183e12c5d1SDavid du Colombier 			break;
5193e12c5d1SDavid du Colombier 		}
5203e12c5d1SDavid du Colombier 		break;
5213e12c5d1SDavid du Colombier 
5223e12c5d1SDavid du Colombier 	case ODIV:
5233e12c5d1SDavid du Colombier 	case OLDIV:
5243e12c5d1SDavid du Colombier 		xcom(l);
5253e12c5d1SDavid du Colombier 		xcom(r);
5263e12c5d1SDavid du Colombier 		g = vlog(r);
5273e12c5d1SDavid du Colombier 		if(g >= 0) {
5283e12c5d1SDavid du Colombier 			if(n->op == ODIV)
5293e12c5d1SDavid du Colombier 				n->op = OASHR;
5303e12c5d1SDavid du Colombier 			else
5313e12c5d1SDavid du Colombier 				n->op = OLSHR;
532*219b2ee8SDavid du Colombier 			r->vconst = g;
5333e12c5d1SDavid du Colombier 		}
5343e12c5d1SDavid du Colombier 		break;
5353e12c5d1SDavid du Colombier 
5363e12c5d1SDavid du Colombier 	case OASMUL:
5373e12c5d1SDavid du Colombier 	case OASLMUL:
5383e12c5d1SDavid du Colombier 		xcom(l);
5393e12c5d1SDavid du Colombier 		xcom(r);
5403e12c5d1SDavid du Colombier 		g = vlog(r);
5413e12c5d1SDavid du Colombier 		if(g >= 0) {
5423e12c5d1SDavid du Colombier 			n->op = OASASHL;
543*219b2ee8SDavid du Colombier 			r->vconst = g;
5443e12c5d1SDavid du Colombier 		}
5453e12c5d1SDavid du Colombier 		break;
5463e12c5d1SDavid du Colombier 
5473e12c5d1SDavid du Colombier 	case OASDIV:
5483e12c5d1SDavid du Colombier 	case OASLDIV:
5493e12c5d1SDavid du Colombier 		xcom(l);
5503e12c5d1SDavid du Colombier 		xcom(r);
5513e12c5d1SDavid du Colombier 		g = vlog(r);
5523e12c5d1SDavid du Colombier 		if(g >= 0) {
5533e12c5d1SDavid du Colombier 			if(n->op == OASDIV)
5543e12c5d1SDavid du Colombier 				n->op = OASASHR;
5553e12c5d1SDavid du Colombier 			else
5563e12c5d1SDavid du Colombier 				n->op = OASLSHR;
557*219b2ee8SDavid du Colombier 			r->vconst = g;
5583e12c5d1SDavid du Colombier 		}
5593e12c5d1SDavid du Colombier 		break;
5603e12c5d1SDavid du Colombier 
5613e12c5d1SDavid du Colombier 	default:
5623e12c5d1SDavid du Colombier 		if(l != Z)
5633e12c5d1SDavid du Colombier 			xcom(l);
5643e12c5d1SDavid du Colombier 		if(r != Z)
5653e12c5d1SDavid du Colombier 			xcom(r);
5663e12c5d1SDavid du Colombier 		break;
5673e12c5d1SDavid du Colombier 	}
5683e12c5d1SDavid du Colombier brk:
5693e12c5d1SDavid du Colombier 	if(n->addable >= 10)
5703e12c5d1SDavid du Colombier 		return;
5713e12c5d1SDavid du Colombier 	if(l != Z)
5723e12c5d1SDavid du Colombier 		n->complex = l->complex;
5733e12c5d1SDavid du Colombier 	if(r != Z) {
5743e12c5d1SDavid du Colombier 		if(r->complex == n->complex)
5753e12c5d1SDavid du Colombier 			n->complex = r->complex+1;
5763e12c5d1SDavid du Colombier 		else
5773e12c5d1SDavid du Colombier 		if(r->complex > n->complex)
5783e12c5d1SDavid du Colombier 			n->complex = r->complex;
5793e12c5d1SDavid du Colombier 	}
5803e12c5d1SDavid du Colombier 	if(n->complex == 0)
5813e12c5d1SDavid du Colombier 		n->complex++;
582*219b2ee8SDavid du Colombier 
583*219b2ee8SDavid du Colombier 	if(com64(n))
584*219b2ee8SDavid du Colombier 		return;
585*219b2ee8SDavid du Colombier 
5863e12c5d1SDavid du Colombier 	switch(n->op) {
5873e12c5d1SDavid du Colombier 
5883e12c5d1SDavid du Colombier 	case OFUNC:
5893e12c5d1SDavid du Colombier 		n->complex = FNX;
5903e12c5d1SDavid du Colombier 		break;
5913e12c5d1SDavid du Colombier 
5923e12c5d1SDavid du Colombier 	case OLMOD:
5933e12c5d1SDavid du Colombier 	case OMOD:
5943e12c5d1SDavid du Colombier 	case OLMUL:
5953e12c5d1SDavid du Colombier 	case OLDIV:
5963e12c5d1SDavid du Colombier 	case OMUL:
5973e12c5d1SDavid du Colombier 	case ODIV:
5983e12c5d1SDavid du Colombier 	case OASLMUL:
5993e12c5d1SDavid du Colombier 	case OASLDIV:
6003e12c5d1SDavid du Colombier 	case OASLMOD:
6013e12c5d1SDavid du Colombier 	case OASMUL:
6023e12c5d1SDavid du Colombier 	case OASDIV:
6033e12c5d1SDavid du Colombier 	case OASMOD:
6043e12c5d1SDavid du Colombier 		if(r->complex >= l->complex) {
6053e12c5d1SDavid du Colombier 			n->complex = l->complex + 3;
6063e12c5d1SDavid du Colombier 			if(r->complex > n->complex)
6073e12c5d1SDavid du Colombier 				n->complex = r->complex;
6083e12c5d1SDavid du Colombier 		} else {
6093e12c5d1SDavid du Colombier 			n->complex = r->complex + 3;
6103e12c5d1SDavid du Colombier 			if(l->complex > n->complex)
6113e12c5d1SDavid du Colombier 				n->complex = l->complex;
6123e12c5d1SDavid du Colombier 		}
6133e12c5d1SDavid du Colombier 		break;
6143e12c5d1SDavid du Colombier 
6153e12c5d1SDavid du Colombier 	case OLSHR:
6163e12c5d1SDavid du Colombier 	case OASHL:
6173e12c5d1SDavid du Colombier 	case OASHR:
6183e12c5d1SDavid du Colombier 	case OASLSHR:
6193e12c5d1SDavid du Colombier 	case OASASHL:
6203e12c5d1SDavid du Colombier 	case OASASHR:
6213e12c5d1SDavid du Colombier 		if(r->complex >= l->complex) {
6223e12c5d1SDavid du Colombier 			n->complex = l->complex + 2;
6233e12c5d1SDavid du Colombier 			if(r->complex > n->complex)
6243e12c5d1SDavid du Colombier 				n->complex = r->complex;
6253e12c5d1SDavid du Colombier 		} else {
6263e12c5d1SDavid du Colombier 			n->complex = r->complex + 2;
6273e12c5d1SDavid du Colombier 			if(l->complex > n->complex)
6283e12c5d1SDavid du Colombier 				n->complex = l->complex;
6293e12c5d1SDavid du Colombier 		}
6303e12c5d1SDavid du Colombier 		break;
6313e12c5d1SDavid du Colombier 
6323e12c5d1SDavid du Colombier 	case OADD:
6333e12c5d1SDavid du Colombier 	case OXOR:
6343e12c5d1SDavid du Colombier 	case OAND:
6353e12c5d1SDavid du Colombier 	case OOR:
6363e12c5d1SDavid du Colombier 		/*
6373e12c5d1SDavid du Colombier 		 * immediate operators, make const on right
6383e12c5d1SDavid du Colombier 		 */
6393e12c5d1SDavid du Colombier 		if(l->op == OCONST) {
6403e12c5d1SDavid du Colombier 			n->left = r;
6413e12c5d1SDavid du Colombier 			n->right = l;
6423e12c5d1SDavid du Colombier 		}
6433e12c5d1SDavid du Colombier 		break;
6443e12c5d1SDavid du Colombier 
6453e12c5d1SDavid du Colombier 	case OEQ:
6463e12c5d1SDavid du Colombier 	case ONE:
6473e12c5d1SDavid du Colombier 	case OLE:
6483e12c5d1SDavid du Colombier 	case OLT:
6493e12c5d1SDavid du Colombier 	case OGE:
6503e12c5d1SDavid du Colombier 	case OGT:
6513e12c5d1SDavid du Colombier 	case OHI:
6523e12c5d1SDavid du Colombier 	case OHS:
6533e12c5d1SDavid du Colombier 	case OLO:
6543e12c5d1SDavid du Colombier 	case OLS:
6553e12c5d1SDavid du Colombier 		/*
6563e12c5d1SDavid du Colombier 		 * compare operators, make const on left
6573e12c5d1SDavid du Colombier 		 */
6583e12c5d1SDavid du Colombier 		if(r->op == OCONST) {
6593e12c5d1SDavid du Colombier 			n->left = r;
6603e12c5d1SDavid du Colombier 			n->right = l;
6613e12c5d1SDavid du Colombier 			n->op = invrel[relindex(n->op)];
6623e12c5d1SDavid du Colombier 		}
6633e12c5d1SDavid du Colombier 		break;
6643e12c5d1SDavid du Colombier 	}
6653e12c5d1SDavid du Colombier }
6663e12c5d1SDavid du Colombier 
6673e12c5d1SDavid du Colombier void
6683e12c5d1SDavid du Colombier indx(Node *n)
6693e12c5d1SDavid du Colombier {
6703e12c5d1SDavid du Colombier 	Node *l, *r;
6713e12c5d1SDavid du Colombier 
6723e12c5d1SDavid du Colombier 	if(debug['x'])
6733e12c5d1SDavid du Colombier 		prtree(n, "indx");
6743e12c5d1SDavid du Colombier 
6753e12c5d1SDavid du Colombier 	l = n->left;
6763e12c5d1SDavid du Colombier 	r = n->right;
6773e12c5d1SDavid du Colombier 	if(l->addable == 1 || l->addable == 13) {
6783e12c5d1SDavid du Colombier 		n->right = l;
6793e12c5d1SDavid du Colombier 		n->left = r;
6803e12c5d1SDavid du Colombier 		l = r;
6813e12c5d1SDavid du Colombier 		r = n->right;
6823e12c5d1SDavid du Colombier 	}
6833e12c5d1SDavid du Colombier 	if(l->addable != 7) {
6843e12c5d1SDavid du Colombier 		idx.regtree = l;
6853e12c5d1SDavid du Colombier 		idx.scale = 1;
6863e12c5d1SDavid du Colombier 	} else
6873e12c5d1SDavid du Colombier 	if(l->right->addable == 20) {
6883e12c5d1SDavid du Colombier 		idx.regtree = l->left;
689*219b2ee8SDavid du Colombier 		idx.scale = 1 << l->right->vconst;
6903e12c5d1SDavid du Colombier 	} else
6913e12c5d1SDavid du Colombier 	if(l->left->addable == 20) {
6923e12c5d1SDavid du Colombier 		idx.regtree = l->right;
693*219b2ee8SDavid du Colombier 		idx.scale = 1 << l->left->vconst;
6943e12c5d1SDavid du Colombier 	} else
6953e12c5d1SDavid du Colombier 		diag(n, "bad index");
6963e12c5d1SDavid du Colombier 
6973e12c5d1SDavid du Colombier 	idx.basetree = r;
6983e12c5d1SDavid du Colombier 	if(debug['x']) {
6993e12c5d1SDavid du Colombier 		print("scale = %d\n", idx.scale);
7003e12c5d1SDavid du Colombier 		prtree(idx.regtree, "index");
7013e12c5d1SDavid du Colombier 		prtree(idx.basetree, "base");
7023e12c5d1SDavid du Colombier 	}
7033e12c5d1SDavid du Colombier }
7043e12c5d1SDavid du Colombier 
7053e12c5d1SDavid du Colombier void
7063e12c5d1SDavid du Colombier bcomplex(Node *n)
7073e12c5d1SDavid du Colombier {
7083e12c5d1SDavid du Colombier 
7093e12c5d1SDavid du Colombier 	complex(n);
7103e12c5d1SDavid du Colombier 	if(n->type != T)
7113e12c5d1SDavid du Colombier 	if(tcompat(n, T, n->type, tnot))
7123e12c5d1SDavid du Colombier 		n->type = T;
7133e12c5d1SDavid du Colombier 	if(n->type != T) {
714*219b2ee8SDavid du Colombier 		bool64(n);
7153e12c5d1SDavid du Colombier 		boolgen(n, 1, Z);
7163e12c5d1SDavid du Colombier 	} else
7173e12c5d1SDavid du Colombier 		gbranch(OGOTO);
7183e12c5d1SDavid du Colombier }
719