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