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