xref: /plan9-contrib/sys/src/cmd/qc/cgen.c (revision 40d015479ed36701ae6dcfd8814f849fc6285e8d)
1 #include "gc.h"
2 
3 static void cmpv(Node*, int, Node*);
4 static void testv(Node*, int);
5 static void cgen64(Node*, Node*);
6 static int isvconstable(int, vlong);
7 static void genasop(int, Node*, Node*, Node*);
8 
9 void
cgen(Node * n,Node * nn)10 cgen(Node *n, Node *nn)
11 {
12 	Node *l, *r;
13 	Prog *p1;
14 	Node nod, nod1, nod2, nod3, nod4;
15 	int o;
16 	long v, curs;
17 
18 	if(debug['g']) {
19 		prtree(nn, "cgen lhs");
20 		prtree(n, "cgen");
21 	}
22 	if(n == Z || n->type == T)
23 		return;
24 	if(typesu[n->type->etype]) {
25 		sugen(n, nn, n->type->width);
26 		return;
27 	}
28 	if(typev[n->type->etype]) {
29 		switch(n->op) {
30 		case OCONST:
31 		case OFUNC:
32 			cgen64(n, nn);
33 			return;
34 		}
35 	}
36 	l = n->left;
37 	r = n->right;
38 	o = n->op;
39 	if(n->addable >= INDEXED) {
40 		if(nn == Z) {
41 			switch(o) {
42 			default:
43 				nullwarn(Z, Z);
44 				break;
45 			case OINDEX:
46 				nullwarn(l, r);
47 				break;
48 			}
49 			return;
50 		}
51 		gmove(n, nn);
52 		return;
53 	}
54 	curs = cursafe;
55 
56 	if(n->complex >= FNX)
57 	if(l->complex >= FNX)
58 	if(r != Z && r->complex >= FNX)
59 	switch(o) {
60 	default:
61 		if(!typev[r->type->etype]) {
62 			regret(&nod, r);
63 			cgen(r, &nod);
64 			regsalloc(&nod1, r);
65 			gmove(&nod, &nod1);
66 			regfree(&nod);
67 		} else {
68 			regsalloc(&nod1, r);
69 			cgen(r, &nod1);
70 		}
71 
72 		nod = *n;
73 		nod.right = &nod1;
74 		cgen(&nod, nn);
75 		return;
76 
77 	case OFUNC:
78 	case OCOMMA:
79 	case OANDAND:
80 	case OOROR:
81 	case OCOND:
82 	case ODOT:
83 		break;
84 	}
85 
86 	switch(o) {
87 	default:
88 		diag(n, "unknown op in cgen: %O", o);
89 		break;
90 
91 	case ONEG:
92 	case OCOM:
93 		if(nn == Z) {
94 			nullwarn(l, Z);
95 			break;
96 		}
97 		regalloc(&nod, l, nn);
98 		cgen(l, &nod);
99 		gopcode(o, &nod, Z, &nod);
100 		gmove(&nod, nn);
101 		regfree(&nod);
102 		break;
103 
104 	case OAS:
105 		if(l->op == OBIT)
106 			goto bitas;
107 		if(l->addable >= INDEXED) {
108 			if(nn != Z || r->addable < INDEXED) {
109 				regalloc(&nod, r, nn);
110 				cgen(r, &nod);
111 				gmove(&nod, l);
112 				regfree(&nod);
113 			} else
114 				gmove(r, l);
115 			break;
116 		}
117 		if(l->complex >= r->complex) {
118 			reglcgen(&nod1, l, Z);
119 			if(r->addable >= INDEXED) {
120 				gmove(r, &nod1);
121 				if(nn != Z)
122 					gmove(r, nn);
123 				regfree(&nod1);
124 				break;
125 			}
126 			regalloc(&nod, r, nn);
127 			cgen(r, &nod);
128 		} else {
129 			regalloc(&nod, r, nn);
130 			cgen(r, &nod);
131 			reglcgen(&nod1, l, Z);
132 		}
133 		gmove(&nod, &nod1);
134 		regfree(&nod);
135 		regfree(&nod1);
136 		break;
137 
138 	bitas:
139 		n = l->left;
140 		regalloc(&nod, r, nn);
141 		if(l->complex >= r->complex) {
142 			reglcgen(&nod1, n, Z);
143 			cgen(r, &nod);
144 		} else {
145 			cgen(r, &nod);
146 			reglcgen(&nod1, n, Z);
147 		}
148 		regalloc(&nod2, n, Z);
149 		gopcode(OAS, &nod1, Z, &nod2);
150 		bitstore(l, &nod, &nod1, &nod2, nn);
151 		break;
152 
153 	case OBIT:
154 		if(nn == Z) {
155 			nullwarn(l, Z);
156 			break;
157 		}
158 		bitload(n, &nod, Z, Z, nn);
159 		gopcode(OAS, &nod, Z, nn);
160 		regfree(&nod);
161 		break;
162 
163 	case OXOR:
164 		if(nn != Z)
165 		if(r->op == OCONST && r->vconst == -1){
166 			regalloc(&nod, l, nn);
167 			cgen(l, &nod);
168 			gopcode(OCOM, &nod, Z, &nod);
169 			gmove(&nod, nn);
170 			regfree(&nod);
171 			break;
172 		}
173 
174 	case OADD:
175 	case OSUB:
176 	case OAND:
177 	case OOR:
178 	case OLSHR:
179 	case OASHL:
180 	case OASHR:
181 		/*
182 		 * immediate operands
183 		 */
184 		if(nn != Z && r->op == OCONST && !typefd[n->type->etype] &&
185 		    (!typev[n->type->etype] || isvconstable(o, r->vconst))) {
186 			regalloc(&nod, l, nn);
187 			cgen(l, &nod);
188 			if(o == OAND || r->vconst != 0)
189 				gopcode(o, r, Z, &nod);
190 			gmove(&nod, nn);
191 			regfree(&nod);
192 			break;
193 		}
194 
195 	case OMUL:
196 	case OLMUL:
197 	case OLDIV:
198 	case OLMOD:
199 	case ODIV:
200 	case OMOD:
201 		if(nn == Z) {
202 			nullwarn(l, r);
203 			break;
204 		}
205 		if((o == OMUL || o == OLMUL) && !typev[n->type->etype]) {
206 			if(mulcon(n, nn))
207 				break;
208 			if(debug['M'])
209 				print("%L multiply\n", n->lineno);
210 		}
211 		if(l->complex >= r->complex) {
212 			regalloc(&nod, l, nn);
213 			cgen(l, &nod);
214 			if(o != OMUL || typev[n->type->etype] || !sconst(r)) {
215 				regalloc(&nod1, r, Z);
216 				cgen(r, &nod1);
217 				gopcode(o, &nod1, Z, &nod);
218 				regfree(&nod1);
219 			} else
220 				gopcode(o, r, Z, &nod);
221 		} else {
222 			regalloc(&nod1, r, nn);
223 			cgen(r, &nod1);
224 			regalloc(&nod, l, Z);
225 			cgen(l, &nod);
226 			gopcode(o, &nod1, Z, &nod);
227 			regfree(&nod1);
228 		}
229 		gopcode(OAS, &nod, Z, nn);
230 		regfree(&nod);
231 		break;
232 
233 	case OASLSHR:
234 	case OASASHL:
235 	case OASASHR:
236 	case OASAND:
237 	case OASADD:
238 	case OASSUB:
239 	case OASXOR:
240 	case OASOR:
241 		if(l->op == OBIT)
242 			goto asbitop;
243 		if(r->op == OCONST && !typefd[r->type->etype] && !typefd[n->type->etype] &&
244 		   (!typev[n->type->etype] || isvconstable(o, r->vconst))) {
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 		regalloc(&nod3, r, Z);
276 		if(l->complex >= r->complex) {
277 			bitload(l, &nod, &nod1, &nod2, &nod4);
278 			cgen(r, &nod3);
279 		} else {
280 			cgen(r, &nod3);
281 			bitload(l, &nod, &nod1, &nod2, &nod4);
282 		}
283 		gmove(&nod, &nod4);
284 		gopcode(n->op, &nod3, Z, &nod4);
285 		regfree(&nod3);
286 		gmove(&nod4, &nod);
287 		regfree(&nod4);
288 		bitstore(l, &nod, &nod1, &nod2, nn);
289 		break;
290 
291 	case OADDR:
292 		if(nn == Z) {
293 			nullwarn(l, Z);
294 			break;
295 		}
296 		lcgen(l, nn);
297 		break;
298 
299 	case OFUNC:
300 		if(l->complex >= FNX) {
301 			if(l->op != OIND)
302 				diag(n, "bad function call");
303 
304 			regret(&nod, l->left);
305 			cgen(l->left, &nod);
306 			regsalloc(&nod1, l->left);
307 			gopcode(OAS, &nod, Z, &nod1);
308 			regfree(&nod);
309 
310 			nod = *n;
311 			nod.left = &nod2;
312 			nod2 = *l;
313 			nod2.left = &nod1;
314 			nod2.complex = 1;
315 			cgen(&nod, nn);
316 
317 			return;
318 		}
319 		o = reg[REGARG];
320 		gargs(r, &nod, &nod1);
321 		if(l->addable < INDEXED) {
322 			reglcgen(&nod, l, Z);
323 			gopcode(OFUNC, Z, Z, &nod);
324 			regfree(&nod);
325 		} else
326 			gopcode(OFUNC, Z, Z, l);
327 		if(REGARG)
328 			if(o != reg[REGARG])
329 				reg[REGARG]--;
330 		if(nn != Z) {
331 			regret(&nod, n);
332 			gopcode(OAS, &nod, Z, nn);
333 			regfree(&nod);
334 		}
335 		break;
336 
337 	case OIND:
338 		if(nn == Z) {
339 			cgen(l, nn);
340 			break;
341 		}
342 		regialloc(&nod, n, nn);
343 		r = l;
344 		while(r->op == OADD)
345 			r = r->right;
346 		if(sconst(r)) {
347 			v = r->vconst;
348 			r->vconst = 0;
349 			cgen(l, &nod);
350 			nod.xoffset += v;
351 			r->vconst = v;
352 		} else
353 			cgen(l, &nod);
354 		regind(&nod, n);
355 		gmove(&nod, nn);
356 		regfree(&nod);
357 		break;
358 
359 	case OEQ:
360 	case ONE:
361 	case OLE:
362 	case OLT:
363 	case OGE:
364 	case OGT:
365 	case OLO:
366 	case OLS:
367 	case OHI:
368 	case OHS:
369 		if(nn == Z) {
370 			nullwarn(l, r);
371 			break;
372 		}
373 		boolgen(n, 1, nn);
374 		break;
375 
376 	case OANDAND:
377 	case OOROR:
378 		boolgen(n, 1, nn);
379 		if(nn == Z)
380 			patch(p, pc);
381 		break;
382 
383 	case ONOT:
384 		if(nn == Z) {
385 			nullwarn(l, Z);
386 			break;
387 		}
388 		boolgen(n, 1, nn);
389 		break;
390 
391 	case OCOMMA:
392 		cgen(l, Z);
393 		cgen(r, nn);
394 		break;
395 
396 	case OCAST:
397 		if(nn == Z) {
398 			nullwarn(l, Z);
399 			break;
400 		}
401 		/*
402 		 * convert from types l->n->nn
403 		 */
404 		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
405 			/* both null, gen l->nn */
406 			cgen(l, nn);
407 			break;
408 		}
409 		if(typev[l->type->etype] || typev[n->type->etype]) {
410 			cgen64(n, nn);
411 			break;
412 		}
413 		regalloc(&nod, l, nn);
414 		cgen(l, &nod);
415 		regalloc(&nod1, n, &nod);
416 		gmove(&nod, &nod1);
417 		gmove(&nod1, nn);
418 		regfree(&nod1);
419 		regfree(&nod);
420 		break;
421 
422 	case ODOT:
423 		sugen(l, nodrat, l->type->width);
424 		if(nn != Z) {
425 			warn(n, "non-interruptable temporary");
426 			nod = *nodrat;
427 			if(!r || r->op != OCONST) {
428 				diag(n, "DOT and no offset");
429 				break;
430 			}
431 			nod.xoffset += (long)r->vconst;
432 			nod.type = n->type;
433 			cgen(&nod, nn);
434 		}
435 		break;
436 
437 	case OCOND:
438 		bcgen(l, 1);
439 		p1 = p;
440 		cgen(r->left, nn);
441 		gbranch(OGOTO);
442 		patch(p1, pc);
443 		p1 = p;
444 		cgen(r->right, nn);
445 		patch(p1, pc);
446 		break;
447 
448 	case OPOSTINC:
449 	case OPOSTDEC:
450 		v = 1;
451 		if(l->type->etype == TIND)
452 			v = l->type->link->width;
453 		if(o == OPOSTDEC)
454 			v = -v;
455 		if(l->op == OBIT)
456 			goto bitinc;
457 		if(nn == Z)
458 			goto pre;
459 
460 		if(l->addable < INDEXED)
461 			reglcgen(&nod2, l, Z);
462 		else
463 			nod2 = *l;
464 
465 		regalloc(&nod, l, nn);
466 		gopcode(OAS, &nod2, Z, &nod);
467 		regalloc(&nod1, l, Z);
468 		if(typefd[l->type->etype]) {
469 			regalloc(&nod3, l, Z);
470 			if(v < 0) {
471 				gopcode(OAS, nodfconst(-v), Z, &nod3);
472 				gopcode(OSUB, &nod3, &nod, &nod1);
473 			} else {
474 				gopcode(OAS, nodfconst(v), Z, &nod3);
475 				gopcode(OADD, &nod3, &nod, &nod1);
476 			}
477 			regfree(&nod3);
478 		} else
479 			gopcode(OADD, nodconst(v), &nod, &nod1);
480 		gopcode(OAS, &nod1, Z, &nod2);
481 
482 		regfree(&nod);
483 		regfree(&nod1);
484 		if(l->addable < INDEXED)
485 			regfree(&nod2);
486 		break;
487 
488 	case OPREINC:
489 	case OPREDEC:
490 		v = 1;
491 		if(l->type->etype == TIND)
492 			v = l->type->link->width;
493 		if(o == OPREDEC)
494 			v = -v;
495 		if(l->op == OBIT)
496 			goto bitinc;
497 
498 	pre:
499 		if(l->addable < INDEXED)
500 			reglcgen(&nod2, l, Z);
501 		else
502 			nod2 = *l;
503 
504 		regalloc(&nod, l, nn);
505 		gopcode(OAS, &nod2, Z, &nod);
506 		if(typefd[l->type->etype]) {
507 			regalloc(&nod3, l, Z);
508 			if(v < 0) {
509 				gopcode(OAS, nodfconst(-v), Z, &nod3);
510 				gopcode(OSUB, &nod3, Z, &nod);
511 			} else {
512 				gopcode(OAS, nodfconst(v), Z, &nod3);
513 				gopcode(OADD, &nod3, Z, &nod);
514 			}
515 			regfree(&nod3);
516 		} else
517 			gopcode(OADD, nodconst(v), Z, &nod);
518 		gopcode(OAS, &nod, Z, &nod2);
519 		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
520 			gins(ANOP, l, Z);
521 
522 		regfree(&nod);
523 		if(l->addable < INDEXED)
524 			regfree(&nod2);
525 		break;
526 
527 	bitinc:
528 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
529 			bitload(l, &nod, &nod1, &nod2, Z);
530 			gopcode(OAS, &nod, Z, nn);
531 			gopcode(OADD, nodconst(v), Z, &nod);
532 			bitstore(l, &nod, &nod1, &nod2, Z);
533 			break;
534 		}
535 		bitload(l, &nod, &nod1, &nod2, nn);
536 		gopcode(OADD, nodconst(v), Z, &nod);
537 		bitstore(l, &nod, &nod1, &nod2, nn);
538 		break;
539 	}
540 	cursafe = curs;
541 }
542 
543 static void
genasop(int o,Node * l,Node * r,Node * nn)544 genasop(int o, Node *l, Node *r, Node *nn)
545 {
546 	Node nod, nod1, nod2;
547 	int hardleft;
548 
549 	hardleft = l->addable < INDEXED || l->complex >= FNX;
550 	if(l->complex >= r->complex) {
551 		if(hardleft)
552 			reglcgen(&nod2, l, Z);
553 		else
554 			nod2 = *l;
555 		regalloc(&nod1, r, Z);
556 		cgen(r, &nod1);
557 	} else {
558 		regalloc(&nod1, r, Z);
559 		cgen(r, &nod1);
560 		if(hardleft)
561 			reglcgen(&nod2, l, Z);
562 		else
563 			nod2 = *l;
564 	}
565 	if(nod1.type == nod2.type || !typefd[nod1.type->etype])
566 		regalloc(&nod, &nod2, nn);
567 	else
568 		regalloc(&nod, &nod1, Z);
569 	gmove(&nod2, &nod);
570 	gopcode(o, &nod1, Z, &nod);
571 	gmove(&nod, &nod2);
572 	if(nn != Z)
573 		gmove(&nod2, nn);
574 	regfree(&nod);
575 	regfree(&nod1);
576 	if(hardleft)
577 		regfree(&nod2);
578 }
579 
580 void
reglcgen(Node * t,Node * n,Node * nn)581 reglcgen(Node *t, Node *n, Node *nn)
582 {
583 	Node *r;
584 	long v;
585 
586 	regialloc(t, n, nn);
587 	if(n->op == OIND) {
588 		r = n->left;
589 		while(r->op == OADD)
590 			r = r->right;
591 		if(sconst(r)) {
592 			v = r->vconst;
593 			r->vconst = 0;
594 			lcgen(n, t);
595 			t->xoffset += v;
596 			r->vconst = v;
597 			regind(t, n);
598 			return;
599 		}
600 	}
601 	lcgen(n, t);
602 	regind(t, n);
603 }
604 
605 void
lcgen(Node * n,Node * nn)606 lcgen(Node *n, Node *nn)
607 {
608 	Prog *p1;
609 	Node nod;
610 
611 	if(debug['g']) {
612 		prtree(nn, "lcgen lhs");
613 		prtree(n, "lcgen");
614 	}
615 	if(n == Z || n->type == T)
616 		return;
617 	if(nn == Z) {
618 		nn = &nod;
619 		regalloc(&nod, n, Z);
620 	}
621 	switch(n->op) {
622 	default:
623 		if(n->addable < INDEXED) {
624 			diag(n, "unknown op in lcgen: %O", n->op);
625 			break;
626 		}
627 		nod = *n;
628 		nod.op = OADDR;
629 		nod.left = n;
630 		nod.right = Z;
631 		nod.type = types[TIND];
632 		gopcode(OAS, &nod, Z, nn);
633 		break;
634 
635 	case OCOMMA:
636 		cgen(n->left, n->left);
637 		lcgen(n->right, nn);
638 		break;
639 
640 	case OIND:
641 		cgen(n->left, nn);
642 		break;
643 
644 	case OCOND:
645 		bcgen(n->left, 1);
646 		p1 = p;
647 		lcgen(n->right->left, nn);
648 		gbranch(OGOTO);
649 		patch(p1, pc);
650 		p1 = p;
651 		lcgen(n->right->right, nn);
652 		patch(p1, pc);
653 		break;
654 	}
655 }
656 
657 void
bcgen(Node * n,int true)658 bcgen(Node *n, int true)
659 {
660 
661 	if(n->type == T)
662 		gbranch(OGOTO);
663 	else
664 		boolgen(n, true, Z);
665 }
666 
667 void
boolgen(Node * n,int true,Node * nn)668 boolgen(Node *n, int true, Node *nn)
669 {
670 	int o, uns;
671 	Prog *p1, *p2;
672 	Node *l, *r, nod, nod1;
673 	long curs;
674 
675 	if(debug['g']) {
676 		prtree(nn, "boolgen lhs");
677 		prtree(n, "boolgen");
678 	}
679 	uns = 0;
680 	curs = cursafe;
681 	l = n->left;
682 	r = n->right;
683 	switch(n->op) {
684 
685 	default:
686 		if(n->op == 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 		if(typev[n->type->etype]) {
699 			testv(n, true);
700 			goto com;
701 		}
702 		regalloc(&nod, n, nn);
703 		cgen(n, &nod);
704 		o = ONE;
705 		if(true)
706 			o = comrel[relindex(o)];
707 		if(typefd[n->type->etype]) {
708 			nodreg(&nod1, n, NREG+FREGZERO);
709 			gopcode(o, &nod, Z, &nod1);
710 		} else
711 			gopcode(o, &nod, Z, nodconst(0));
712 		regfree(&nod);
713 		goto com;
714 
715 	case OCOMMA:
716 		cgen(l, Z);
717 		boolgen(r, true, nn);
718 		break;
719 
720 	case ONOT:
721 		boolgen(l, !true, nn);
722 		break;
723 
724 	case OCOND:
725 		bcgen(l, 1);
726 		p1 = p;
727 		bcgen(r->left, true);
728 		p2 = p;
729 		gbranch(OGOTO);
730 		patch(p1, pc);
731 		p1 = p;
732 		bcgen(r->right, !true);
733 		patch(p2, pc);
734 		p2 = p;
735 		gbranch(OGOTO);
736 		patch(p1, pc);
737 		patch(p2, pc);
738 		goto com;
739 
740 	case OANDAND:
741 		if(!true)
742 			goto caseor;
743 
744 	caseand:
745 		bcgen(l, true);
746 		p1 = p;
747 		bcgen(r, !true);
748 		p2 = p;
749 		patch(p1, pc);
750 		gbranch(OGOTO);
751 		patch(p2, pc);
752 		goto com;
753 
754 	case OOROR:
755 		if(!true)
756 			goto caseand;
757 
758 	caseor:
759 		bcgen(l, !true);
760 		p1 = p;
761 		bcgen(r, !true);
762 		p2 = p;
763 		gbranch(OGOTO);
764 		patch(p1, pc);
765 		patch(p2, pc);
766 		goto com;
767 
768 	case OHI:
769 	case OHS:
770 	case OLO:
771 	case OLS:
772 		uns = 1;
773 		/* fall through */
774 	case OEQ:
775 	case ONE:
776 	case OLE:
777 	case OLT:
778 	case OGE:
779 	case OGT:
780 		if(typev[l->type->etype]){
781 			cmpv(n, true, Z);
782 			goto com;
783 		}
784 		o = n->op;
785 		if(true)
786 			o = comrel[relindex(o)];
787 		if(l->complex >= FNX && r->complex >= FNX) {
788 			regret(&nod, r);
789 			cgen(r, &nod);
790 			regsalloc(&nod1, r);
791 			gopcode(OAS, &nod, Z, &nod1);
792 			regfree(&nod);
793 			nod = *n;
794 			nod.right = &nod1;
795 			boolgen(&nod, true, nn);
796 			break;
797 		}
798 		if(!uns && sconst(r) || (uns || o == OEQ || o == ONE) && uconst(r)) {
799 			regalloc(&nod, l, nn);
800 			cgen(l, &nod);
801 			gopcode(o, &nod, Z, r);
802 			regfree(&nod);
803 			goto com;
804 		}
805 		if(l->complex >= r->complex) {
806 			regalloc(&nod1, l, nn);
807 			cgen(l, &nod1);
808 			regalloc(&nod, r, Z);
809 			cgen(r, &nod);
810 		} else {
811 			regalloc(&nod, r, nn);
812 			cgen(r, &nod);
813 			regalloc(&nod1, l, Z);
814 			cgen(l, &nod1);
815 		}
816 		gopcode(o, &nod1, Z, &nod);
817 		regfree(&nod);
818 		regfree(&nod1);
819 
820 	com:
821 		if(nn != Z) {
822 			p1 = p;
823 			gopcode(OAS, nodconst(1L), Z, nn);
824 			gbranch(OGOTO);
825 			p2 = p;
826 			patch(p1, pc);
827 			gopcode(OAS, nodconst(0L), Z, nn);
828 			patch(p2, pc);
829 		}
830 		break;
831 	}
832 	cursafe = curs;
833 }
834 
835 void
sugen(Node * n,Node * nn,long w)836 sugen(Node *n, Node *nn, long w)
837 {
838 	Prog *p1;
839 	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
840 	Type *t;
841 	long pc1;
842 	int i, m, c;
843 
844 	if(n == Z || n->type == T)
845 		return;
846 	if(nn == nodrat)
847 		if(w > nrathole)
848 			nrathole = w;
849 	if(debug['g']) {
850 		prtree(nn, "sugen lhs");
851 		prtree(n, "sugen");
852 	}
853 	if(typev[n->type->etype]) {
854 		diag(n, "old vlong sugen: %O", n->op);
855 		return;
856 	}
857 	switch(n->op) {
858 	case OIND:
859 		if(nn == Z) {
860 			nullwarn(n->left, Z);
861 			break;
862 		}
863 
864 	default:
865 		goto copy;
866 
867 	case ODOT:
868 		l = n->left;
869 		sugen(l, nodrat, l->type->width);
870 		if(nn != Z) {
871 			warn(n, "non-interruptable temporary");
872 			nod1 = *nodrat;
873 			r = n->right;
874 			if(!r || r->op != OCONST) {
875 				diag(n, "DOT and no offset");
876 				break;
877 			}
878 			nod1.xoffset += (long)r->vconst;
879 			nod1.type = n->type;
880 			sugen(&nod1, nn, w);
881 		}
882 		break;
883 
884 	case OSTRUCT:
885 		/*
886 		 * rewrite so lhs has no side effects
887 		 */
888 		if(nn != Z && side(nn)) {
889 			nod1 = *n;
890 			nod1.type = typ(TIND, n->type);
891 			regalloc(&nod2, &nod1, Z);
892 			lcgen(nn, &nod2);
893 			regsalloc(&nod0, &nod1);
894 			gopcode(OAS, &nod2, Z, &nod0);
895 			regfree(&nod2);
896 
897 			nod1 = *n;
898 			nod1.op = OIND;
899 			nod1.left = &nod0;
900 			nod1.right = Z;
901 			nod1.complex = 1;
902 
903 			sugen(n, &nod1, w);
904 			return;
905 		}
906 
907 		r = n->left;
908 		for(t = n->type->link; t != T; t = t->down) {
909 			l = r;
910 			if(r->op == OLIST) {
911 				l = r->left;
912 				r = r->right;
913 			}
914 			if(nn == Z) {
915 				cgen(l, nn);
916 				continue;
917 			}
918 			/*
919 			 * hand craft *(&nn + o) = l
920 			 */
921 			nod0 = znode;
922 			nod0.op = OAS;
923 			nod0.type = t;
924 			nod0.left = &nod1;
925 			nod0.right = l;
926 
927 			nod1 = znode;
928 			nod1.op = OIND;
929 			nod1.type = t;
930 			nod1.left = &nod2;
931 
932 			nod2 = znode;
933 			nod2.op = OADD;
934 			nod2.type = typ(TIND, t);
935 			nod2.left = &nod3;
936 			nod2.right = &nod4;
937 
938 			nod3 = znode;
939 			nod3.op = OADDR;
940 			nod3.type = nod2.type;
941 			nod3.left = nn;
942 
943 			nod4 = znode;
944 			nod4.op = OCONST;
945 			nod4.type = nod2.type;
946 			nod4.vconst = t->offset;
947 
948 			ccom(&nod0);
949 			acom(&nod0);
950 			xcom(&nod0);
951 			nod0.addable = 0;
952 
953 			/* prtree(&nod0, "hand craft"); /* */
954 			cgen(&nod0, Z);
955 		}
956 		break;
957 
958 	case OAS:
959 		if(nn == Z) {
960 			if(n->addable < INDEXED)
961 				sugen(n->right, n->left, w);
962 			break;
963 		}
964 		/* BOTCH -- functions can clobber rathole */
965 		sugen(n->right, nodrat, w);
966 		warn(n, "non-interruptable temporary");
967 		sugen(nodrat, n->left, w);
968 		sugen(nodrat, nn, w);
969 		break;
970 
971 	case OFUNC:
972 		/* this transformation should probably be done earlier */
973 		if(nn == Z) {
974 			sugen(n, nodrat, w);
975 			break;
976 		}
977 		if(nn->op != OIND) {
978 			nn = new1(OADDR, nn, Z);
979 			nn->type = types[TIND];
980 			nn->addable = 0;
981 		} else
982 			nn = nn->left;
983 		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
984 		n->complex = FNX;
985 		n->type = types[TVOID];
986 		n->left->type = types[TVOID];
987 		cgen(n, Z);
988 		break;
989 
990 	case OCOND:
991 		bcgen(n->left, 1);
992 		p1 = p;
993 		sugen(n->right->left, nn, w);
994 		gbranch(OGOTO);
995 		patch(p1, pc);
996 		p1 = p;
997 		sugen(n->right->right, nn, w);
998 		patch(p1, pc);
999 		break;
1000 
1001 	case OCOMMA:
1002 		cgen(n->left, Z);
1003 		sugen(n->right, nn, w);
1004 		break;
1005 	}
1006 	return;
1007 
1008 copy:
1009 	if(nn == Z)
1010 		return;
1011 	if(n->complex >= FNX && nn->complex >= FNX) {
1012 		t = nn->type;
1013 		nn->type = types[TLONG];
1014 		regialloc(&nod1, nn, Z);
1015 		lcgen(nn, &nod1);
1016 		regsalloc(&nod2, nn);
1017 		nn->type = t;
1018 
1019 		gmove(&nod1, &nod2);
1020 		regfree(&nod1);
1021 
1022 		nod2.type = typ(TIND, t);
1023 
1024 		nod1 = nod2;
1025 		nod1.op = OIND;
1026 		nod1.left = &nod2;
1027 		nod1.right = Z;
1028 		nod1.complex = 1;
1029 		nod1.type = t;
1030 
1031 		sugen(n, &nod1, w);
1032 		return;
1033 	}
1034 
1035 	if(n->complex > nn->complex) {
1036 		t = n->type;
1037 		n->type = types[TLONG];
1038 		reglcgen(&nod1, n, Z);
1039 		n->type = t;
1040 
1041 		t = nn->type;
1042 		nn->type = types[TLONG];
1043 		reglcgen(&nod2, nn, Z);
1044 		nn->type = t;
1045 	} else {
1046 		t = nn->type;
1047 		nn->type = types[TLONG];
1048 		reglcgen(&nod2, nn, Z);
1049 		nn->type = t;
1050 
1051 		t = n->type;
1052 		n->type = types[TLONG];
1053 		reglcgen(&nod1, n, Z);
1054 		n->type = t;
1055 	}
1056 
1057 	w /= SZ_LONG;
1058 	if(w <= 5) {
1059 		layout(&nod1, &nod2, w, 0, Z);
1060 		goto out;
1061 	}
1062 
1063 	/*
1064 	 * minimize space for unrolling loop
1065 	 * 3,4,5 times. (6 or more is never minimum)
1066 	 * if small structure, try 2 also.
1067 	 */
1068 	c = 0; /* set */
1069 	m = 100;
1070 	i = 3;
1071 	if(w <= 15)
1072 		i = 2;
1073 	for(; i<=5; i++)
1074 		if(i + w%i <= m) {
1075 			c = i;
1076 			m = c + w%c;
1077 		}
1078 
1079 	regalloc(&nod3, &regnode, Z);
1080 	layout(&nod1, &nod2, w%c, w/c, &nod3);
1081 
1082 	pc1 = pc;
1083 	layout(&nod1, &nod2, c, 0, Z);
1084 
1085 	gopcode(OSUB, nodconst(1L), Z, &nod3);
1086 	nod1.op = OREGISTER;
1087 	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
1088 	nod2.op = OREGISTER;
1089 	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
1090 
1091 	gopcode(OGT, &nod3, Z, nodconst(0));
1092 	patch(p, pc1);
1093 
1094 	regfree(&nod3);
1095 out:
1096 	regfree(&nod1);
1097 	regfree(&nod2);
1098 }
1099 
1100 void
layout(Node * f,Node * t,int c,int cv,Node * cn)1101 layout(Node *f, Node *t, int c, int cv, Node *cn)
1102 {
1103 	Node t1, t2;
1104 
1105 	while(c > 3) {
1106 		layout(f, t, 2, 0, Z);
1107 		c -= 2;
1108 	}
1109 
1110 	regalloc(&t1, &regnode, Z);
1111 	regalloc(&t2, &regnode, Z);
1112 	if(c > 0) {
1113 		gopcode(OAS, f, Z, &t1);
1114 		f->xoffset += SZ_LONG;
1115 	}
1116 	if(cn != Z)
1117 		gopcode(OAS, nodconst(cv), Z, cn);
1118 	if(c > 1) {
1119 		gopcode(OAS, f, Z, &t2);
1120 		f->xoffset += SZ_LONG;
1121 	}
1122 	if(c > 0) {
1123 		gopcode(OAS, &t1, Z, t);
1124 		t->xoffset += SZ_LONG;
1125 	}
1126 	if(c > 2) {
1127 		gopcode(OAS, f, Z, &t1);
1128 		f->xoffset += SZ_LONG;
1129 	}
1130 	if(c > 1) {
1131 		gopcode(OAS, &t2, Z, t);
1132 		t->xoffset += SZ_LONG;
1133 	}
1134 	if(c > 2) {
1135 		gopcode(OAS, &t1, Z, t);
1136 		t->xoffset += SZ_LONG;
1137 	}
1138 	regfree(&t1);
1139 	regfree(&t2);
1140 }
1141 
1142 /*
1143  * is the vlong's value directly addressible?
1144  */
1145 int
isvdirect(Node * n)1146 isvdirect(Node *n)
1147 {
1148 	return n->op == ONAME || n->op == OCONST || n->op == OINDREG;
1149 }
1150 
1151 /*
1152  * can the constant be used with given vlong op?
1153  */
1154 static int
isvconstable(int o,vlong v)1155 isvconstable(int o, vlong v)
1156 {
1157 	switch(o) {
1158 	case OADD:
1159 	case OASADD:
1160 		/* there isn't an immediate form for ADDE/SUBE, but there are special ADDME/ADDZE etc */
1161 		return v == 0 || v == -1;
1162 	case OAND:
1163 	case OOR:
1164 	case OXOR:
1165 	case OLSHR:
1166 	case OASHL:
1167 	case OASHR:
1168 	case OASLSHR:
1169 	case OASASHL:
1170 	case OASASHR:
1171 		return 1;
1172 	}
1173 	return 0;
1174 }
1175 
1176 /*
1177  * most 64-bit operations: cgen into a register pair, then operate.
1178  * 64-bit comparisons are handled a little differently because the two underlying
1179  * comparisons can be compiled separately, since the calculations don't interact.
1180  */
1181 
1182 static void
vcgen(Node * n,Node * o,int * f)1183 vcgen(Node *n, Node *o, int *f)
1184 {
1185 	*f = 0;
1186 	if(!isvdirect(n)) {
1187 		if(n->complex >= FNX) {
1188 			regsalloc(o, n);
1189 			cgen(n, o);
1190 			return;
1191 		}
1192 		*f = 1;
1193 		if(n->addable < INDEXED && n->op != OIND && n->op != OINDEX) {
1194 			regalloc(o, n, Z);
1195 			cgen(n, o);
1196 		} else
1197 			reglcgen(o, n, Z);
1198 	} else
1199 		*o = *n;
1200 }
1201 
1202 static int
isuns(int op)1203 isuns(int op)
1204 {
1205 	switch(op){
1206 	case OLO:
1207 	case OLS:
1208 	case OHI:
1209 	case OHS:
1210 		return 1;
1211 	default:
1212 		return 0;
1213 	}
1214 }
1215 
1216 static void
gcmpv(Node * l,Node * r,void (* mov)(Node *,Node *,int),int op)1217 gcmpv(Node *l, Node *r, void (*mov)(Node*, Node*, int), int op)
1218 {
1219 	Node vl, vr;
1220 
1221 	regalloc(&vl, &regnode, Z);
1222 	mov(l, &vl, 0);
1223 	regalloc(&vr, &regnode, Z);
1224 	mov(r, &vr, 1+isuns(op));
1225 	gopcode(op, &vl, Z, &vr);
1226 	if(vl.op == OREGISTER)
1227 		regfree(&vl);
1228 	if(vr.op == OREGISTER)
1229 		regfree(&vr);
1230 }
1231 
1232 static void
brcondv(Node * l,Node * r,int chi,int clo)1233 brcondv(Node *l, Node *r, int chi, int clo)
1234 {
1235 	Prog *p1, *p2, *p3, *p4;
1236 
1237 	gcmpv(l, r, gloadhi, chi);
1238 	p1 = p;
1239 	gins(ABNE, Z, Z);
1240 	p2 = p;
1241 	gcmpv(l, r, gloadlo, clo);
1242 	p3 = p;
1243 	gbranch(OGOTO);
1244 	p4 = p;
1245 	patch(p1, pc);
1246 	patch(p3, pc);
1247 	gbranch(OGOTO);
1248 	patch(p2, pc);
1249 	patch(p4, pc);
1250 }
1251 
1252 static void
testv(Node * n,int true)1253 testv(Node *n, int true)
1254 {
1255 	Node nod;
1256 
1257 	nod = znode;
1258 	nod.op = ONE;
1259 	nod.left = n;
1260 	nod.right = new1(0, Z, Z);
1261 	*nod.right = *nodconst(0);
1262 	nod.right->type = n->type;
1263 	nod.type = types[TLONG];
1264 	cmpv(&nod, true, Z);
1265 }
1266 
1267 /*
1268  * comparison for vlong does high and low order parts separately,
1269  * which saves loading the latter if the high order comparison suffices
1270  */
1271 static void
cmpv(Node * n,int true,Node * nn)1272 cmpv(Node *n, int true, Node *nn)
1273 {
1274 	Node *l, *r, nod, nod1;
1275 	int o, f1, f2;
1276 	Prog *p1, *p2;
1277 	long curs;
1278 
1279 	if(debug['g']) {
1280 		if(nn != nil)
1281 			prtree(nn, "cmpv lhs");
1282 		prtree(n, "cmpv");
1283 	}
1284 	curs = cursafe;
1285 	l = n->left;
1286 	r = n->right;
1287 	if(l->complex >= FNX && r->complex >= FNX) {
1288 		regsalloc(&nod1, r);
1289 		cgen(r, &nod1);
1290 		nod = *n;
1291 		nod.right = &nod1;
1292 		cmpv(&nod, true, nn);
1293 		cursafe = curs;
1294 		return;
1295 	}
1296 	if(l->complex >= r->complex) {
1297 		vcgen(l, &nod1, &f1);
1298 		vcgen(r, &nod, &f2);
1299 	} else {
1300 		vcgen(r, &nod, &f2);
1301 		vcgen(l, &nod1, &f1);
1302 	}
1303 	nod.type = types[TLONG];
1304 	nod1.type = types[TLONG];
1305 	o = n->op;
1306 	if(true)
1307 		o = comrel[relindex(o)];
1308 	switch(o){
1309 	case OEQ:
1310 		gcmpv(&nod1, &nod, gloadhi, ONE);
1311 		p1 = p;
1312 		gcmpv(&nod1, &nod, gloadlo, ONE);
1313 		p2 = p;
1314 		gbranch(OGOTO);
1315 		patch(p1, pc);
1316 		patch(p2, pc);
1317 		break;
1318 	case ONE:
1319 		gcmpv(&nod1, &nod, gloadhi, ONE);
1320 		p1 = p;
1321 		gcmpv(&nod1, &nod, gloadlo, OEQ);
1322 		p2 = p;
1323 		patch(p1, pc);
1324 		gbranch(OGOTO);
1325 		patch(p2, pc);
1326 		break;
1327 	case OLE:
1328 		brcondv(&nod1, &nod, OLT, OLS);
1329 		break;
1330 	case OGT:
1331 		brcondv(&nod1, &nod, OGT, OHI);
1332 		break;
1333 	case OLS:
1334 		brcondv(&nod1, &nod, OLO, OLS);
1335 		break;
1336 	case OHI:
1337 		brcondv(&nod1, &nod, OHI, OHI);
1338 		break;
1339 	case OLT:
1340 		brcondv(&nod1, &nod, OLT, OLO);
1341 		break;
1342 	case OGE:
1343 		brcondv(&nod1, &nod, OGT, OHS);
1344 		break;
1345 	case OLO:
1346 		brcondv(&nod1, &nod, OLO, OLO);
1347 		break;
1348 	case OHS:
1349 		brcondv(&nod1, &nod, OHI, OHS);
1350 		break;
1351 	default:
1352 		diag(n, "bad cmpv");
1353 		return;
1354 	}
1355 	if(f1)
1356 		regfree(&nod1);
1357 	if(f2)
1358 		regfree(&nod);
1359 	cursafe = curs;
1360 }
1361 
1362 static void
cgen64(Node * n,Node * nn)1363 cgen64(Node *n, Node *nn)
1364 {
1365 	Node *l, *r, *d;
1366 	Node nod, nod1;
1367 	long curs;
1368 	Type *t;
1369 	int o, m;
1370 
1371 	curs = cursafe;
1372 	l = n->left;
1373 	r = n->right;
1374 	o = n->op;
1375 	switch(o) {
1376 
1377 	case OCONST:
1378 		if(nn == Z) {
1379 			nullwarn(n->left, Z);
1380 			break;
1381 		}
1382 		if(nn->op != OREGPAIR) {
1383 //prtree(n, "cgen64 const");
1384 			t = nn->type;
1385 			nn->type = types[TLONG];
1386 			reglcgen(&nod1, nn, Z);
1387 			nn->type = t;
1388 
1389 			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
1390 				gmove(nod32const(n->vconst>>32), &nod1);
1391 			else
1392 				gmove(nod32const(n->vconst), &nod1);
1393 			nod1.xoffset += SZ_LONG;
1394 			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
1395 				gmove(nod32const(n->vconst), &nod1);
1396 			else
1397 				gmove(nod32const(n->vconst>>32), &nod1);
1398 
1399 			regfree(&nod1);
1400 		} else
1401 			gmove(n, nn);
1402 		break;
1403 
1404 	case OCAST:
1405 		/*
1406 		 * convert from types l->n->nn
1407 		 */
1408 		if(typev[l->type->etype]){
1409 			/* vlong to non-vlong */
1410 			if(!isvdirect(l)) {
1411 				if(l->addable < INDEXED && l->op != OIND && l->op != OINDEX) {
1412 					regalloc(&nod, l, l);
1413 					cgen(l, &nod);
1414 					regalloc(&nod1, n, nn);
1415 					gmove(nod.right, &nod1);
1416 				} else {
1417 					reglcgen(&nod, l, Z);
1418 					regalloc(&nod1, n, nn);
1419 					gloadlo(&nod, &nod1, 0);	/* TO DO: not correct for typefd */
1420 				}
1421 				regfree(&nod);
1422 			} else {
1423 				regalloc(&nod1, n, nn);
1424 				gloadlo(l, &nod1, 0);	/* TO DO: not correct for typefd */
1425 			}
1426 		}else{
1427 			/* non-vlong to vlong */
1428 			regalloc(&nod, l, Z);
1429 			cgen(l, &nod);
1430 			regalloc(&nod1, n, nn);
1431 			gmove(&nod, nod1.right);
1432 			if(typeu[l->type->etype])
1433 				gmove(nodconst(0), nod1.left);
1434 			else
1435 				gopcode(OASHR, nodconst(31), nod1.right, nod1.left);
1436 			regfree(&nod);
1437 		}
1438 		gmove(&nod1, nn);
1439 		regfree(&nod1);
1440 		break;
1441 
1442 	case OFUNC:
1443 		/* this transformation should probably be done earlier */
1444 		if(nn == Z) {
1445 			regsalloc(&nod1, n);
1446 			nn = &nod1;
1447 		}
1448 		m = 0;
1449 		if(nn->op != OIND) {
1450 			if(nn->op == OREGPAIR) {
1451 				m = 1;
1452 				regsalloc(&nod1, nn);
1453 				d = &nod1;
1454 			}else
1455 				d = nn;
1456 			d = new1(OADDR, d, Z);
1457 			d->type = types[TIND];
1458 			d->addable = 0;
1459 		} else
1460 			d = nn->left;
1461 		n = new(OFUNC, l, new(OLIST, d, r));
1462 		n->complex = FNX;
1463 		n->type = types[TVOID];
1464 		n->left->type = types[TVOID];
1465 		cgen(n, Z);
1466 		if(m)
1467 			gmove(&nod1, nn);
1468 		break;
1469 
1470 	default:
1471 		diag(n, "bad cgen64 %O", o);
1472 		break;
1473 	}
1474 	cursafe = curs;
1475 }
1476