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