xref: /plan9/sys/src/cmd/vc/cgen.c (revision ff8c3af2f44d95267f67219afa20ba82ff6cf7e4)
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[n->type->etype]) {
204 			if(l->addable < INDEXED)
205 				reglcgen(&nod2, l, Z);
206 			else
207 				nod2 = *l;
208 			regalloc(&nod, r, nn);
209 			gopcode(OAS, &nod2, Z, &nod);
210 			gopcode(o, r, Z, &nod);
211 			gopcode(OAS, &nod, Z, &nod2);
212 
213 			regfree(&nod);
214 			if(l->addable < INDEXED)
215 				regfree(&nod2);
216 			break;
217 		}
218 
219 	case OASLMUL:
220 	case OASLDIV:
221 	case OASLMOD:
222 	case OASMUL:
223 	case OASDIV:
224 	case OASMOD:
225 		if(l->op == OBIT)
226 			goto asbitop;
227 		if(l->complex >= r->complex) {
228 			if(l->addable < INDEXED)
229 				reglcgen(&nod2, l, Z);
230 			else
231 				nod2 = *l;
232 			regalloc(&nod1, r, Z);
233 			cgen(r, &nod1);
234 		} else {
235 			regalloc(&nod1, r, Z);
236 			cgen(r, &nod1);
237 			if(l->addable < INDEXED)
238 				reglcgen(&nod2, l, Z);
239 			else
240 				nod2 = *l;
241 		}
242 
243 		regalloc(&nod, n, nn);
244 		gmove(&nod2, &nod);
245 		gopcode(o, &nod1, Z, &nod);
246 		gmove(&nod, &nod2);
247 		if(nn != Z)
248 			gopcode(OAS, &nod, Z, nn);
249 		regfree(&nod);
250 		regfree(&nod1);
251 		if(l->addable < INDEXED)
252 			regfree(&nod2);
253 		break;
254 
255 	asbitop:
256 		regalloc(&nod4, n, nn);
257 		if(l->complex >= r->complex) {
258 			bitload(l, &nod, &nod1, &nod2, &nod4);
259 			regalloc(&nod3, r, Z);
260 			cgen(r, &nod3);
261 		} else {
262 			regalloc(&nod3, r, Z);
263 			cgen(r, &nod3);
264 			bitload(l, &nod, &nod1, &nod2, &nod4);
265 		}
266 		gmove(&nod, &nod4);
267 		gopcode(o, &nod3, Z, &nod4);
268 		regfree(&nod3);
269 		gmove(&nod4, &nod);
270 		regfree(&nod4);
271 		bitstore(l, &nod, &nod1, &nod2, nn);
272 		break;
273 
274 	case OADDR:
275 		if(nn == Z) {
276 			nullwarn(l, Z);
277 			break;
278 		}
279 		lcgen(l, nn);
280 		break;
281 
282 	case OFUNC:
283 		if(l->complex >= FNX) {
284 			if(l->op != OIND)
285 				diag(n, "bad function call");
286 
287 			regret(&nod, l->left);
288 			cgen(l->left, &nod);
289 			regsalloc(&nod1, l->left);
290 			gopcode(OAS, &nod, Z, &nod1);
291 			regfree(&nod);
292 
293 			nod = *n;
294 			nod.left = &nod2;
295 			nod2 = *l;
296 			nod2.left = &nod1;
297 			nod2.complex = 1;
298 			cgen(&nod, nn);
299 
300 			return;
301 		}
302 		o = reg[REGARG];
303 		gargs(r, &nod, &nod1);
304 		if(l->addable < INDEXED) {
305 			reglcgen(&nod, l, Z);
306 			gopcode(OFUNC, Z, Z, &nod);
307 			regfree(&nod);
308 		} else
309 			gopcode(OFUNC, Z, Z, l);
310 		if(REGARG)
311 			if(o != reg[REGARG])
312 				reg[REGARG]--;
313 		if(nn != Z) {
314 			regret(&nod, n);
315 			gopcode(OAS, &nod, Z, nn);
316 			regfree(&nod);
317 		}
318 		break;
319 
320 	case OIND:
321 		if(nn == Z) {
322 			nullwarn(l, Z);
323 			break;
324 		}
325 		regialloc(&nod, n, nn);
326 		r = l;
327 		while(r->op == OADD)
328 			r = r->right;
329 		if(sconst(r)) {
330 			v = r->vconst;
331 			r->vconst = 0;
332 			cgen(l, &nod);
333 			nod.xoffset += v;
334 			r->vconst = v;
335 		} else
336 			cgen(l, &nod);
337 		regind(&nod, n);
338 		gopcode(OAS, &nod, Z, nn);
339 		regfree(&nod);
340 		break;
341 
342 	case OEQ:
343 	case ONE:
344 	case OLE:
345 	case OLT:
346 	case OGE:
347 	case OGT:
348 	case OLO:
349 	case OLS:
350 	case OHI:
351 	case OHS:
352 		if(nn == Z) {
353 			nullwarn(l, r);
354 			break;
355 		}
356 		boolgen(n, 1, nn);
357 		break;
358 
359 	case OANDAND:
360 	case OOROR:
361 		boolgen(n, 1, nn);
362 		if(nn == Z)
363 			patch(p, pc);
364 		break;
365 
366 	case ONOT:
367 		if(nn == Z) {
368 			nullwarn(l, Z);
369 			break;
370 		}
371 		boolgen(n, 1, nn);
372 		break;
373 
374 	case OCOMMA:
375 		cgen(l, Z);
376 		cgen(r, nn);
377 		break;
378 
379 	case OCAST:
380 		if(nn == Z) {
381 			nullwarn(l, Z);
382 			break;
383 		}
384 		/*
385 		 * convert from types l->n->nn
386 		 */
387 		if(nocast(l->type, n->type)) {
388 			if(nocast(n->type, nn->type)) {
389 				cgen(l, nn);
390 				break;
391 			}
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 
500 		regfree(&nod);
501 		if(l->addable < INDEXED)
502 			regfree(&nod2);
503 		break;
504 
505 	bitinc:
506 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
507 			bitload(l, &nod, &nod1, &nod2, Z);
508 			gopcode(OAS, &nod, Z, nn);
509 			gopcode(OADD, nodconst(v), Z, &nod);
510 			bitstore(l, &nod, &nod1, &nod2, Z);
511 			break;
512 		}
513 		bitload(l, &nod, &nod1, &nod2, nn);
514 		gopcode(OADD, nodconst(v), Z, &nod);
515 		bitstore(l, &nod, &nod1, &nod2, nn);
516 		break;
517 	}
518 	cursafe = curs;
519 }
520 
521 void
522 reglcgen(Node *t, Node *n, Node *nn)
523 {
524 	Node *r;
525 	long v;
526 
527 	regialloc(t, n, nn);
528 	if(n->op == OIND) {
529 		r = n->left;
530 		while(r->op == OADD)
531 			r = r->right;
532 		if(sconst(r)) {
533 			v = r->vconst;
534 			r->vconst = 0;
535 			lcgen(n, t);
536 			t->xoffset += v;
537 			r->vconst = v;
538 			regind(t, n);
539 			return;
540 		}
541 	}
542 	lcgen(n, t);
543 	regind(t, n);
544 }
545 
546 void
547 lcgen(Node *n, Node *nn)
548 {
549 	Prog *p1;
550 	Node nod;
551 
552 	if(debug['g']) {
553 		prtree(nn, "lcgen lhs");
554 		prtree(n, "lcgen");
555 	}
556 	if(n == Z || n->type == T)
557 		return;
558 	if(nn == Z) {
559 		nn = &nod;
560 		regalloc(&nod, n, Z);
561 	}
562 	switch(n->op) {
563 	default:
564 		if(n->addable < INDEXED) {
565 			diag(n, "unknown op in lcgen: %O", n->op);
566 			break;
567 		}
568 		nod = *n;
569 		nod.op = OADDR;
570 		nod.left = n;
571 		nod.right = Z;
572 		nod.type = types[TIND];
573 		gopcode(OAS, &nod, Z, nn);
574 		break;
575 
576 	case OCOMMA:
577 		cgen(n->left, n->left);
578 		lcgen(n->right, nn);
579 		break;
580 
581 	case OIND:
582 		cgen(n->left, nn);
583 		break;
584 
585 	case OCOND:
586 		bcgen(n->left, 1);
587 		p1 = p;
588 		lcgen(n->right->left, nn);
589 		gbranch(OGOTO);
590 		patch(p1, pc);
591 		p1 = p;
592 		lcgen(n->right->right, nn);
593 		patch(p1, pc);
594 		break;
595 	}
596 }
597 
598 void
599 bcgen(Node *n, int true)
600 {
601 
602 	if(n->type == T)
603 		gbranch(OGOTO);
604 	else
605 		boolgen(n, true, Z);
606 }
607 
608 void
609 boolgen(Node *n, int true, Node *nn)
610 {
611 	int o;
612 	Prog *p1, *p2;
613 	Node *l, *r, nod, nod1;
614 	long curs;
615 
616 	if(debug['g']) {
617 		prtree(nn, "boolgen lhs");
618 		prtree(n, "boolgen");
619 	}
620 	curs = cursafe;
621 	l = n->left;
622 	r = n->right;
623 	switch(n->op) {
624 
625 	default:
626 		regalloc(&nod, n, nn);
627 		cgen(n, &nod);
628 		if(nn == Z || typefd[n->type->etype]) {
629 			o = ONE;
630 			if(true)
631 				o = comrel[relindex(o)];
632 			if(typefd[n->type->etype]) {
633 				nodreg(&nod1, n, NREG+FREGZERO);
634 				gopcode(o, &nod, &nod1, Z);
635 			} else
636 				gopcode(o, &nod, Z, Z);
637 			regfree(&nod);
638 			goto com;
639 		}
640 		if(true)
641 			gopcode(OCOND, &nod, nodconst(0), &nod);
642 		else
643 			gopcode(OCOND, nodconst(1), &nod, &nod);
644 		gopcode(OAS, &nod, Z, nn);
645 		regfree(&nod);
646 		break;
647 
648 	case OCONST:
649 		o = vconst(n);
650 		if(!true)
651 			o = !o;
652 		gbranch(OGOTO);
653 		if(o) {
654 			p1 = p;
655 			gbranch(OGOTO);
656 			patch(p1, pc);
657 		}
658 		goto com;
659 
660 	case OCOMMA:
661 		cgen(l, Z);
662 		boolgen(r, true, nn);
663 		break;
664 
665 	case ONOT:
666 		boolgen(l, !true, nn);
667 		break;
668 
669 	case OCOND:
670 		bcgen(l, 1);
671 		p1 = p;
672 		bcgen(r->left, true);
673 		p2 = p;
674 		gbranch(OGOTO);
675 		patch(p1, pc);
676 		p1 = p;
677 		bcgen(r->right, !true);
678 		patch(p2, pc);
679 		p2 = p;
680 		gbranch(OGOTO);
681 		patch(p1, pc);
682 		patch(p2, pc);
683 		goto com;
684 
685 	case OANDAND:
686 		if(!true)
687 			goto caseor;
688 
689 	caseand:
690 		bcgen(l, true);
691 		p1 = p;
692 		bcgen(r, !true);
693 		p2 = p;
694 		patch(p1, pc);
695 		gbranch(OGOTO);
696 		patch(p2, pc);
697 		goto com;
698 
699 	case OOROR:
700 		if(!true)
701 			goto caseand;
702 
703 	caseor:
704 		bcgen(l, !true);
705 		p1 = p;
706 		bcgen(r, !true);
707 		p2 = p;
708 		gbranch(OGOTO);
709 		patch(p1, pc);
710 		patch(p2, pc);
711 		goto com;
712 
713 	case OEQ:
714 	case ONE:
715 	case OLE:
716 	case OLT:
717 	case OGE:
718 	case OGT:
719 	case OHI:
720 	case OHS:
721 	case OLO:
722 	case OLS:
723 		o = n->op;
724 		if(true)
725 			o = comrel[relindex(o)];
726 		if(l->complex >= FNX && r->complex >= FNX) {
727 			regret(&nod, r);
728 			cgen(r, &nod);
729 			regsalloc(&nod1, r);
730 			gopcode(OAS, &nod, Z, &nod1);
731 			regfree(&nod);
732 			nod = *n;
733 			nod.right = &nod1;
734 			boolgen(&nod, true, nn);
735 			break;
736 		}
737 		if(nn != Z && !typefd[l->type->etype]) {
738 			if(l->complex >= r->complex) {
739 				regalloc(&nod1, l, nn);
740 				cgen(l, &nod1);
741 				regalloc(&nod, r, Z);
742 				cgen(r, &nod);
743 			} else {
744 				regalloc(&nod, r, nn);
745 				cgen(r, &nod);
746 				regalloc(&nod1, l, Z);
747 				cgen(l, &nod1);
748 			}
749 			switch(o) {
750 			case OEQ:
751 				gopcode(OSUB, &nod1, &nod, &nod);
752 				gopcode(OCOND, &nod, nodconst(0), &nod);
753 				break;
754 			case ONE:
755 				gopcode(OSUB, &nod1, &nod, &nod);
756 				gopcode(OCOND, nodconst(1), &nod, &nod);
757 				break;
758 			case OLE:
759 				gopcode(OCOMMA, &nod1, &nod, &nod);
760 				break;
761 			case OGT:
762 				gopcode(OCOMMA, &nod1, &nod, &nod);
763 				gopcode(OXOR, nodconst(1), &nod, &nod);
764 				break;
765 			case OLT:
766 				gopcode(OCOMMA, &nod, &nod1, &nod);
767 				gopcode(OXOR, nodconst(1), &nod, &nod);
768 				break;
769 			case OGE:
770 				gopcode(OCOMMA, &nod, &nod1, &nod);
771 				break;
772 			case OLS:
773 				gopcode(OCOND, &nod1, &nod, &nod);
774 				break;
775 			case OHI:
776 				gopcode(OCOND, &nod1, &nod, &nod);
777 				gopcode(OXOR, nodconst(1), &nod, &nod);
778 				break;
779 			case OLO:
780 				gopcode(OCOND, &nod, &nod1, &nod);
781 				gopcode(OXOR, nodconst(1), &nod, &nod);
782 				break;
783 			case OHS:
784 				gopcode(OCOND, &nod, &nod1, &nod);
785 				break;
786 			}
787 			gopcode(OAS, &nod, Z, nn);
788 			regfree(&nod);
789 			regfree(&nod1);
790 			break;
791 		}
792 		if(sconst(l)) {
793 			switch(o) {
794 			default:
795 				if(l->vconst != 0)
796 					break;
797 
798 			case OGT:
799 			case OHI:
800 			case OLE:
801 			case OLS:
802 				regalloc(&nod, r, nn);
803 				cgen(r, &nod);
804 				gopcode(o, l, &nod, Z);
805 				regfree(&nod);
806 				goto com;
807 			}
808 		}
809 		if(sconst(r)) {
810 			switch(o) {
811 			default:
812 				if(r->vconst != 0)
813 					break;
814 
815 			case OGE:
816 			case OHS:
817 			case OLT:
818 			case OLO:
819 				regalloc(&nod, l, nn);
820 				cgen(l, &nod);
821 				gopcode(o, &nod, r, Z);
822 				regfree(&nod);
823 				goto com;
824 			}
825 		}
826 		if(l->complex >= r->complex) {
827 			regalloc(&nod1, l, nn);
828 			cgen(l, &nod1);
829 			regalloc(&nod, r, Z);
830 			cgen(r, &nod);
831 		} else {
832 			regalloc(&nod, r, nn);
833 			cgen(r, &nod);
834 			regalloc(&nod1, l, Z);
835 			cgen(l, &nod1);
836 		}
837 		gopcode(o, &nod1, &nod, Z);
838 		regfree(&nod);
839 		regfree(&nod1);
840 
841 	com:
842 		if(nn != Z) {
843 			p1 = p;
844 			gopcode(OAS, nodconst(1), Z, nn);
845 			gbranch(OGOTO);
846 			p2 = p;
847 			patch(p1, pc);
848 			gopcode(OAS, nodconst(0), Z, nn);
849 			patch(p2, pc);
850 		}
851 		break;
852 	}
853 	cursafe = curs;
854 }
855 
856 void
857 sugen(Node *n, Node *nn, long w)
858 {
859 	Prog *p1;
860 	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
861 	Type *t;
862 	long pc1;
863 	int i, m, c;
864 
865 	if(n == Z || n->type == T)
866 		return;
867 	if(debug['g']) {
868 		prtree(nn, "sugen lhs");
869 		prtree(n, "sugen");
870 	}
871 	if(nn == nodrat)
872 		if(w > nrathole)
873 			nrathole = w;
874 	switch(n->op) {
875 	case OIND:
876 		if(nn == Z) {
877 			nullwarn(n->left, Z);
878 			break;
879 		}
880 
881 	default:
882 		goto copy;
883 
884 	case OCONST:
885 		if(n->type && typev[n->type->etype]) {
886 			if(nn == Z) {
887 				nullwarn(n->left, Z);
888 				break;
889 			}
890 
891 			t = nn->type;
892 			nn->type = types[TLONG];
893 			reglcgen(&nod1, nn, Z);
894 			nn->type = t;
895 
896 			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
897 				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
898 			else
899 				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
900 			nod1.xoffset += SZ_LONG;
901 			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
902 				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
903 			else
904 				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
905 
906 			regfree(&nod1);
907 			break;
908 		}
909 		goto copy;
910 
911 	case ODOT:
912 		l = n->left;
913 		sugen(l, nodrat, l->type->width);
914 		if(nn != Z) {
915 			warn(n, "non-interruptable temporary");
916 			nod1 = *nodrat;
917 			r = n->right;
918 			if(!r || r->op != OCONST) {
919 				diag(n, "DOT and no offset");
920 				break;
921 			}
922 			nod1.xoffset += (long)r->vconst;
923 			nod1.type = n->type;
924 			sugen(&nod1, nn, w);
925 		}
926 		break;
927 
928 	case OSTRUCT:
929 		/*
930 		 * rewrite so lhs has no fn call
931 		 */
932 		if(nn != Z && nn->complex >= FNX) {
933 			nod1 = *n;
934 			nod1.type = typ(TIND, n->type);
935 			regret(&nod2, &nod1);
936 			lcgen(nn, &nod2);
937 			regsalloc(&nod0, &nod1);
938 			gopcode(OAS, &nod2, Z, &nod0);
939 			regfree(&nod2);
940 
941 			nod1 = *n;
942 			nod1.op = OIND;
943 			nod1.left = &nod0;
944 			nod1.right = Z;
945 			nod1.complex = 1;
946 
947 			sugen(n, &nod1, w);
948 			return;
949 		}
950 
951 		r = n->left;
952 		for(t = n->type->link; t != T; t = t->down) {
953 			l = r;
954 			if(r->op == OLIST) {
955 				l = r->left;
956 				r = r->right;
957 			}
958 			if(nn == Z) {
959 				cgen(l, nn);
960 				continue;
961 			}
962 			/*
963 			 * hand craft *(&nn + o) = l
964 			 */
965 			nod0 = znode;
966 			nod0.op = OAS;
967 			nod0.type = t;
968 			nod0.left = &nod1;
969 			nod0.right = l;
970 
971 			nod1 = znode;
972 			nod1.op = OIND;
973 			nod1.type = t;
974 			nod1.left = &nod2;
975 
976 			nod2 = znode;
977 			nod2.op = OADD;
978 			nod2.type = typ(TIND, t);
979 			nod2.left = &nod3;
980 			nod2.right = &nod4;
981 
982 			nod3 = znode;
983 			nod3.op = OADDR;
984 			nod3.type = nod2.type;
985 			nod3.left = nn;
986 
987 			nod4 = znode;
988 			nod4.op = OCONST;
989 			nod4.type = nod2.type;
990 			nod4.vconst = t->offset;
991 
992 			ccom(&nod0);
993 			acom(&nod0);
994 			xcom(&nod0);
995 			nod0.addable = 0;
996 
997 			cgen(&nod0, Z);
998 		}
999 		break;
1000 
1001 	case OAS:
1002 		if(nn == Z) {
1003 			if(n->addable < INDEXED)
1004 				sugen(n->right, n->left, w);
1005 			break;
1006 		}
1007 		sugen(n->right, nodrat, w);
1008 		warn(n, "non-interruptable temporary");
1009 		sugen(nodrat, n->left, w);
1010 		sugen(nodrat, nn, w);
1011 		break;
1012 
1013 	case OFUNC:
1014 		if(nn == Z) {
1015 			sugen(n, nodrat, w);
1016 			break;
1017 		}
1018 		if(nn->op != OIND) {
1019 			nn = new1(OADDR, nn, Z);
1020 			nn->type = types[TIND];
1021 			nn->addable = 0;
1022 		} else
1023 			nn = nn->left;
1024 		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
1025 		n->type = types[TVOID];
1026 		n->left->type = types[TVOID];
1027 		cgen(n, Z);
1028 		break;
1029 
1030 	case OCOND:
1031 		bcgen(n->left, 1);
1032 		p1 = p;
1033 		sugen(n->right->left, nn, w);
1034 		gbranch(OGOTO);
1035 		patch(p1, pc);
1036 		p1 = p;
1037 		sugen(n->right->right, nn, w);
1038 		patch(p1, pc);
1039 		break;
1040 
1041 	case OCOMMA:
1042 		cgen(n->left, Z);
1043 		sugen(n->right, nn, w);
1044 		break;
1045 	}
1046 	return;
1047 
1048 copy:
1049 	if(nn == Z)
1050 		return;
1051 	if(n->complex >= FNX && nn->complex >= FNX) {
1052 		t = nn->type;
1053 		nn->type = types[TLONG];
1054 		regialloc(&nod1, nn, Z);
1055 		lcgen(nn, &nod1);
1056 		regsalloc(&nod2, nn);
1057 		nn->type = t;
1058 
1059 		gopcode(OAS, &nod1, Z, &nod2);
1060 		regfree(&nod1);
1061 
1062 		nod2.type = typ(TIND, t);
1063 
1064 		nod1 = nod2;
1065 		nod1.op = OIND;
1066 		nod1.left = &nod2;
1067 		nod1.right = Z;
1068 		nod1.complex = 1;
1069 		nod1.type = t;
1070 
1071 		sugen(n, &nod1, w);
1072 		return;
1073 	}
1074 
1075 	if(n->complex > nn->complex) {
1076 		t = n->type;
1077 		n->type = types[TLONG];
1078 		reglcgen(&nod1, n, Z);
1079 		n->type = t;
1080 
1081 		t = nn->type;
1082 		nn->type = types[TLONG];
1083 		reglcgen(&nod2, nn, Z);
1084 		nn->type = t;
1085 	} else {
1086 		t = nn->type;
1087 		nn->type = types[TLONG];
1088 		reglcgen(&nod2, nn, Z);
1089 		nn->type = t;
1090 
1091 		t = n->type;
1092 		n->type = types[TLONG];
1093 		reglcgen(&nod1, n, Z);
1094 		n->type = t;
1095 	}
1096 
1097 	w /= SZ_LONG;
1098 	if(w <= 5) {
1099 		layout(&nod1, &nod2, w, 0, Z);
1100 		goto out;
1101 	}
1102 
1103 	/*
1104 	 * minimize space for unrolling loop
1105 	 * 3,4,5 times. (6 or more is never minimum)
1106 	 * if small structure, try 2 also.
1107 	 */
1108 	c = 0; /* set */
1109 	m = 100;
1110 	i = 3;
1111 	if(w <= 15)
1112 		i = 2;
1113 	for(; i<=5; i++)
1114 		if(i + w%i <= m) {
1115 			c = i;
1116 			m = c + w%c;
1117 		}
1118 
1119 	regalloc(&nod3, &regnode, Z);
1120 	layout(&nod1, &nod2, w%c, w/c, &nod3);
1121 
1122 	pc1 = pc;
1123 	layout(&nod1, &nod2, c, 0, Z);
1124 
1125 	gopcode(OSUB, nodconst(1), Z, &nod3);
1126 	nod1.op = OREGISTER;
1127 	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
1128 	nod2.op = OREGISTER;
1129 	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
1130 
1131 	gopcode(OEQ, &nod3, Z, Z);
1132 	p->as = ABGTZ;
1133 	patch(p, pc1);
1134 
1135 	regfree(&nod3);
1136 out:
1137 	regfree(&nod1);
1138 	regfree(&nod2);
1139 }
1140 
1141 void
1142 layout(Node *f, Node *t, int c, int cv, Node *cn)
1143 {
1144 	Node t1, t2;
1145 
1146 	while(c > 3) {
1147 		layout(f, t, 2, 0, Z);
1148 		c -= 2;
1149 	}
1150 
1151 	regalloc(&t1, &regnode, Z);
1152 	regalloc(&t2, &regnode, Z);
1153 	t1.type = types[TLONG];
1154 	t2.type = types[TLONG];
1155 	if(c > 0) {
1156 		gopcode(OAS, f, Z, &t1);
1157 		f->xoffset += SZ_LONG;
1158 	}
1159 	if(cn != Z)
1160 		gopcode(OAS, nodconst(cv), Z, cn);
1161 	if(c > 1) {
1162 		gopcode(OAS, f, Z, &t2);
1163 		f->xoffset += SZ_LONG;
1164 	}
1165 	if(c > 0) {
1166 		gopcode(OAS, &t1, Z, t);
1167 		t->xoffset += SZ_LONG;
1168 	}
1169 	if(c > 2) {
1170 		gopcode(OAS, f, Z, &t1);
1171 		f->xoffset += SZ_LONG;
1172 	}
1173 	if(c > 1) {
1174 		gopcode(OAS, &t2, Z, t);
1175 		t->xoffset += SZ_LONG;
1176 	}
1177 	if(c > 2) {
1178 		gopcode(OAS, &t1, Z, t);
1179 		t->xoffset += SZ_LONG;
1180 	}
1181 	regfree(&t1);
1182 	regfree(&t2);
1183 }
1184