xref: /plan9/sys/src/cmd/vc/sgen.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1*3e12c5d1SDavid du Colombier #include "gc.h"
2*3e12c5d1SDavid du Colombier 
3*3e12c5d1SDavid du Colombier void
4*3e12c5d1SDavid du Colombier codgen(Node *n, Node *nn)
5*3e12c5d1SDavid du Colombier {
6*3e12c5d1SDavid du Colombier 	Prog *sp;
7*3e12c5d1SDavid du Colombier 	Node *n1, nod, nod1;
8*3e12c5d1SDavid du Colombier 
9*3e12c5d1SDavid du Colombier 	cursafe = 0;
10*3e12c5d1SDavid du Colombier 	curarg = 0;
11*3e12c5d1SDavid du Colombier 	maxargsafe = 0;
12*3e12c5d1SDavid du Colombier 
13*3e12c5d1SDavid du Colombier 	/*
14*3e12c5d1SDavid du Colombier 	 * isolate name
15*3e12c5d1SDavid du Colombier 	 */
16*3e12c5d1SDavid du Colombier 	for(n1 = nn;; n1 = n1->left) {
17*3e12c5d1SDavid du Colombier 		if(n1 == Z) {
18*3e12c5d1SDavid du Colombier 			diag(nn, "cant find function name");
19*3e12c5d1SDavid du Colombier 			return;
20*3e12c5d1SDavid du Colombier 		}
21*3e12c5d1SDavid du Colombier 		if(n1->op == ONAME)
22*3e12c5d1SDavid du Colombier 			break;
23*3e12c5d1SDavid du Colombier 	}
24*3e12c5d1SDavid du Colombier 	nearln = nn->lineno;
25*3e12c5d1SDavid du Colombier 	gpseudo(ATEXT, n1->sym, nodconst(stkoff));
26*3e12c5d1SDavid du Colombier 	sp = p;
27*3e12c5d1SDavid du Colombier 
28*3e12c5d1SDavid du Colombier 	/*
29*3e12c5d1SDavid du Colombier 	 * isolate first argument
30*3e12c5d1SDavid du Colombier 	 */
31*3e12c5d1SDavid du Colombier 	if(REGARG) {
32*3e12c5d1SDavid du Colombier 		if(typesu[thisfn->link->etype]) {
33*3e12c5d1SDavid du Colombier 			nod1 = *nodret->left;
34*3e12c5d1SDavid du Colombier 			nodreg(&nod, &nod1, REGARG);
35*3e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, &nod1);
36*3e12c5d1SDavid du Colombier 		} else
37*3e12c5d1SDavid du Colombier 		if(firstarg && typechlp[firstargtype->etype]) {
38*3e12c5d1SDavid du Colombier 			nod1 = *nodret->left;
39*3e12c5d1SDavid du Colombier 			nod1.sym = firstarg;
40*3e12c5d1SDavid du Colombier 			nod1.type = firstargtype;
41*3e12c5d1SDavid du Colombier 			if(firstargtype->width < tint->width)
42*3e12c5d1SDavid du Colombier 				nod1.offset += endian(firstargtype->width);
43*3e12c5d1SDavid du Colombier 			nod1.etype = firstargtype->etype;
44*3e12c5d1SDavid du Colombier 			nodreg(&nod, &nod1, REGARG);
45*3e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, &nod1);
46*3e12c5d1SDavid du Colombier 		}
47*3e12c5d1SDavid du Colombier 	}
48*3e12c5d1SDavid du Colombier 
49*3e12c5d1SDavid du Colombier 	retok = 0;
50*3e12c5d1SDavid du Colombier 	gen(n);
51*3e12c5d1SDavid du Colombier 	if(!retok)
52*3e12c5d1SDavid du Colombier 		if(thisfn->link->etype != TVOID)
53*3e12c5d1SDavid du Colombier 			warn(Z, "no return at end of function: %s", n1->sym->name);
54*3e12c5d1SDavid du Colombier 	noretval(3);
55*3e12c5d1SDavid du Colombier 	gbranch(ORETURN);
56*3e12c5d1SDavid du Colombier 
57*3e12c5d1SDavid du Colombier 	if(!debug['N'] || debug['R'] || debug['P'])
58*3e12c5d1SDavid du Colombier 		regopt(sp);
59*3e12c5d1SDavid du Colombier 
60*3e12c5d1SDavid du Colombier 	sp->to.offset += maxargsafe;
61*3e12c5d1SDavid du Colombier }
62*3e12c5d1SDavid du Colombier 
63*3e12c5d1SDavid du Colombier void
64*3e12c5d1SDavid du Colombier gen(Node *n)
65*3e12c5d1SDavid du Colombier {
66*3e12c5d1SDavid du Colombier 	Node *l, nod;
67*3e12c5d1SDavid du Colombier 	Prog *sp, *spc, *spb;
68*3e12c5d1SDavid du Colombier 	Case *cn;
69*3e12c5d1SDavid du Colombier 	long sbc, scc;
70*3e12c5d1SDavid du Colombier 	int o;
71*3e12c5d1SDavid du Colombier 
72*3e12c5d1SDavid du Colombier loop:
73*3e12c5d1SDavid du Colombier 	if(n == Z)
74*3e12c5d1SDavid du Colombier 		return;
75*3e12c5d1SDavid du Colombier 	nearln = n->lineno;
76*3e12c5d1SDavid du Colombier 	o = n->op;
77*3e12c5d1SDavid du Colombier 	if(debug['G'])
78*3e12c5d1SDavid du Colombier 		if(o != OLIST)
79*3e12c5d1SDavid du Colombier 			print("%L %O\n", nearln, o);
80*3e12c5d1SDavid du Colombier 
81*3e12c5d1SDavid du Colombier 	retok = 0;
82*3e12c5d1SDavid du Colombier 	switch(o) {
83*3e12c5d1SDavid du Colombier 
84*3e12c5d1SDavid du Colombier 	default:
85*3e12c5d1SDavid du Colombier 		complex(n);
86*3e12c5d1SDavid du Colombier 		cgen(n, Z);
87*3e12c5d1SDavid du Colombier 		break;
88*3e12c5d1SDavid du Colombier 
89*3e12c5d1SDavid du Colombier 	case OLIST:
90*3e12c5d1SDavid du Colombier 		gen(n->left);
91*3e12c5d1SDavid du Colombier 
92*3e12c5d1SDavid du Colombier 	rloop:
93*3e12c5d1SDavid du Colombier 		n = n->right;
94*3e12c5d1SDavid du Colombier 		goto loop;
95*3e12c5d1SDavid du Colombier 
96*3e12c5d1SDavid du Colombier 	case ORETURN:
97*3e12c5d1SDavid du Colombier 		retok = 1;
98*3e12c5d1SDavid du Colombier 		complex(n);
99*3e12c5d1SDavid du Colombier 		if(n->type == T)
100*3e12c5d1SDavid du Colombier 			break;
101*3e12c5d1SDavid du Colombier 		l = n->left;
102*3e12c5d1SDavid du Colombier 		if(l == Z) {
103*3e12c5d1SDavid du Colombier 			noretval(3);
104*3e12c5d1SDavid du Colombier 			gbranch(ORETURN);
105*3e12c5d1SDavid du Colombier 			break;
106*3e12c5d1SDavid du Colombier 		}
107*3e12c5d1SDavid du Colombier 		if(typesu[n->type->etype]) {
108*3e12c5d1SDavid du Colombier 			sugen(l, nodret, n->type->width);
109*3e12c5d1SDavid du Colombier 			noretval(3);
110*3e12c5d1SDavid du Colombier 			gbranch(ORETURN);
111*3e12c5d1SDavid du Colombier 			break;
112*3e12c5d1SDavid du Colombier 		}
113*3e12c5d1SDavid du Colombier 		regret(&nod, n);
114*3e12c5d1SDavid du Colombier 		cgen(l, &nod);
115*3e12c5d1SDavid du Colombier 		regfree(&nod);
116*3e12c5d1SDavid du Colombier 		if(typefdv[n->type->etype])
117*3e12c5d1SDavid du Colombier 			noretval(1);
118*3e12c5d1SDavid du Colombier 		else
119*3e12c5d1SDavid du Colombier 			noretval(2);
120*3e12c5d1SDavid du Colombier 		gbranch(ORETURN);
121*3e12c5d1SDavid du Colombier 		break;
122*3e12c5d1SDavid du Colombier 
123*3e12c5d1SDavid du Colombier 	case OLABEL:
124*3e12c5d1SDavid du Colombier 		l = n->left;
125*3e12c5d1SDavid du Colombier 		if(l) {
126*3e12c5d1SDavid du Colombier 			l->offset = pc;
127*3e12c5d1SDavid du Colombier 			if(l->label)
128*3e12c5d1SDavid du Colombier 				patch(l->label, pc);
129*3e12c5d1SDavid du Colombier 		}
130*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);	/* prevent self reference in reg */
131*3e12c5d1SDavid du Colombier 		patch(p, pc);
132*3e12c5d1SDavid du Colombier 		goto rloop;
133*3e12c5d1SDavid du Colombier 
134*3e12c5d1SDavid du Colombier 	case OGOTO:
135*3e12c5d1SDavid du Colombier 		retok = 1;
136*3e12c5d1SDavid du Colombier 		n = n->left;
137*3e12c5d1SDavid du Colombier 		if(n == Z)
138*3e12c5d1SDavid du Colombier 			return;
139*3e12c5d1SDavid du Colombier 		if(n->complex == 0) {
140*3e12c5d1SDavid du Colombier 			diag(Z, "label undefined: %s", n->sym->name);
141*3e12c5d1SDavid du Colombier 			return;
142*3e12c5d1SDavid du Colombier 		}
143*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
144*3e12c5d1SDavid du Colombier 		if(n->offset) {
145*3e12c5d1SDavid du Colombier 			patch(p, n->offset);
146*3e12c5d1SDavid du Colombier 			return;
147*3e12c5d1SDavid du Colombier 		}
148*3e12c5d1SDavid du Colombier 		if(n->label)
149*3e12c5d1SDavid du Colombier 			patch(n->label, pc-1);
150*3e12c5d1SDavid du Colombier 		n->label = p;
151*3e12c5d1SDavid du Colombier 		return;
152*3e12c5d1SDavid du Colombier 
153*3e12c5d1SDavid du Colombier 	case OCASE:
154*3e12c5d1SDavid du Colombier 		l = n->left;
155*3e12c5d1SDavid du Colombier 		if(cases == C)
156*3e12c5d1SDavid du Colombier 			diag(n, "case/default outside a switch");
157*3e12c5d1SDavid du Colombier 		if(l == Z) {
158*3e12c5d1SDavid du Colombier 			cas();
159*3e12c5d1SDavid du Colombier 			cases->val = 0;
160*3e12c5d1SDavid du Colombier 			cases->def = 1;
161*3e12c5d1SDavid du Colombier 			cases->label = pc;
162*3e12c5d1SDavid du Colombier 			goto rloop;
163*3e12c5d1SDavid du Colombier 		}
164*3e12c5d1SDavid du Colombier 		complex(l);
165*3e12c5d1SDavid du Colombier 		if(l->type == T)
166*3e12c5d1SDavid du Colombier 			goto rloop;
167*3e12c5d1SDavid du Colombier 		if(l->op == OCONST)
168*3e12c5d1SDavid du Colombier 		if(typechl[l->type->etype]) {
169*3e12c5d1SDavid du Colombier 			cas();
170*3e12c5d1SDavid du Colombier 			cases->val = l->offset;
171*3e12c5d1SDavid du Colombier 			cases->def = 0;
172*3e12c5d1SDavid du Colombier 			cases->label = pc;
173*3e12c5d1SDavid du Colombier 			goto rloop;
174*3e12c5d1SDavid du Colombier 		}
175*3e12c5d1SDavid du Colombier 		diag(n, "case expression must be integer constant");
176*3e12c5d1SDavid du Colombier 		goto rloop;
177*3e12c5d1SDavid du Colombier 
178*3e12c5d1SDavid du Colombier 	case OSWITCH:
179*3e12c5d1SDavid du Colombier 		l = n->left;
180*3e12c5d1SDavid du Colombier 		complex(l);
181*3e12c5d1SDavid du Colombier 		if(l->type == T)
182*3e12c5d1SDavid du Colombier 			break;
183*3e12c5d1SDavid du Colombier 		if(!typechl[l->type->etype]) {
184*3e12c5d1SDavid du Colombier 			diag(n, "switch expression must be integer");
185*3e12c5d1SDavid du Colombier 			break;
186*3e12c5d1SDavid du Colombier 		}
187*3e12c5d1SDavid du Colombier 
188*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);		/* entry */
189*3e12c5d1SDavid du Colombier 		sp = p;
190*3e12c5d1SDavid du Colombier 
191*3e12c5d1SDavid du Colombier 		cn = cases;
192*3e12c5d1SDavid du Colombier 		cases = C;
193*3e12c5d1SDavid du Colombier 		cas();
194*3e12c5d1SDavid du Colombier 
195*3e12c5d1SDavid du Colombier 		sbc = breakpc;
196*3e12c5d1SDavid du Colombier 		breakpc = pc;
197*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
198*3e12c5d1SDavid du Colombier 		spb = p;
199*3e12c5d1SDavid du Colombier 
200*3e12c5d1SDavid du Colombier 		gen(n->right);
201*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
202*3e12c5d1SDavid du Colombier 		patch(p, breakpc);
203*3e12c5d1SDavid du Colombier 
204*3e12c5d1SDavid du Colombier 		patch(sp, pc);
205*3e12c5d1SDavid du Colombier 		regalloc(&nod, l, Z);
206*3e12c5d1SDavid du Colombier 		nod.type = types[TLONG];
207*3e12c5d1SDavid du Colombier 		cgen(l, &nod);
208*3e12c5d1SDavid du Colombier 		doswit(&nod);
209*3e12c5d1SDavid du Colombier 		regfree(&nod);
210*3e12c5d1SDavid du Colombier 		patch(spb, pc);
211*3e12c5d1SDavid du Colombier 
212*3e12c5d1SDavid du Colombier 		cases = cn;
213*3e12c5d1SDavid du Colombier 		breakpc = sbc;
214*3e12c5d1SDavid du Colombier 		break;
215*3e12c5d1SDavid du Colombier 
216*3e12c5d1SDavid du Colombier 	case OWHILE:
217*3e12c5d1SDavid du Colombier 	case ODWHILE:
218*3e12c5d1SDavid du Colombier 		l = n->left;
219*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);		/* entry */
220*3e12c5d1SDavid du Colombier 		sp = p;
221*3e12c5d1SDavid du Colombier 
222*3e12c5d1SDavid du Colombier 		scc = continpc;
223*3e12c5d1SDavid du Colombier 		continpc = pc;
224*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
225*3e12c5d1SDavid du Colombier 		spc = p;
226*3e12c5d1SDavid du Colombier 
227*3e12c5d1SDavid du Colombier 		sbc = breakpc;
228*3e12c5d1SDavid du Colombier 		breakpc = pc;
229*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
230*3e12c5d1SDavid du Colombier 		spb = p;
231*3e12c5d1SDavid du Colombier 
232*3e12c5d1SDavid du Colombier 		patch(spc, pc);
233*3e12c5d1SDavid du Colombier 		if(n->op == OWHILE)
234*3e12c5d1SDavid du Colombier 			patch(sp, pc);
235*3e12c5d1SDavid du Colombier 		bcomplex(l);		/* test */
236*3e12c5d1SDavid du Colombier 		patch(p, breakpc);
237*3e12c5d1SDavid du Colombier 
238*3e12c5d1SDavid du Colombier 		if(n->op == ODWHILE)
239*3e12c5d1SDavid du Colombier 			patch(sp, pc);
240*3e12c5d1SDavid du Colombier 		gen(n->right);		/* body */
241*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
242*3e12c5d1SDavid du Colombier 		patch(p, continpc);
243*3e12c5d1SDavid du Colombier 
244*3e12c5d1SDavid du Colombier 		patch(spb, pc);
245*3e12c5d1SDavid du Colombier 		continpc = scc;
246*3e12c5d1SDavid du Colombier 		breakpc = sbc;
247*3e12c5d1SDavid du Colombier 		break;
248*3e12c5d1SDavid du Colombier 
249*3e12c5d1SDavid du Colombier 	case OFOR:
250*3e12c5d1SDavid du Colombier 		l = n->left;
251*3e12c5d1SDavid du Colombier 		gen(l->right->left);	/* init */
252*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);		/* entry */
253*3e12c5d1SDavid du Colombier 		sp = p;
254*3e12c5d1SDavid du Colombier 
255*3e12c5d1SDavid du Colombier 		scc = continpc;
256*3e12c5d1SDavid du Colombier 		continpc = pc;
257*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
258*3e12c5d1SDavid du Colombier 		spc = p;
259*3e12c5d1SDavid du Colombier 
260*3e12c5d1SDavid du Colombier 		sbc = breakpc;
261*3e12c5d1SDavid du Colombier 		breakpc = pc;
262*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
263*3e12c5d1SDavid du Colombier 		spb = p;
264*3e12c5d1SDavid du Colombier 
265*3e12c5d1SDavid du Colombier 		patch(spc, pc);
266*3e12c5d1SDavid du Colombier 		gen(l->right->right);	/* inc */
267*3e12c5d1SDavid du Colombier 		patch(sp, pc);
268*3e12c5d1SDavid du Colombier 		if(l->left != Z) {	/* test */
269*3e12c5d1SDavid du Colombier 			bcomplex(l->left);
270*3e12c5d1SDavid du Colombier 			patch(p, breakpc);
271*3e12c5d1SDavid du Colombier 		}
272*3e12c5d1SDavid du Colombier 		gen(n->right);		/* body */
273*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
274*3e12c5d1SDavid du Colombier 		patch(p, continpc);
275*3e12c5d1SDavid du Colombier 
276*3e12c5d1SDavid du Colombier 		patch(spb, pc);
277*3e12c5d1SDavid du Colombier 		continpc = scc;
278*3e12c5d1SDavid du Colombier 		breakpc = sbc;
279*3e12c5d1SDavid du Colombier 		break;
280*3e12c5d1SDavid du Colombier 
281*3e12c5d1SDavid du Colombier 	case OCONTINUE:
282*3e12c5d1SDavid du Colombier 		if(continpc < 0) {
283*3e12c5d1SDavid du Colombier 			diag(n, "continue not in a loop");
284*3e12c5d1SDavid du Colombier 			break;
285*3e12c5d1SDavid du Colombier 		}
286*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
287*3e12c5d1SDavid du Colombier 		patch(p, continpc);
288*3e12c5d1SDavid du Colombier 		break;
289*3e12c5d1SDavid du Colombier 
290*3e12c5d1SDavid du Colombier 	case OBREAK:
291*3e12c5d1SDavid du Colombier 		if(breakpc < 0) {
292*3e12c5d1SDavid du Colombier 			diag(n, "break not in a loop");
293*3e12c5d1SDavid du Colombier 			break;
294*3e12c5d1SDavid du Colombier 		}
295*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
296*3e12c5d1SDavid du Colombier 		patch(p, breakpc);
297*3e12c5d1SDavid du Colombier 		break;
298*3e12c5d1SDavid du Colombier 
299*3e12c5d1SDavid du Colombier 	case OIF:
300*3e12c5d1SDavid du Colombier 		l = n->left;
301*3e12c5d1SDavid du Colombier 		bcomplex(l);
302*3e12c5d1SDavid du Colombier 		sp = p;
303*3e12c5d1SDavid du Colombier 		if(n->right->left != Z)
304*3e12c5d1SDavid du Colombier 			gen(n->right->left);
305*3e12c5d1SDavid du Colombier 		if(n->right->right != Z) {
306*3e12c5d1SDavid du Colombier 			gbranch(OGOTO);
307*3e12c5d1SDavid du Colombier 			patch(sp, pc);
308*3e12c5d1SDavid du Colombier 			sp = p;
309*3e12c5d1SDavid du Colombier 			gen(n->right->right);
310*3e12c5d1SDavid du Colombier 		}
311*3e12c5d1SDavid du Colombier 		patch(sp, pc);
312*3e12c5d1SDavid du Colombier 		break;
313*3e12c5d1SDavid du Colombier 
314*3e12c5d1SDavid du Colombier 	case OSET:
315*3e12c5d1SDavid du Colombier 	case OUSED:
316*3e12c5d1SDavid du Colombier 		n = n->left;
317*3e12c5d1SDavid du Colombier 		for(;;) {
318*3e12c5d1SDavid du Colombier 			if(n->op == OLIST) {
319*3e12c5d1SDavid du Colombier 				l = n->right;
320*3e12c5d1SDavid du Colombier 				n = n->left;
321*3e12c5d1SDavid du Colombier 				complex(l);
322*3e12c5d1SDavid du Colombier 				if(l->op == ONAME) {
323*3e12c5d1SDavid du Colombier 					if(o == OSET)
324*3e12c5d1SDavid du Colombier 						gins(ANOP, Z, l);
325*3e12c5d1SDavid du Colombier 					else
326*3e12c5d1SDavid du Colombier 						gins(ANOP, l, Z);
327*3e12c5d1SDavid du Colombier 				}
328*3e12c5d1SDavid du Colombier 			} else {
329*3e12c5d1SDavid du Colombier 				complex(n);
330*3e12c5d1SDavid du Colombier 				if(n->op == ONAME) {
331*3e12c5d1SDavid du Colombier 					if(o == OSET)
332*3e12c5d1SDavid du Colombier 						gins(ANOP, Z, n);
333*3e12c5d1SDavid du Colombier 					else
334*3e12c5d1SDavid du Colombier 						gins(ANOP, n, Z);
335*3e12c5d1SDavid du Colombier 				}
336*3e12c5d1SDavid du Colombier 				break;
337*3e12c5d1SDavid du Colombier 			}
338*3e12c5d1SDavid du Colombier 		}
339*3e12c5d1SDavid du Colombier 		break;
340*3e12c5d1SDavid du Colombier 	}
341*3e12c5d1SDavid du Colombier }
342*3e12c5d1SDavid du Colombier 
343*3e12c5d1SDavid du Colombier void
344*3e12c5d1SDavid du Colombier noretval(int n)
345*3e12c5d1SDavid du Colombier {
346*3e12c5d1SDavid du Colombier 
347*3e12c5d1SDavid du Colombier 	if(n & 1) {
348*3e12c5d1SDavid du Colombier 		gins(ANOP, Z, Z);
349*3e12c5d1SDavid du Colombier 		p->to.type = D_REG;
350*3e12c5d1SDavid du Colombier 		p->to.reg = REGRET;
351*3e12c5d1SDavid du Colombier 	}
352*3e12c5d1SDavid du Colombier 	if(n & 2) {
353*3e12c5d1SDavid du Colombier 		gins(ANOP, Z, Z);
354*3e12c5d1SDavid du Colombier 		p->to.type = D_FREG;
355*3e12c5d1SDavid du Colombier 		p->to.reg = FREGRET;
356*3e12c5d1SDavid du Colombier 	}
357*3e12c5d1SDavid du Colombier }
358*3e12c5d1SDavid du Colombier 
359*3e12c5d1SDavid du Colombier /*
360*3e12c5d1SDavid du Colombier  *	calculate addressability as follows
361*3e12c5d1SDavid du Colombier  *		CONST ==> 20		$value
362*3e12c5d1SDavid du Colombier  *		NAME ==> 10		name
363*3e12c5d1SDavid du Colombier  *		REGISTER ==> 11		register
364*3e12c5d1SDavid du Colombier  *		INDREG ==> 12		*[(reg)+offset]
365*3e12c5d1SDavid du Colombier  *		&10 ==> 2		$name
366*3e12c5d1SDavid du Colombier  *		ADD(2, 20) ==> 2	$name+offset
367*3e12c5d1SDavid du Colombier  *		ADD(3, 20) ==> 3	$(reg)+offset
368*3e12c5d1SDavid du Colombier  *		&12 ==> 3		$(reg)+offset
369*3e12c5d1SDavid du Colombier  *		*11 ==> 11		??
370*3e12c5d1SDavid du Colombier  *		*2 ==> 10		name
371*3e12c5d1SDavid du Colombier  *		*3 ==> 12		*(reg)+offset
372*3e12c5d1SDavid du Colombier  *	calculate complexity (number of registers)
373*3e12c5d1SDavid du Colombier  */
374*3e12c5d1SDavid du Colombier void
375*3e12c5d1SDavid du Colombier xcom(Node *n)
376*3e12c5d1SDavid du Colombier {
377*3e12c5d1SDavid du Colombier 	Node *l, *r;
378*3e12c5d1SDavid du Colombier 	int t;
379*3e12c5d1SDavid du Colombier 
380*3e12c5d1SDavid du Colombier 	if(n == Z)
381*3e12c5d1SDavid du Colombier 		return;
382*3e12c5d1SDavid du Colombier 	l = n->left;
383*3e12c5d1SDavid du Colombier 	r = n->right;
384*3e12c5d1SDavid du Colombier 	n->addable = 0;
385*3e12c5d1SDavid du Colombier 	n->complex = 0;
386*3e12c5d1SDavid du Colombier 	switch(n->op) {
387*3e12c5d1SDavid du Colombier 	case OCONST:
388*3e12c5d1SDavid du Colombier 		n->addable = 20;
389*3e12c5d1SDavid du Colombier 		return;
390*3e12c5d1SDavid du Colombier 
391*3e12c5d1SDavid du Colombier 	case OREGISTER:
392*3e12c5d1SDavid du Colombier 		n->addable = 11;
393*3e12c5d1SDavid du Colombier 		return;
394*3e12c5d1SDavid du Colombier 
395*3e12c5d1SDavid du Colombier 	case OINDREG:
396*3e12c5d1SDavid du Colombier 		n->addable = 12;
397*3e12c5d1SDavid du Colombier 		return;
398*3e12c5d1SDavid du Colombier 
399*3e12c5d1SDavid du Colombier 	case ONAME:
400*3e12c5d1SDavid du Colombier 		n->addable = 10;
401*3e12c5d1SDavid du Colombier 		return;
402*3e12c5d1SDavid du Colombier 
403*3e12c5d1SDavid du Colombier 	case OADDR:
404*3e12c5d1SDavid du Colombier 		xcom(l);
405*3e12c5d1SDavid du Colombier 		if(l->addable == 10)
406*3e12c5d1SDavid du Colombier 			n->addable = 2;
407*3e12c5d1SDavid du Colombier 		if(l->addable == 12)
408*3e12c5d1SDavid du Colombier 			n->addable = 3;
409*3e12c5d1SDavid du Colombier 		break;
410*3e12c5d1SDavid du Colombier 
411*3e12c5d1SDavid du Colombier 	case OIND:
412*3e12c5d1SDavid du Colombier 		xcom(l);
413*3e12c5d1SDavid du Colombier 		if(l->addable == 11)
414*3e12c5d1SDavid du Colombier 			n->addable = 12;
415*3e12c5d1SDavid du Colombier 		if(l->addable == 3)
416*3e12c5d1SDavid du Colombier 			n->addable = 12;
417*3e12c5d1SDavid du Colombier 		if(l->addable == 2)
418*3e12c5d1SDavid du Colombier 			n->addable = 10;
419*3e12c5d1SDavid du Colombier 		break;
420*3e12c5d1SDavid du Colombier 
421*3e12c5d1SDavid du Colombier 	case OADD:
422*3e12c5d1SDavid du Colombier 		xcom(l);
423*3e12c5d1SDavid du Colombier 		xcom(r);
424*3e12c5d1SDavid du Colombier 		if(l->addable == 20) {
425*3e12c5d1SDavid du Colombier 			if(r->addable == 2)
426*3e12c5d1SDavid du Colombier 				n->addable = 2;
427*3e12c5d1SDavid du Colombier 			if(r->addable == 3)
428*3e12c5d1SDavid du Colombier 				n->addable = 3;
429*3e12c5d1SDavid du Colombier 		}
430*3e12c5d1SDavid du Colombier 		if(r->addable == 20) {
431*3e12c5d1SDavid du Colombier 			if(l->addable == 2)
432*3e12c5d1SDavid du Colombier 				n->addable = 2;
433*3e12c5d1SDavid du Colombier 			if(l->addable == 3)
434*3e12c5d1SDavid du Colombier 				n->addable = 3;
435*3e12c5d1SDavid du Colombier 		}
436*3e12c5d1SDavid du Colombier 		break;
437*3e12c5d1SDavid du Colombier 
438*3e12c5d1SDavid du Colombier 	case OASLMUL:
439*3e12c5d1SDavid du Colombier 	case OASMUL:
440*3e12c5d1SDavid du Colombier 		xcom(l);
441*3e12c5d1SDavid du Colombier 		xcom(r);
442*3e12c5d1SDavid du Colombier 		t = vlog(r);
443*3e12c5d1SDavid du Colombier 		if(t >= 0) {
444*3e12c5d1SDavid du Colombier 			n->op = OASASHL;
445*3e12c5d1SDavid du Colombier 			r->offset = t;
446*3e12c5d1SDavid du Colombier 		}
447*3e12c5d1SDavid du Colombier 		break;
448*3e12c5d1SDavid du Colombier 
449*3e12c5d1SDavid du Colombier 	case OMUL:
450*3e12c5d1SDavid du Colombier 	case OLMUL:
451*3e12c5d1SDavid du Colombier 		xcom(l);
452*3e12c5d1SDavid du Colombier 		xcom(r);
453*3e12c5d1SDavid du Colombier 		t = vlog(r);
454*3e12c5d1SDavid du Colombier 		if(t >= 0) {
455*3e12c5d1SDavid du Colombier 			n->op = OASHL;
456*3e12c5d1SDavid du Colombier 			r->offset = t;
457*3e12c5d1SDavid du Colombier 		}
458*3e12c5d1SDavid du Colombier 		t = vlog(l);
459*3e12c5d1SDavid du Colombier 		if(t >= 0) {
460*3e12c5d1SDavid du Colombier 			n->op = OASHL;
461*3e12c5d1SDavid du Colombier 			n->left = r;
462*3e12c5d1SDavid du Colombier 			n->right = l;
463*3e12c5d1SDavid du Colombier 			r = l;
464*3e12c5d1SDavid du Colombier 			l = n->left;
465*3e12c5d1SDavid du Colombier 			r->offset = t;
466*3e12c5d1SDavid du Colombier 		}
467*3e12c5d1SDavid du Colombier 		break;
468*3e12c5d1SDavid du Colombier 
469*3e12c5d1SDavid du Colombier 	case OASLDIV:
470*3e12c5d1SDavid du Colombier 		xcom(l);
471*3e12c5d1SDavid du Colombier 		xcom(r);
472*3e12c5d1SDavid du Colombier 		t = vlog(r);
473*3e12c5d1SDavid du Colombier 		if(t >= 0) {
474*3e12c5d1SDavid du Colombier 			n->op = OASLSHR;
475*3e12c5d1SDavid du Colombier 			r->offset = t;
476*3e12c5d1SDavid du Colombier 		}
477*3e12c5d1SDavid du Colombier 		break;
478*3e12c5d1SDavid du Colombier 
479*3e12c5d1SDavid du Colombier 	case OLDIV:
480*3e12c5d1SDavid du Colombier 		xcom(l);
481*3e12c5d1SDavid du Colombier 		xcom(r);
482*3e12c5d1SDavid du Colombier 		t = vlog(r);
483*3e12c5d1SDavid du Colombier 		if(t >= 0) {
484*3e12c5d1SDavid du Colombier 			n->op = OLSHR;
485*3e12c5d1SDavid du Colombier 			r->offset = t;
486*3e12c5d1SDavid du Colombier 		}
487*3e12c5d1SDavid du Colombier 		break;
488*3e12c5d1SDavid du Colombier 
489*3e12c5d1SDavid du Colombier 	case OASLMOD:
490*3e12c5d1SDavid du Colombier 		xcom(l);
491*3e12c5d1SDavid du Colombier 		xcom(r);
492*3e12c5d1SDavid du Colombier 		t = vlog(r);
493*3e12c5d1SDavid du Colombier 		if(t >= 0) {
494*3e12c5d1SDavid du Colombier 			n->op = OASAND;
495*3e12c5d1SDavid du Colombier 			r->offset--;
496*3e12c5d1SDavid du Colombier 		}
497*3e12c5d1SDavid du Colombier 		break;
498*3e12c5d1SDavid du Colombier 
499*3e12c5d1SDavid du Colombier 	case OLMOD:
500*3e12c5d1SDavid du Colombier 		xcom(l);
501*3e12c5d1SDavid du Colombier 		xcom(r);
502*3e12c5d1SDavid du Colombier 		t = vlog(r);
503*3e12c5d1SDavid du Colombier 		if(t >= 0) {
504*3e12c5d1SDavid du Colombier 			n->op = OAND;
505*3e12c5d1SDavid du Colombier 			r->offset--;
506*3e12c5d1SDavid du Colombier 		}
507*3e12c5d1SDavid du Colombier 		break;
508*3e12c5d1SDavid du Colombier 
509*3e12c5d1SDavid du Colombier 	default:
510*3e12c5d1SDavid du Colombier 		if(l != Z)
511*3e12c5d1SDavid du Colombier 			xcom(l);
512*3e12c5d1SDavid du Colombier 		if(r != Z)
513*3e12c5d1SDavid du Colombier 			xcom(r);
514*3e12c5d1SDavid du Colombier 		break;
515*3e12c5d1SDavid du Colombier 	}
516*3e12c5d1SDavid du Colombier 	if(n->addable >= 10)
517*3e12c5d1SDavid du Colombier 		return;
518*3e12c5d1SDavid du Colombier 	if(l != Z)
519*3e12c5d1SDavid du Colombier 		n->complex = l->complex;
520*3e12c5d1SDavid du Colombier 	if(r != Z) {
521*3e12c5d1SDavid du Colombier 		if(r->complex == n->complex)
522*3e12c5d1SDavid du Colombier 			n->complex = r->complex+1; else
523*3e12c5d1SDavid du Colombier 		if(r->complex > n->complex)
524*3e12c5d1SDavid du Colombier 			n->complex = r->complex;
525*3e12c5d1SDavid du Colombier 	}
526*3e12c5d1SDavid du Colombier 	if(n->complex == 0)
527*3e12c5d1SDavid du Colombier 		n->complex++;
528*3e12c5d1SDavid du Colombier 	switch(n->op) {
529*3e12c5d1SDavid du Colombier 
530*3e12c5d1SDavid du Colombier 	case OFUNC:
531*3e12c5d1SDavid du Colombier 		n->complex = FNX;
532*3e12c5d1SDavid du Colombier 		break;
533*3e12c5d1SDavid du Colombier 
534*3e12c5d1SDavid du Colombier 	case OADD:
535*3e12c5d1SDavid du Colombier 	case OXOR:
536*3e12c5d1SDavid du Colombier 	case OAND:
537*3e12c5d1SDavid du Colombier 	case OOR:
538*3e12c5d1SDavid du Colombier 	case OEQ:
539*3e12c5d1SDavid du Colombier 	case ONE:
540*3e12c5d1SDavid du Colombier 		/*
541*3e12c5d1SDavid du Colombier 		 * immediate operators, make const on right
542*3e12c5d1SDavid du Colombier 		 */
543*3e12c5d1SDavid du Colombier 		if(l->op == OCONST) {
544*3e12c5d1SDavid du Colombier 			n->left = r;
545*3e12c5d1SDavid du Colombier 			n->right = l;
546*3e12c5d1SDavid du Colombier 		}
547*3e12c5d1SDavid du Colombier 		break;
548*3e12c5d1SDavid du Colombier 	}
549*3e12c5d1SDavid du Colombier }
550*3e12c5d1SDavid du Colombier 
551*3e12c5d1SDavid du Colombier void
552*3e12c5d1SDavid du Colombier bcomplex(Node *n)
553*3e12c5d1SDavid du Colombier {
554*3e12c5d1SDavid du Colombier 
555*3e12c5d1SDavid du Colombier 	complex(n);
556*3e12c5d1SDavid du Colombier 	if(n->type != T)
557*3e12c5d1SDavid du Colombier 	if(tcompat(n, T, n->type, tnot))
558*3e12c5d1SDavid du Colombier 		n->type = T;
559*3e12c5d1SDavid du Colombier 	if(n->type != T) {
560*3e12c5d1SDavid du Colombier 		boolgen(n, 1, Z);
561*3e12c5d1SDavid du Colombier 	} else
562*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
563*3e12c5d1SDavid du Colombier }
564