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, ®node, 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, ®node, Z);
1111 regalloc(&t2, ®node, 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, ®node, Z);
1222 mov(l, &vl, 0);
1223 regalloc(&vr, ®node, 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