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