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