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