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