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