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