xref: /plan9-contrib/sys/src/cmd/4c/cgen.c (revision cd2352d6608a4808c4d45036d1b19a92b395369d)
1 #include "gc.h"
2 
3 static void genasop(int, Node*, Node*, Node*);
4 
5 void
cgen(Node * n,Node * nn)6 cgen(Node *n, Node *nn)
7 {
8 	Node *l, *r;
9 	Prog *p1;
10 	Node nod, nod1, nod2, nod3, nod4;
11 	int o;
12 	long v, curs;
13 
14 	if(debug['g']) {
15 		prtree(nn, "cgen lhs");
16 		prtree(n, "cgen");
17 	}
18 	if(n == Z || n->type == T)
19 		return;
20 	if(typesu[n->type->etype]) {
21 		sugen(n, nn, n->type->width);
22 		return;
23 	}
24 	l = n->left;
25 	r = n->right;
26 	o = n->op;
27 	if(n->addable >= INDEXED) {
28 		if(nn == Z) {
29 			switch(o) {
30 			default:
31 				nullwarn(Z, Z);
32 				break;
33 			case OINDEX:
34 				nullwarn(l, r);
35 				break;
36 			}
37 			return;
38 		}
39 		gmove(n, nn);
40 		return;
41 	}
42 	curs = cursafe;
43 
44 	if(n->complex >= FNX)
45 	if(l->complex >= FNX)
46 	if(r != Z && r->complex >= FNX)
47 	switch(o) {
48 	default:
49 		regret(&nod, r);
50 		cgen(r, &nod);
51 
52 		regsalloc(&nod1, r);
53 		gopcode(OAS, &nod, Z, &nod1);
54 
55 		regfree(&nod);
56 		nod = *n;
57 		nod.right = &nod1;
58 		cgen(&nod, nn);
59 		return;
60 
61 	case OFUNC:
62 	case OCOMMA:
63 	case OANDAND:
64 	case OOROR:
65 	case OCOND:
66 	case ODOT:
67 		break;
68 	}
69 
70 	switch(o) {
71 	default:
72 		diag(n, "unknown op in cgen: %O", o);
73 		break;
74 
75 	case OAS:
76 		if(l->op == OBIT)
77 			goto bitas;
78 		if(l->addable >= INDEXED && l->complex < FNX) {
79 			if(nn != Z || r->addable < INDEXED) {
80 				if(r->complex >= FNX && nn == Z)
81 					regret(&nod, r);
82 				else
83 					regalloc(&nod, r, nn);
84 				cgen(r, &nod);
85 				gmove(&nod, l);
86 				if(nn != Z)
87 					gmove(&nod, nn);
88 				regfree(&nod);
89 			} else
90 				gmove(r, l);
91 			break;
92 		}
93 		if(l->complex >= r->complex) {
94 			reglcgen(&nod1, l, Z);
95 			if(r->addable >= INDEXED) {
96 				gmove(r, &nod1);
97 				if(nn != Z)
98 					gmove(r, nn);
99 				regfree(&nod1);
100 				break;
101 			}
102 			regalloc(&nod, r, nn);
103 			cgen(r, &nod);
104 		} else {
105 			regalloc(&nod, r, nn);
106 			cgen(r, &nod);
107 			reglcgen(&nod1, l, Z);
108 		}
109 		gmove(&nod, &nod1);
110 		regfree(&nod);
111 		regfree(&nod1);
112 		break;
113 
114 	bitas:
115 		n = l->left;
116 		regalloc(&nod, r, nn);
117 		if(l->complex >= r->complex) {
118 			reglcgen(&nod1, n, Z);
119 			cgen(r, &nod);
120 		} else {
121 			cgen(r, &nod);
122 			reglcgen(&nod1, n, Z);
123 		}
124 		regalloc(&nod2, n, Z);
125 		gopcode(OAS, &nod1, Z, &nod2);
126 		bitstore(l, &nod, &nod1, &nod2, nn);
127 		break;
128 
129 	case OBIT:
130 		if(nn == Z) {
131 			nullwarn(l, Z);
132 			break;
133 		}
134 		bitload(n, &nod, Z, Z, nn);
135 		gopcode(OAS, &nod, Z, nn);
136 		regfree(&nod);
137 		break;
138 
139 	case OADD:
140 	case OSUB:
141 	case OAND:
142 	case OOR:
143 	case OXOR:
144 	case OLSHR:
145 	case OASHL:
146 	case OASHR:
147 		/*
148 		 * immediate operands
149 		 */
150 		if(nn != Z)
151 		if(r->op == OCONST)
152 		if(!typefd[n->type->etype]) {
153 			cgen(l, nn);
154 			if(r->vconst == 0)
155 			if(o != OAND)
156 				break;
157 			if(nn != Z)
158 				gopcode(o, r, Z, nn);
159 			break;
160 		}
161 
162 	case OLMUL:
163 	case OLDIV:
164 	case OLMOD:
165 	case OMUL:
166 	case ODIV:
167 	case OMOD:
168 		if(nn == Z) {
169 			nullwarn(l, r);
170 			break;
171 		}
172 		if(o == OMUL || o == OLMUL) {
173 			if(mulcon(n, nn))
174 				break;
175 		}
176 		if(l->complex >= r->complex) {
177 			regalloc(&nod, l, nn);
178 			cgen(l, &nod);
179 			regalloc(&nod1, r, Z);
180 			cgen(r, &nod1);
181 			gopcode(o, &nod1, Z, &nod);
182 		} else {
183 			regalloc(&nod, r, nn);
184 			cgen(r, &nod);
185 			regalloc(&nod1, l, Z);
186 			cgen(l, &nod1);
187 			gopcode(o, &nod, &nod1, &nod);
188 		}
189 		gopcode(OAS, &nod, Z, nn);
190 		regfree(&nod);
191 		regfree(&nod1);
192 		break;
193 
194 	case OASLSHR:
195 	case OASASHL:
196 	case OASASHR:
197 	case OASAND:
198 	case OASADD:
199 	case OASSUB:
200 	case OASXOR:
201 	case OASOR:
202 		if(l->op == OBIT)
203 			goto asbitop;
204 		if(r->op == OCONST)
205 		if(!typefd[r->type->etype])
206 		if(!typefd[n->type->etype]) {
207 			if(l->addable < INDEXED)
208 				reglcgen(&nod2, l, Z);
209 			else
210 				nod2 = *l;
211 			regalloc(&nod, r, nn);
212 			gopcode(OAS, &nod2, Z, &nod);
213 			gopcode(o, r, Z, &nod);
214 			gopcode(OAS, &nod, Z, &nod2);
215 
216 			regfree(&nod);
217 			if(l->addable < INDEXED)
218 				regfree(&nod2);
219 			break;
220 		}
221 		genasop(o, l, r, nn);
222 		break;
223 
224 	case OASLMUL:
225 	case OASLDIV:
226 	case OASLMOD:
227 	case OASMUL:
228 	case OASDIV:
229 	case OASMOD:
230 		if(l->op == OBIT)
231 			goto asbitop;
232 		genasop(o, l, r, nn);
233 		break;
234 
235 	asbitop:
236 		regalloc(&nod4, n, nn);
237 		if(l->complex >= r->complex) {
238 			bitload(l, &nod, &nod1, &nod2, &nod4);
239 			regalloc(&nod3, r, Z);
240 			cgen(r, &nod3);
241 		} else {
242 			regalloc(&nod3, r, Z);
243 			cgen(r, &nod3);
244 			bitload(l, &nod, &nod1, &nod2, &nod4);
245 		}
246 		gmove(&nod, &nod4);
247 		gopcode(o, &nod3, Z, &nod4);
248 		regfree(&nod3);
249 		gmove(&nod4, &nod);
250 		regfree(&nod4);
251 		bitstore(l, &nod, &nod1, &nod2, nn);
252 		break;
253 
254 	case OADDR:
255 		if(nn == Z) {
256 			nullwarn(l, Z);
257 			break;
258 		}
259 		lcgen(l, nn);
260 		break;
261 
262 	case OFUNC:
263 		if(l->complex >= FNX) {
264 			if(l->op != OIND)
265 				diag(n, "bad function call");
266 
267 			regret(&nod, l->left);
268 			cgen(l->left, &nod);
269 			regsalloc(&nod1, l->left);
270 			gopcode(OAS, &nod, Z, &nod1);
271 			regfree(&nod);
272 
273 			nod = *n;
274 			nod.left = &nod2;
275 			nod2 = *l;
276 			nod2.left = &nod1;
277 			nod2.complex = 1;
278 			cgen(&nod, nn);
279 
280 			return;
281 		}
282 		o = reg[REGARG];
283 		gargs(r, &nod, &nod1);
284 		if(l->addable < INDEXED) {
285 			reglcgen(&nod, l, Z);
286 			gopcode(OFUNC, Z, Z, &nod);
287 			regfree(&nod);
288 		} else
289 			gopcode(OFUNC, Z, Z, l);
290 		if(REGARG)
291 			if(o != reg[REGARG])
292 				reg[REGARG]--;
293 		if(nn != Z) {
294 			regret(&nod, n);
295 			gopcode(OAS, &nod, Z, nn);
296 			regfree(&nod);
297 		}
298 		break;
299 
300 	case OIND:
301 		if(nn == Z) {
302 			nullwarn(l, Z);
303 			break;
304 		}
305 		regialloc(&nod, n, nn);
306 		r = l;
307 		while(r->op == OADD)
308 			r = r->right;
309 		if(sconst(r)) {
310 			v = r->vconst;
311 			r->vconst = 0;
312 			cgen(l, &nod);
313 			nod.xoffset += v;
314 			r->vconst = v;
315 		} else
316 			cgen(l, &nod);
317 		regind(&nod, n);
318 		gopcode(OAS, &nod, Z, nn);
319 		regfree(&nod);
320 		break;
321 
322 	case OEQ:
323 	case ONE:
324 	case OLE:
325 	case OLT:
326 	case OGE:
327 	case OGT:
328 	case OLO:
329 	case OLS:
330 	case OHI:
331 	case OHS:
332 		if(nn == Z) {
333 			nullwarn(l, r);
334 			break;
335 		}
336 		boolgen(n, 1, nn);
337 		break;
338 
339 	case OANDAND:
340 	case OOROR:
341 		boolgen(n, 1, nn);
342 		if(nn == Z)
343 			patch(p, pc);
344 		break;
345 
346 	case ONOT:
347 		if(nn == Z) {
348 			nullwarn(l, Z);
349 			break;
350 		}
351 		boolgen(n, 1, nn);
352 		break;
353 
354 	case OCOMMA:
355 		cgen(l, Z);
356 		cgen(r, nn);
357 		break;
358 
359 	case OCAST:
360 		if(nn == Z) {
361 			nullwarn(l, Z);
362 			break;
363 		}
364 		/*
365 		 * convert from types l->n->nn
366 		 */
367 		if(nocast(l->type, n->type)) {
368 			if(nocast(n->type, nn->type)) {
369 				cgen(l, nn);
370 				break;
371 			}
372 		}
373 		regalloc(&nod, l, nn);
374 		cgen(l, &nod);
375 		regalloc(&nod1, n, &nod);
376 		gopcode(OAS, &nod, Z, &nod1);
377 		gopcode(OAS, &nod1, Z, nn);
378 		regfree(&nod1);
379 		regfree(&nod);
380 		break;
381 
382 	case ODOT:
383 		sugen(l, nodrat, l->type->width);
384 		if(nn != Z) {
385 			warn(n, "non-interruptable temporary");
386 			nod = *nodrat;
387 			if(!r || r->op != OCONST) {
388 				diag(n, "DOT and no offset");
389 				break;
390 			}
391 			nod.xoffset += (long)r->vconst;
392 			nod.type = n->type;
393 			cgen(&nod, nn);
394 		}
395 		break;
396 
397 	case OCOND:
398 		bcgen(l, 1);
399 		p1 = p;
400 		cgen(r->left, nn);
401 		gbranch(OGOTO);
402 		patch(p1, pc);
403 		p1 = p;
404 		cgen(r->right, nn);
405 		patch(p1, pc);
406 		break;
407 
408 	case OPOSTINC:
409 	case OPOSTDEC:
410 		v = 1;
411 		if(l->type->etype == TIND)
412 			v = l->type->link->width;
413 		if(o == OPOSTDEC)
414 			v = -v;
415 		if(l->op == OBIT)
416 			goto bitinc;
417 		if(nn == Z)
418 			goto pre;
419 
420 		if(l->addable < INDEXED)
421 			reglcgen(&nod2, l, Z);
422 		else
423 			nod2 = *l;
424 
425 		regalloc(&nod, l, nn);
426 		gopcode(OAS, &nod2, Z, &nod);
427 		regalloc(&nod1, l, Z);
428 		if(typefd[l->type->etype]) {
429 			regalloc(&nod3, l, Z);
430 			if(v < 0) {
431 				gopcode(OAS, nodfconst(-v), Z, &nod3);
432 				gopcode(OSUB, &nod3, &nod, &nod1);
433 			} else {
434 				gopcode(OAS, nodfconst(v), Z, &nod3);
435 				gopcode(OADD, &nod3, &nod, &nod1);
436 			}
437 			regfree(&nod3);
438 		} else
439 			gopcode(OADD, nodconst(v), &nod, &nod1);
440 		gopcode(OAS, &nod1, Z, &nod2);
441 
442 		regfree(&nod);
443 		regfree(&nod1);
444 		if(l->addable < INDEXED)
445 			regfree(&nod2);
446 		break;
447 
448 	case OPREINC:
449 	case OPREDEC:
450 		v = 1;
451 		if(l->type->etype == TIND)
452 			v = l->type->link->width;
453 		if(o == OPREDEC)
454 			v = -v;
455 		if(l->op == OBIT)
456 			goto bitinc;
457 
458 	pre:
459 		if(l->addable < INDEXED)
460 			reglcgen(&nod2, l, Z);
461 		else
462 			nod2 = *l;
463 
464 		regalloc(&nod, l, nn);
465 		gopcode(OAS, &nod2, Z, &nod);
466 		if(typefd[l->type->etype]) {
467 			regalloc(&nod3, l, Z);
468 			if(v < 0) {
469 				gopcode(OAS, nodfconst(-v), Z, &nod3);
470 				gopcode(OSUB, &nod3, Z, &nod);
471 			} else {
472 				gopcode(OAS, nodfconst(v), Z, &nod3);
473 				gopcode(OADD, &nod3, Z, &nod);
474 			}
475 			regfree(&nod3);
476 		} else
477 			gopcode(OADD, nodconst(v), Z, &nod);
478 		gopcode(OAS, &nod, Z, &nod2);
479 		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
480 			gins(ANOP, l, Z);
481 
482 		regfree(&nod);
483 		if(l->addable < INDEXED)
484 			regfree(&nod2);
485 		break;
486 
487 	bitinc:
488 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
489 			bitload(l, &nod, &nod1, &nod2, Z);
490 			gopcode(OAS, &nod, Z, nn);
491 			gopcode(OADD, nodconst(v), Z, &nod);
492 			bitstore(l, &nod, &nod1, &nod2, Z);
493 			break;
494 		}
495 		bitload(l, &nod, &nod1, &nod2, nn);
496 		gopcode(OADD, nodconst(v), Z, &nod);
497 		bitstore(l, &nod, &nod1, &nod2, nn);
498 		break;
499 	}
500 	cursafe = curs;
501 }
502 
503 static void
genasop(int o,Node * l,Node * r,Node * nn)504 genasop(int o, Node *l, Node *r, Node *nn)
505 {
506 	Node nod, nod1, nod2;
507 	int hardleft;
508 
509 	hardleft = l->addable < INDEXED || l->complex >= FNX;
510 	if(l->complex >= r->complex) {
511 		if(hardleft)
512 			reglcgen(&nod2, l, Z);
513 		else
514 			nod2 = *l;
515 		regalloc(&nod1, r, Z);
516 		cgen(r, &nod1);
517 	} else {
518 		regalloc(&nod1, r, Z);
519 		cgen(r, &nod1);
520 		if(hardleft)
521 			reglcgen(&nod2, l, Z);
522 		else
523 			nod2 = *l;
524 	}
525 	if(nod1.type == nod2.type || !typefd[nod1.type->etype])
526 		regalloc(&nod, &nod2, nn);
527 	else
528 		regalloc(&nod, &nod1, Z);
529 	gmove(&nod2, &nod);
530 	gopcode(o, &nod1, Z, &nod);
531 	gmove(&nod, &nod2);
532 	if(nn != Z)
533 		gmove(&nod2, nn);
534 	regfree(&nod);
535 	regfree(&nod1);
536 	if(hardleft)
537 		regfree(&nod2);
538 }
539 
540 void
reglcgen(Node * t,Node * n,Node * nn)541 reglcgen(Node *t, Node *n, Node *nn)
542 {
543 	Node *r;
544 	long v;
545 
546 	regialloc(t, n, nn);
547 	if(n->op == OIND) {
548 		r = n->left;
549 		while(r->op == OADD)
550 			r = r->right;
551 		if(sconst(r)) {
552 			v = r->vconst;
553 			r->vconst = 0;
554 			lcgen(n, t);
555 			t->xoffset += v;
556 			r->vconst = v;
557 			regind(t, n);
558 			return;
559 		}
560 	}
561 	lcgen(n, t);
562 	regind(t, n);
563 }
564 
565 void
lcgen(Node * n,Node * nn)566 lcgen(Node *n, Node *nn)
567 {
568 	Prog *p1;
569 	Node nod;
570 
571 	if(debug['g']) {
572 		prtree(nn, "lcgen lhs");
573 		prtree(n, "lcgen");
574 	}
575 	if(n == Z || n->type == T)
576 		return;
577 	if(nn == Z) {
578 		nn = &nod;
579 		regalloc(&nod, n, Z);
580 	}
581 	switch(n->op) {
582 	default:
583 		if(n->addable < INDEXED) {
584 			diag(n, "unknown op in lcgen: %O", n->op);
585 			break;
586 		}
587 		nod = *n;
588 		nod.op = OADDR;
589 		nod.left = n;
590 		nod.right = Z;
591 		nod.type = types[TIND];
592 		gopcode(OAS, &nod, Z, nn);
593 		break;
594 
595 	case OCOMMA:
596 		cgen(n->left, n->left);
597 		lcgen(n->right, nn);
598 		break;
599 
600 	case OIND:
601 		cgen(n->left, nn);
602 		break;
603 
604 	case OCOND:
605 		bcgen(n->left, 1);
606 		p1 = p;
607 		lcgen(n->right->left, nn);
608 		gbranch(OGOTO);
609 		patch(p1, pc);
610 		p1 = p;
611 		lcgen(n->right->right, nn);
612 		patch(p1, pc);
613 		break;
614 	}
615 }
616 
617 void
bcgen(Node * n,int true)618 bcgen(Node *n, int true)
619 {
620 
621 	if(n->type == T)
622 		gbranch(OGOTO);
623 	else
624 		boolgen(n, true, Z);
625 }
626 
627 void
boolgen(Node * n,int true,Node * nn)628 boolgen(Node *n, int true, Node *nn)
629 {
630 	int o;
631 	Prog *p1, *p2;
632 	Node *l, *r, nod, nod1;
633 	long curs;
634 
635 	if(debug['g']) {
636 		prtree(nn, "boolgen lhs");
637 		prtree(n, "boolgen");
638 	}
639 	curs = cursafe;
640 	l = n->left;
641 	r = n->right;
642 	switch(n->op) {
643 
644 	default:
645 		regalloc(&nod, n, nn);
646 		cgen(n, &nod);
647 		if(nn == Z || typefd[n->type->etype]) {
648 			o = ONE;
649 			if(true)
650 				o = comrel[relindex(o)];
651 			if(typefd[n->type->etype]) {
652 				nodreg(&nod1, n, NREG+FREGZERO);
653 				gopcode(o, &nod, &nod1, Z);
654 			} else
655 				gopcode(o, &nod, Z, Z);
656 			regfree(&nod);
657 			goto com;
658 		}
659 		if(true)
660 			gopcode(OCOND, &nod, nodconst(0), &nod);
661 		else
662 			gopcode(OCOND, nodconst(1), &nod, &nod);
663 		gopcode(OAS, &nod, Z, nn);
664 		regfree(&nod);
665 		break;
666 
667 	case OCONST:
668 		o = vconst(n);
669 		if(!true)
670 			o = !o;
671 		gbranch(OGOTO);
672 		if(o) {
673 			p1 = p;
674 			gbranch(OGOTO);
675 			patch(p1, pc);
676 		}
677 		goto com;
678 
679 	case OCOMMA:
680 		cgen(l, Z);
681 		boolgen(r, true, nn);
682 		break;
683 
684 	case ONOT:
685 		boolgen(l, !true, nn);
686 		break;
687 
688 	case OCOND:
689 		bcgen(l, 1);
690 		p1 = p;
691 		bcgen(r->left, true);
692 		p2 = p;
693 		gbranch(OGOTO);
694 		patch(p1, pc);
695 		p1 = p;
696 		bcgen(r->right, !true);
697 		patch(p2, pc);
698 		p2 = p;
699 		gbranch(OGOTO);
700 		patch(p1, pc);
701 		patch(p2, pc);
702 		goto com;
703 
704 	case OANDAND:
705 		if(!true)
706 			goto caseor;
707 
708 	caseand:
709 		bcgen(l, true);
710 		p1 = p;
711 		bcgen(r, !true);
712 		p2 = p;
713 		patch(p1, pc);
714 		gbranch(OGOTO);
715 		patch(p2, pc);
716 		goto com;
717 
718 	case OOROR:
719 		if(!true)
720 			goto caseand;
721 
722 	caseor:
723 		bcgen(l, !true);
724 		p1 = p;
725 		bcgen(r, !true);
726 		p2 = p;
727 		gbranch(OGOTO);
728 		patch(p1, pc);
729 		patch(p2, pc);
730 		goto com;
731 
732 	case OEQ:
733 	case ONE:
734 	case OLE:
735 	case OLT:
736 	case OGE:
737 	case OGT:
738 	case OHI:
739 	case OHS:
740 	case OLO:
741 	case OLS:
742 		o = n->op;
743 		if(true)
744 			o = comrel[relindex(o)];
745 		if(l->complex >= FNX && r->complex >= FNX) {
746 			regret(&nod, r);
747 			cgen(r, &nod);
748 			regsalloc(&nod1, r);
749 			gopcode(OAS, &nod, Z, &nod1);
750 			regfree(&nod);
751 			nod = *n;
752 			nod.right = &nod1;
753 			boolgen(&nod, true, nn);
754 			break;
755 		}
756 		if(nn != Z && !typefd[l->type->etype]) {
757 			if(l->complex >= r->complex) {
758 				regalloc(&nod1, l, nn);
759 				cgen(l, &nod1);
760 				regalloc(&nod, r, Z);
761 				cgen(r, &nod);
762 			} else {
763 				regalloc(&nod, r, nn);
764 				cgen(r, &nod);
765 				regalloc(&nod1, l, Z);
766 				cgen(l, &nod1);
767 			}
768 			switch(o) {
769 			case OEQ:
770 				gopcode(OSUB, &nod1, &nod, &nod);
771 				gopcode(OCOND, &nod, nodconst(0), &nod);
772 				break;
773 			case ONE:
774 				gopcode(OSUB, &nod1, &nod, &nod);
775 				gopcode(OCOND, nodconst(1), &nod, &nod);
776 				break;
777 			case OLE:
778 				gopcode(OCOMMA, &nod1, &nod, &nod);
779 				break;
780 			case OGT:
781 				gopcode(OCOMMA, &nod1, &nod, &nod);
782 				gopcode(OXOR, nodconst(1), &nod, &nod);
783 				break;
784 			case OLT:
785 				gopcode(OCOMMA, &nod, &nod1, &nod);
786 				gopcode(OXOR, nodconst(1), &nod, &nod);
787 				break;
788 			case OGE:
789 				gopcode(OCOMMA, &nod, &nod1, &nod);
790 				break;
791 			case OLS:
792 				gopcode(OCOND, &nod1, &nod, &nod);
793 				break;
794 			case OHI:
795 				gopcode(OCOND, &nod1, &nod, &nod);
796 				gopcode(OXOR, nodconst(1), &nod, &nod);
797 				break;
798 			case OLO:
799 				gopcode(OCOND, &nod, &nod1, &nod);
800 				gopcode(OXOR, nodconst(1), &nod, &nod);
801 				break;
802 			case OHS:
803 				gopcode(OCOND, &nod, &nod1, &nod);
804 				break;
805 			}
806 			gopcode(OAS, &nod, Z, nn);
807 			regfree(&nod);
808 			regfree(&nod1);
809 			break;
810 		}
811 		if(sconst(l)) {
812 			switch(o) {
813 			default:
814 				if(l->vconst != 0)
815 					break;
816 
817 			case OGT:
818 			case OHI:
819 			case OLE:
820 			case OLS:
821 				regalloc(&nod, r, nn);
822 				cgen(r, &nod);
823 				gopcode(o, l, &nod, Z);
824 				regfree(&nod);
825 				goto com;
826 			}
827 		}
828 		if(sconst(r)) {
829 			switch(o) {
830 			default:
831 				if(r->vconst != 0)
832 					break;
833 
834 			case OGE:
835 			case OHS:
836 			case OLT:
837 			case OLO:
838 				regalloc(&nod, l, nn);
839 				cgen(l, &nod);
840 				gopcode(o, &nod, r, Z);
841 				regfree(&nod);
842 				goto com;
843 			}
844 		}
845 		if(l->complex >= r->complex) {
846 			regalloc(&nod1, l, nn);
847 			cgen(l, &nod1);
848 			regalloc(&nod, r, Z);
849 			cgen(r, &nod);
850 		} else {
851 			regalloc(&nod, r, nn);
852 			cgen(r, &nod);
853 			regalloc(&nod1, l, Z);
854 			cgen(l, &nod1);
855 		}
856 		gopcode(o, &nod1, &nod, Z);
857 		regfree(&nod);
858 		regfree(&nod1);
859 
860 	com:
861 		if(nn != Z) {
862 			p1 = p;
863 			gopcode(OAS, nodconst(1), Z, nn);
864 			gbranch(OGOTO);
865 			p2 = p;
866 			patch(p1, pc);
867 			gopcode(OAS, nodconst(0), Z, nn);
868 			patch(p2, pc);
869 		}
870 		break;
871 	}
872 	cursafe = curs;
873 }
874 
875 void
sugen(Node * n,Node * nn,long w)876 sugen(Node *n, Node *nn, long w)
877 {
878 	Prog *p1;
879 	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
880 	Type *t;
881 	long pc1;
882 	int i, m, c;
883 
884 	if(n == Z || n->type == T)
885 		return;
886 	if(debug['g']) {
887 		prtree(nn, "sugen lhs");
888 		prtree(n, "sugen");
889 	}
890 	if(nn == nodrat)
891 		if(w > nrathole)
892 			nrathole = w;
893 	switch(n->op) {
894 	case OIND:
895 		if(nn == Z) {
896 			nullwarn(n->left, Z);
897 			break;
898 		}
899 
900 	default:
901 		goto copy;
902 
903 	case ODOT:
904 		l = n->left;
905 		sugen(l, nodrat, l->type->width);
906 		if(nn != Z) {
907 			warn(n, "non-interruptable temporary");
908 			nod1 = *nodrat;
909 			r = n->right;
910 			if(!r || r->op != OCONST) {
911 				diag(n, "DOT and no offset");
912 				break;
913 			}
914 			nod1.xoffset += (long)r->vconst;
915 			nod1.type = n->type;
916 			sugen(&nod1, nn, w);
917 		}
918 		break;
919 
920 	case OSTRUCT:
921 		/*
922 		 * rewrite so lhs has no side effects
923 		 */
924 		if(nn != Z && side(nn)) {
925 			nod1 = *n;
926 			nod1.type = typ(TIND, n->type);
927 			regalloc(&nod2, &nod1, Z);
928 			lcgen(nn, &nod2);
929 			regsalloc(&nod0, &nod1);
930 			gopcode(OAS, &nod2, Z, &nod0);
931 			regfree(&nod2);
932 
933 			nod1 = *n;
934 			nod1.op = OIND;
935 			nod1.left = &nod0;
936 			nod1.right = Z;
937 			nod1.complex = 1;
938 
939 			sugen(n, &nod1, w);
940 			return;
941 		}
942 
943 		r = n->left;
944 		for(t = n->type->link; t != T; t = t->down) {
945 			l = r;
946 			if(r->op == OLIST) {
947 				l = r->left;
948 				r = r->right;
949 			}
950 			if(nn == Z) {
951 				cgen(l, nn);
952 				continue;
953 			}
954 			/*
955 			 * hand craft *(&nn + o) = l
956 			 */
957 			nod0 = znode;
958 			nod0.op = OAS;
959 			nod0.type = t;
960 			nod0.left = &nod1;
961 			nod0.right = l;
962 
963 			nod1 = znode;
964 			nod1.op = OIND;
965 			nod1.type = t;
966 			nod1.left = &nod2;
967 
968 			nod2 = znode;
969 			nod2.op = OADD;
970 			nod2.type = typ(TIND, t);
971 			nod2.left = &nod3;
972 			nod2.right = &nod4;
973 
974 			nod3 = znode;
975 			nod3.op = OADDR;
976 			nod3.type = nod2.type;
977 			nod3.left = nn;
978 
979 			nod4 = znode;
980 			nod4.op = OCONST;
981 			nod4.type = nod2.type;
982 			nod4.vconst = t->offset;
983 
984 			ccom(&nod0);
985 			acom(&nod0);
986 			xcom(&nod0);
987 			nod0.addable = 0;
988 
989 			cgen(&nod0, Z);
990 		}
991 		break;
992 
993 	case OAS:
994 		if(nn == Z) {
995 			if(n->addable < INDEXED)
996 				sugen(n->right, n->left, w);
997 			break;
998 		}
999 		sugen(n->right, nodrat, w);
1000 		warn(n, "non-interruptable temporary");
1001 		sugen(nodrat, n->left, w);
1002 		sugen(nodrat, nn, w);
1003 		break;
1004 
1005 	case OFUNC:
1006 		if(nn == Z) {
1007 			sugen(n, nodrat, w);
1008 			break;
1009 		}
1010 		if(nn->op != OIND) {
1011 			nn = new1(OADDR, nn, Z);
1012 			nn->type = types[TIND];
1013 			nn->addable = 0;
1014 		} else
1015 			nn = nn->left;
1016 		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
1017 		n->type = types[TVOID];
1018 		n->left->type = types[TVOID];
1019 		cgen(n, Z);
1020 		break;
1021 
1022 	case OCOND:
1023 		bcgen(n->left, 1);
1024 		p1 = p;
1025 		sugen(n->right->left, nn, w);
1026 		gbranch(OGOTO);
1027 		patch(p1, pc);
1028 		p1 = p;
1029 		sugen(n->right->right, nn, w);
1030 		patch(p1, pc);
1031 		break;
1032 
1033 	case OCOMMA:
1034 		cgen(n->left, Z);
1035 		sugen(n->right, nn, w);
1036 		break;
1037 	}
1038 	return;
1039 
1040 copy:
1041 	if(nn == Z)
1042 		return;
1043 	if(n->complex >= FNX && nn->complex >= FNX) {
1044 		t = nn->type;
1045 		nn->type = types[TLONG];
1046 		regialloc(&nod1, nn, Z);
1047 		lcgen(nn, &nod1);
1048 		regsalloc(&nod2, nn);
1049 		nn->type = t;
1050 
1051 		gopcode(OAS, &nod1, Z, &nod2);
1052 		regfree(&nod1);
1053 
1054 		nod2.type = typ(TIND, t);
1055 
1056 		nod1 = nod2;
1057 		nod1.op = OIND;
1058 		nod1.left = &nod2;
1059 		nod1.right = Z;
1060 		nod1.complex = 1;
1061 		nod1.type = t;
1062 
1063 		sugen(n, &nod1, w);
1064 		return;
1065 	}
1066 
1067 	if(n->complex > nn->complex) {
1068 		t = n->type;
1069 		n->type = types[TVLONG];
1070 		reglcgen(&nod1, n, Z);
1071 		n->type = t;
1072 
1073 		t = nn->type;
1074 		nn->type = types[TVLONG];
1075 		reglcgen(&nod2, nn, Z);
1076 		nn->type = t;
1077 	} else {
1078 		t = nn->type;
1079 		nn->type = types[TVLONG];
1080 		reglcgen(&nod2, nn, Z);
1081 		nn->type = t;
1082 
1083 		t = n->type;
1084 		n->type = types[TVLONG];
1085 		reglcgen(&nod1, n, Z);
1086 		n->type = t;
1087 	}
1088 
1089 	w /= SZ_VLONG;
1090 	if(w <= 5) {
1091 		layout(&nod1, &nod2, w, 0, Z);
1092 		goto out;
1093 	}
1094 
1095 	/*
1096 	 * minimize space for unrolling loop
1097 	 * 3,4,5 times. (6 or more is never minimum)
1098 	 * if small structure, try 2 also.
1099 	 */
1100 	c = 0; /* set */
1101 	m = 100;
1102 	i = 3;
1103 	if(w <= 15)
1104 		i = 2;
1105 	for(; i<=5; i++)
1106 		if(i + w%i <= m) {
1107 			c = i;
1108 			m = c + w%c;
1109 		}
1110 
1111 	regalloc(&nod3, &regnode, Z);
1112 	layout(&nod1, &nod2, w%c, w/c, &nod3);
1113 
1114 	pc1 = pc;
1115 	layout(&nod1, &nod2, c, 0, Z);
1116 
1117 	gopcode(OSUB, nodconst(1), Z, &nod3);
1118 	nod1.op = OREGISTER;
1119 	gopcode(OADD, nodconst(c*SZ_VLONG), Z, &nod1);
1120 	nod2.op = OREGISTER;
1121 	gopcode(OADD, nodconst(c*SZ_VLONG), Z, &nod2);
1122 
1123 	gopcode(OEQ, &nod3, Z, Z);
1124 	p->as = ABGTZ;
1125 	patch(p, pc1);
1126 
1127 	regfree(&nod3);
1128 out:
1129 	regfree(&nod1);
1130 	regfree(&nod2);
1131 }
1132 
1133 void
layout(Node * f,Node * t,int c,int cv,Node * cn)1134 layout(Node *f, Node *t, int c, int cv, Node *cn)
1135 {
1136 	Node t1, t2;
1137 
1138 	while(c > 3) {
1139 		layout(f, t, 2, 0, Z);
1140 		c -= 2;
1141 	}
1142 
1143 	regalloc(&t1, &regnode, Z);
1144 	regalloc(&t2, &regnode, Z);
1145 	t1.type = types[TVLONG];
1146 	t2.type = types[TVLONG];
1147 	if(c > 0) {
1148 		gopcode(OAS, f, Z, &t1);
1149 		f->xoffset += SZ_VLONG;
1150 	}
1151 	if(cn != Z)
1152 		gopcode(OAS, nodconst(cv), Z, cn);
1153 	if(c > 1) {
1154 		gopcode(OAS, f, Z, &t2);
1155 		f->xoffset += SZ_VLONG;
1156 	}
1157 	if(c > 0) {
1158 		gopcode(OAS, &t1, Z, t);
1159 		t->xoffset += SZ_VLONG;
1160 	}
1161 	if(c > 2) {
1162 		gopcode(OAS, f, Z, &t1);
1163 		f->xoffset += SZ_VLONG;
1164 	}
1165 	if(c > 1) {
1166 		gopcode(OAS, &t2, Z, t);
1167 		t->xoffset += SZ_VLONG;
1168 	}
1169 	if(c > 2) {
1170 		gopcode(OAS, &t1, Z, t);
1171 		t->xoffset += SZ_VLONG;
1172 	}
1173 	regfree(&t1);
1174 	regfree(&t2);
1175 }
1176