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