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