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