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(typesuv[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) {
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(r->op == OCONST)
150 if(!typefd[n->type->etype]) {
151 cgen(l, nn);
152 if(r->vconst == 0)
153 if(o != OAND)
154 break;
155 if(nn != Z)
156 gopcode(o, r, Z, nn);
157 break;
158 }
159
160 case OMUL:
161 case OLMUL:
162 case OLDIV:
163 case OLMOD:
164 case ODIV:
165 case OMOD:
166 if(nn == Z) {
167 nullwarn(l, r);
168 break;
169 }
170 if(o == OMUL || o == OLMUL) {
171 if(mulcon(n, nn))
172 break;
173 if(debug['M'])
174 print("%L multiply\n", n->lineno);
175 }
176 if(l->complex >= r->complex) {
177 regalloc(&nod, l, nn);
178 cgen(l, &nod);
179 regalloc(&nod1, r, Z);
180 cgen(r, &nod1);
181 gopcode(o, &nod1, Z, &nod);
182 } else {
183 regalloc(&nod, r, nn);
184 cgen(r, &nod);
185 regalloc(&nod1, l, Z);
186 cgen(l, &nod1);
187 gopcode(o, &nod, &nod1, &nod);
188 }
189 gopcode(OAS, &nod, Z, nn);
190 regfree(&nod);
191 regfree(&nod1);
192 break;
193
194 case OASLSHR:
195 case OASASHL:
196 case OASASHR:
197 case OASAND:
198 case OASADD:
199 case OASSUB:
200 case OASXOR:
201 case OASOR:
202 if(l->op == OBIT)
203 goto asbitop;
204 if(r->op == OCONST)
205 if(!typefd[n->type->etype]) {
206 if(l->addable < INDEXED)
207 reglcgen(&nod2, l, Z);
208 else
209 nod2 = *l;
210 regalloc(&nod, r, nn);
211 gopcode(OAS, &nod2, Z, &nod);
212 gopcode(o, r, Z, &nod);
213 gopcode(OAS, &nod, Z, &nod2);
214
215 regfree(&nod);
216 if(l->addable < INDEXED)
217 regfree(&nod2);
218 break;
219 }
220
221 case OASLMUL:
222 case OASLDIV:
223 case OASLMOD:
224 case OASMUL:
225 case OASDIV:
226 case OASMOD:
227 if(l->op == OBIT)
228 goto asbitop;
229 if(l->complex >= r->complex) {
230 if(l->addable < INDEXED)
231 reglcgen(&nod2, l, Z);
232 else
233 nod2 = *l;
234 regalloc(&nod, n, nn);
235 cgen(r, &nod);
236 } else {
237 regalloc(&nod, n, nn);
238 cgen(r, &nod);
239 if(l->addable < INDEXED)
240 reglcgen(&nod2, l, Z);
241 else
242 nod2 = *l;
243 }
244 regalloc(&nod1, n, Z);
245 gopcode(OAS, &nod2, Z, &nod1);
246 gopcode(o, &nod, &nod1, &nod);
247 gopcode(OAS, &nod, Z, &nod2);
248 regfree(&nod);
249 regfree(&nod1);
250 if(l->addable < INDEXED)
251 regfree(&nod2);
252 break;
253
254 asbitop:
255 regalloc(&nod4, n, nn);
256 regalloc(&nod3, r, Z);
257 if(l->complex >= r->complex) {
258 bitload(l, &nod, &nod1, &nod2, &nod4);
259 cgen(r, &nod3);
260 } else {
261 cgen(r, &nod3);
262 bitload(l, &nod, &nod1, &nod2, &nod4);
263 }
264 gmove(&nod, &nod4);
265 gopcode(n->op, &nod3, Z, &nod4);
266 regfree(&nod3);
267 gmove(&nod4, &nod);
268 regfree(&nod4);
269 bitstore(l, &nod, &nod1, &nod2, nn);
270 break;
271
272 case OADDR:
273 if(nn == Z) {
274 nullwarn(l, Z);
275 break;
276 }
277 lcgen(l, nn);
278 break;
279
280 case OFUNC:
281 if(l->complex >= FNX) {
282 if(l->op != OIND)
283 diag(n, "bad function call");
284
285 regret(&nod, l->left);
286 cgen(l->left, &nod);
287 regsalloc(&nod1, l->left);
288 gopcode(OAS, &nod, Z, &nod1);
289 regfree(&nod);
290
291 nod = *n;
292 nod.left = &nod2;
293 nod2 = *l;
294 nod2.left = &nod1;
295 nod2.complex = 1;
296 cgen(&nod, nn);
297
298 return;
299 }
300 o = reg[REGARG];
301 gargs(r, &nod, &nod1);
302 if(l->addable < INDEXED) {
303 reglcgen(&nod, l, Z);
304 gopcode(OFUNC, Z, Z, &nod);
305 regfree(&nod);
306 } else
307 gopcode(OFUNC, Z, Z, l);
308 if(REGARG)
309 if(o != reg[REGARG])
310 reg[REGARG]--;
311 if(nn != Z) {
312 regret(&nod, n);
313 gopcode(OAS, &nod, Z, nn);
314 regfree(&nod);
315 }
316 break;
317
318 case OIND:
319 if(nn == Z) {
320 cgen(l, nn);
321 break;
322 }
323 regialloc(&nod, n, nn);
324 r = l;
325 while(r->op == OADD)
326 r = r->right;
327 if(sconst(r)) {
328 v = r->vconst;
329 r->vconst = 0;
330 cgen(l, &nod);
331 nod.xoffset += v;
332 r->vconst = v;
333 } else
334 cgen(l, &nod);
335 regind(&nod, n);
336 gopcode(OAS, &nod, Z, nn);
337 regfree(&nod);
338 break;
339
340 case OEQ:
341 case ONE:
342 case OLE:
343 case OLT:
344 case OGE:
345 case OGT:
346 case OLO:
347 case OLS:
348 case OHI:
349 case OHS:
350 if(nn == Z) {
351 nullwarn(l, r);
352 break;
353 }
354 boolgen(n, 1, nn);
355 break;
356
357 case OANDAND:
358 case OOROR:
359 boolgen(n, 1, nn);
360 if(nn == Z)
361 patch(p, pc);
362 break;
363
364 case ONOT:
365 if(nn == Z) {
366 nullwarn(l, Z);
367 break;
368 }
369 boolgen(n, 1, nn);
370 break;
371
372 case OCOMMA:
373 cgen(l, Z);
374 cgen(r, nn);
375 break;
376
377 case OCAST:
378 if(nn == Z) {
379 nullwarn(l, Z);
380 break;
381 }
382 /*
383 * convert from types l->n->nn
384 */
385 if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
386 /* both null, gen l->nn */
387 cgen(l, nn);
388 break;
389 }
390 regalloc(&nod, l, nn);
391 cgen(l, &nod);
392 regalloc(&nod1, n, &nod);
393 gopcode(OAS, &nod, Z, &nod1);
394 gopcode(OAS, &nod1, Z, nn);
395 regfree(&nod1);
396 regfree(&nod);
397 break;
398
399 case ODOT:
400 sugen(l, nodrat, l->type->width);
401 if(nn != Z) {
402 warn(n, "non-interruptable temporary");
403 nod = *nodrat;
404 if(!r || r->op != OCONST) {
405 diag(n, "DOT and no offset");
406 break;
407 }
408 nod.xoffset += (long)r->vconst;
409 nod.type = n->type;
410 cgen(&nod, nn);
411 }
412 break;
413
414 case OCOND:
415 bcgen(l, 1);
416 p1 = p;
417 cgen(r->left, nn);
418 gbranch(OGOTO);
419 patch(p1, pc);
420 p1 = p;
421 cgen(r->right, nn);
422 patch(p1, pc);
423 break;
424
425 case OPOSTINC:
426 case OPOSTDEC:
427 v = 1;
428 if(l->type->etype == TIND)
429 v = l->type->link->width;
430 if(o == OPOSTDEC)
431 v = -v;
432 if(l->op == OBIT)
433 goto bitinc;
434 if(nn == Z)
435 goto pre;
436
437 if(l->addable < INDEXED)
438 reglcgen(&nod2, l, Z);
439 else
440 nod2 = *l;
441
442 regalloc(&nod, l, nn);
443 gopcode(OAS, &nod2, Z, &nod);
444 regalloc(&nod1, l, Z);
445 if(typefd[l->type->etype]) {
446 regalloc(&nod3, l, Z);
447 if(v < 0) {
448 gopcode(OAS, nodfconst(-v), Z, &nod3);
449 gopcode(OSUB, &nod3, &nod, &nod1);
450 } else {
451 gopcode(OAS, nodfconst(v), Z, &nod3);
452 gopcode(OADD, &nod3, &nod, &nod1);
453 }
454 regfree(&nod3);
455 } else
456 gopcode(OADD, nodconst(v), &nod, &nod1);
457 gopcode(OAS, &nod1, Z, &nod2);
458
459 regfree(&nod);
460 regfree(&nod1);
461 if(l->addable < INDEXED)
462 regfree(&nod2);
463 break;
464
465 case OPREINC:
466 case OPREDEC:
467 v = 1;
468 if(l->type->etype == TIND)
469 v = l->type->link->width;
470 if(o == OPREDEC)
471 v = -v;
472 if(l->op == OBIT)
473 goto bitinc;
474
475 pre:
476 if(l->addable < INDEXED)
477 reglcgen(&nod2, l, Z);
478 else
479 nod2 = *l;
480
481 regalloc(&nod, l, nn);
482 gopcode(OAS, &nod2, Z, &nod);
483 if(typefd[l->type->etype]) {
484 regalloc(&nod3, l, Z);
485 if(v < 0) {
486 gopcode(OAS, nodfconst(-v), Z, &nod3);
487 gopcode(OSUB, &nod3, Z, &nod);
488 } else {
489 gopcode(OAS, nodfconst(v), Z, &nod3);
490 gopcode(OADD, &nod3, Z, &nod);
491 }
492 regfree(&nod3);
493 } else
494 gopcode(OADD, nodconst(v), Z, &nod);
495 gopcode(OAS, &nod, Z, &nod2);
496 if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */
497 gins(ANOP, l, Z);
498
499 regfree(&nod);
500 if(l->addable < INDEXED)
501 regfree(&nod2);
502 break;
503
504 bitinc:
505 if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
506 bitload(l, &nod, &nod1, &nod2, Z);
507 gopcode(OAS, &nod, Z, nn);
508 gopcode(OADD, nodconst(v), Z, &nod);
509 bitstore(l, &nod, &nod1, &nod2, Z);
510 break;
511 }
512 bitload(l, &nod, &nod1, &nod2, nn);
513 gopcode(OADD, nodconst(v), Z, &nod);
514 bitstore(l, &nod, &nod1, &nod2, nn);
515 break;
516 }
517 cursafe = curs;
518 }
519
520 void
reglcgen(Node * t,Node * n,Node * nn)521 reglcgen(Node *t, Node *n, Node *nn)
522 {
523 Node *r;
524 long v;
525
526 regialloc(t, n, nn);
527 if(n->op == OIND) {
528 r = n->left;
529 while(r->op == OADD)
530 r = r->right;
531 if(sconst(r)) {
532 v = r->vconst;
533 r->vconst = 0;
534 lcgen(n, t);
535 t->xoffset += v;
536 r->vconst = v;
537 regind(t, n);
538 return;
539 }
540 }
541 lcgen(n, t);
542 regind(t, n);
543 }
544
545 void
lcgen(Node * n,Node * nn)546 lcgen(Node *n, Node *nn)
547 {
548 Prog *p1;
549 Node nod;
550
551 if(debug['g']) {
552 prtree(nn, "lcgen lhs");
553 prtree(n, "lcgen");
554 }
555 if(n == Z || n->type == T)
556 return;
557 if(nn == Z) {
558 nn = &nod;
559 regalloc(&nod, n, Z);
560 }
561 switch(n->op) {
562 default:
563 if(n->addable < INDEXED) {
564 diag(n, "unknown op in lcgen: %O", n->op);
565 break;
566 }
567 nod = *n;
568 nod.op = OADDR;
569 nod.left = n;
570 nod.right = Z;
571 nod.type = types[TIND];
572 gopcode(OAS, &nod, Z, nn);
573 break;
574
575 case OCOMMA:
576 cgen(n->left, n->left);
577 lcgen(n->right, nn);
578 break;
579
580 case OIND:
581 cgen(n->left, nn);
582 break;
583
584 case OCOND:
585 bcgen(n->left, 1);
586 p1 = p;
587 lcgen(n->right->left, nn);
588 gbranch(OGOTO);
589 patch(p1, pc);
590 p1 = p;
591 lcgen(n->right->right, nn);
592 patch(p1, pc);
593 break;
594 }
595 }
596
597 void
bcgen(Node * n,int true)598 bcgen(Node *n, int true)
599 {
600
601 if(n->type == T)
602 gbranch(OGOTO);
603 else
604 boolgen(n, true, Z);
605 }
606
607 void
boolgen(Node * n,int true,Node * nn)608 boolgen(Node *n, int true, Node *nn)
609 {
610 int o;
611 Prog *p1, *p2;
612 Node *l, *r, nod, nod1;
613 long curs;
614
615 if(debug['g']) {
616 prtree(nn, "boolgen lhs");
617 prtree(n, "boolgen");
618 }
619 curs = cursafe;
620 l = n->left;
621 r = n->right;
622 switch(n->op) {
623
624 default:
625 if(n->op == OCONST) {
626 o = vconst(n);
627 if(!true)
628 o = !o;
629 gbranch(OGOTO);
630 if(o) {
631 p1 = p;
632 gbranch(OGOTO);
633 patch(p1, pc);
634 }
635 goto com;
636 }
637 regalloc(&nod, n, nn);
638 cgen(n, &nod);
639 o = ONE;
640 if(true)
641 o = comrel[relindex(o)];
642 if(typefd[n->type->etype]) {
643 nodreg(&nod1, n, NREG+FREGZERO);
644 gopcode(o, &nod, Z, &nod1);
645 } else
646 gopcode(o, &nod, Z, nodconst(0));
647 regfree(&nod);
648 goto com;
649
650 case OCOMMA:
651 cgen(l, Z);
652 boolgen(r, true, nn);
653 break;
654
655 case ONOT:
656 boolgen(l, !true, nn);
657 break;
658
659 case OCOND:
660 bcgen(l, 1);
661 p1 = p;
662 bcgen(r->left, true);
663 p2 = p;
664 gbranch(OGOTO);
665 patch(p1, pc);
666 p1 = p;
667 bcgen(r->right, !true);
668 patch(p2, pc);
669 p2 = p;
670 gbranch(OGOTO);
671 patch(p1, pc);
672 patch(p2, pc);
673 goto com;
674
675 case OANDAND:
676 if(!true)
677 goto caseor;
678
679 caseand:
680 bcgen(l, true);
681 p1 = p;
682 bcgen(r, !true);
683 p2 = p;
684 patch(p1, pc);
685 gbranch(OGOTO);
686 patch(p2, pc);
687 goto com;
688
689 case OOROR:
690 if(!true)
691 goto caseand;
692
693 caseor:
694 bcgen(l, !true);
695 p1 = p;
696 bcgen(r, !true);
697 p2 = p;
698 gbranch(OGOTO);
699 patch(p1, pc);
700 patch(p2, pc);
701 goto com;
702
703 case OEQ:
704 case ONE:
705 case OLE:
706 case OLT:
707 case OGE:
708 case OGT:
709 case OHI:
710 case OHS:
711 case OLO:
712 case OLS:
713 o = n->op;
714 if(true)
715 o = comrel[relindex(o)];
716 if(l->complex >= FNX && r->complex >= FNX) {
717 regret(&nod, r);
718 cgen(r, &nod);
719 regsalloc(&nod1, r);
720 gopcode(OAS, &nod, Z, &nod1);
721 regfree(&nod);
722 nod = *n;
723 nod.right = &nod1;
724 boolgen(&nod, true, nn);
725 break;
726 }
727 if(sconst(r)) {
728 regalloc(&nod, l, nn);
729 cgen(l, &nod);
730 gopcode(o, &nod, Z, r);
731 regfree(&nod);
732 goto com;
733 }
734 if(l->complex >= r->complex) {
735 regalloc(&nod1, l, nn);
736 cgen(l, &nod1);
737 regalloc(&nod, r, Z);
738 cgen(r, &nod);
739 } else {
740 regalloc(&nod, r, nn);
741 cgen(r, &nod);
742 regalloc(&nod1, l, Z);
743 cgen(l, &nod1);
744 }
745 gopcode(o, &nod1, Z, &nod);
746 regfree(&nod);
747 regfree(&nod1);
748
749 com:
750 if(nn != Z) {
751 p1 = p;
752 gopcode(OAS, nodconst(1L), Z, nn);
753 gbranch(OGOTO);
754 p2 = p;
755 patch(p1, pc);
756 gopcode(OAS, nodconst(0L), Z, nn);
757 patch(p2, pc);
758 }
759 break;
760 }
761 cursafe = curs;
762 }
763
764 void
sugen(Node * n,Node * nn,long w)765 sugen(Node *n, Node *nn, long w)
766 {
767 Prog *p1;
768 Node nod0, nod1, nod2, nod3, nod4, *l, *r;
769 Type *t;
770 long pc1;
771 int i, m, c;
772
773 if(n == Z || n->type == T)
774 return;
775 if(debug['g']) {
776 prtree(nn, "sugen lhs");
777 prtree(n, "sugen");
778 }
779 if(nn == nodrat)
780 if(w > nrathole)
781 nrathole = w;
782 switch(n->op) {
783 case OIND:
784 if(nn == Z) {
785 nullwarn(n->left, Z);
786 break;
787 }
788
789 default:
790 goto copy;
791
792 case OCONST:
793 if(n->type && typev[n->type->etype]) {
794 if(nn == Z) {
795 nullwarn(n->left, Z);
796 break;
797 }
798
799 t = nn->type;
800 nn->type = types[TLONG];
801 reglcgen(&nod1, nn, Z);
802 nn->type = t;
803
804 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
805 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
806 else
807 gopcode(OAS, nod32const(n->vconst), Z, &nod1);
808 nod1.xoffset += SZ_LONG;
809 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
810 gopcode(OAS, nod32const(n->vconst), Z, &nod1);
811 else
812 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
813
814 regfree(&nod1);
815 break;
816 }
817 goto copy;
818
819 case ODOT:
820 l = n->left;
821 sugen(l, nodrat, l->type->width);
822 if(nn != Z) {
823 warn(n, "non-interruptable temporary");
824 nod1 = *nodrat;
825 r = n->right;
826 if(!r || r->op != OCONST) {
827 diag(n, "DOT and no offset");
828 break;
829 }
830 nod1.xoffset += (long)r->vconst;
831 nod1.type = n->type;
832 sugen(&nod1, nn, w);
833 }
834 break;
835
836 case OSTRUCT:
837 /*
838 * rewrite so lhs has no fn call
839 */
840 if(nn != Z && nn->complex >= FNX) {
841 nod1 = *n;
842 nod1.type = typ(TIND, n->type);
843 regret(&nod2, &nod1);
844 lcgen(nn, &nod2);
845 regsalloc(&nod0, &nod1);
846 gopcode(OAS, &nod2, Z, &nod0);
847 regfree(&nod2);
848
849 nod1 = *n;
850 nod1.op = OIND;
851 nod1.left = &nod0;
852 nod1.right = Z;
853 nod1.complex = 1;
854
855 sugen(n, &nod1, w);
856 return;
857 }
858
859 r = n->left;
860 for(t = n->type->link; t != T; t = t->down) {
861 l = r;
862 if(r->op == OLIST) {
863 l = r->left;
864 r = r->right;
865 }
866 if(nn == Z) {
867 cgen(l, nn);
868 continue;
869 }
870 /*
871 * hand craft *(&nn + o) = l
872 */
873 nod0 = znode;
874 nod0.op = OAS;
875 nod0.type = t;
876 nod0.left = &nod1;
877 nod0.right = l;
878
879 nod1 = znode;
880 nod1.op = OIND;
881 nod1.type = t;
882 nod1.left = &nod2;
883
884 nod2 = znode;
885 nod2.op = OADD;
886 nod2.type = typ(TIND, t);
887 nod2.left = &nod3;
888 nod2.right = &nod4;
889
890 nod3 = znode;
891 nod3.op = OADDR;
892 nod3.type = nod2.type;
893 nod3.left = nn;
894
895 nod4 = znode;
896 nod4.op = OCONST;
897 nod4.type = nod2.type;
898 nod4.vconst = t->offset;
899
900 ccom(&nod0);
901 acom(&nod0);
902 xcom(&nod0);
903 nod0.addable = 0;
904
905 cgen(&nod0, Z);
906 }
907 break;
908
909 case OAS:
910 if(nn == Z) {
911 if(n->addable < INDEXED)
912 sugen(n->right, n->left, w);
913 break;
914 }
915 /* BOTCH -- functions can clobber rathole */
916 sugen(n->right, nodrat, w);
917 warn(n, "non-interruptable temporary");
918 sugen(nodrat, n->left, w);
919 sugen(nodrat, nn, w);
920 break;
921
922 case OFUNC:
923 if(nn == Z) {
924 sugen(n, nodrat, w);
925 break;
926 }
927 if(nn->op != OIND) {
928 nn = new1(OADDR, nn, Z);
929 nn->type = types[TIND];
930 nn->addable = 0;
931 } else
932 nn = nn->left;
933 n = new(OFUNC, n->left, new(OLIST, nn, n->right));
934 n->type = types[TVOID];
935 n->left->type = types[TVOID];
936 cgen(n, Z);
937 break;
938
939 case OCOND:
940 bcgen(n->left, 1);
941 p1 = p;
942 sugen(n->right->left, nn, w);
943 gbranch(OGOTO);
944 patch(p1, pc);
945 p1 = p;
946 sugen(n->right->right, nn, w);
947 patch(p1, pc);
948 break;
949
950 case OCOMMA:
951 cgen(n->left, Z);
952 sugen(n->right, nn, w);
953 break;
954 }
955 return;
956
957 copy:
958 if(nn == Z)
959 return;
960 if(n->complex >= FNX && nn->complex >= FNX) {
961 t = nn->type;
962 nn->type = types[TLONG];
963 regialloc(&nod1, nn, Z);
964 lcgen(nn, &nod1);
965 regsalloc(&nod2, nn);
966 nn->type = t;
967
968 gopcode(OAS, &nod1, Z, &nod2);
969 regfree(&nod1);
970
971 nod2.type = typ(TIND, t);
972
973 nod1 = nod2;
974 nod1.op = OIND;
975 nod1.left = &nod2;
976 nod1.right = Z;
977 nod1.complex = 1;
978 nod1.type = t;
979
980 sugen(n, &nod1, w);
981 return;
982 }
983
984 if(n->complex > nn->complex) {
985 t = n->type;
986 n->type = types[TLONG];
987 reglcgen(&nod1, n, Z);
988 n->type = t;
989
990 t = nn->type;
991 nn->type = types[TLONG];
992 reglcgen(&nod2, nn, Z);
993 nn->type = t;
994 } else {
995 t = nn->type;
996 nn->type = types[TLONG];
997 reglcgen(&nod2, nn, Z);
998 nn->type = t;
999
1000 t = n->type;
1001 n->type = types[TLONG];
1002 reglcgen(&nod1, n, Z);
1003 n->type = t;
1004 }
1005
1006 w /= SZ_LONG;
1007 if(w <= 5) {
1008 layout(&nod1, &nod2, w, 0, Z);
1009 goto out;
1010 }
1011
1012 /*
1013 * minimize space for unrolling loop
1014 * 3,4,5 times. (6 or more is never minimum)
1015 * if small structure, try 2 also.
1016 */
1017 c = 0; /* set */
1018 m = 100;
1019 i = 3;
1020 if(w <= 15)
1021 i = 2;
1022 for(; i<=5; i++)
1023 if(i + w%i <= m) {
1024 c = i;
1025 m = c + w%c;
1026 }
1027
1028 regalloc(&nod3, ®node, Z);
1029 layout(&nod1, &nod2, w%c, w/c, &nod3);
1030
1031 pc1 = pc;
1032 layout(&nod1, &nod2, c, 0, Z);
1033
1034 gopcode(OSUB, nodconst(1L), Z, &nod3);
1035 nod1.op = OREGISTER;
1036 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
1037 nod2.op = OREGISTER;
1038 gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
1039
1040 gopcode(OGT, &nod3, Z, nodconst(0));
1041 patch(p, pc1);
1042
1043 regfree(&nod3);
1044 out:
1045 regfree(&nod1);
1046 regfree(&nod2);
1047 }
1048
1049 void
layout(Node * f,Node * t,int c,int cv,Node * cn)1050 layout(Node *f, Node *t, int c, int cv, Node *cn)
1051 {
1052 Node t1, t2;
1053
1054 while(c > 3) {
1055 layout(f, t, 2, 0, Z);
1056 c -= 2;
1057 }
1058
1059 regalloc(&t1, ®node, Z);
1060 regalloc(&t2, ®node, Z);
1061 if(c > 0) {
1062 gopcode(OAS, f, Z, &t1);
1063 f->xoffset += SZ_LONG;
1064 }
1065 if(cn != Z)
1066 gopcode(OAS, nodconst(cv), Z, cn);
1067 if(c > 1) {
1068 gopcode(OAS, f, Z, &t2);
1069 f->xoffset += SZ_LONG;
1070 }
1071 if(c > 0) {
1072 gopcode(OAS, &t1, Z, t);
1073 t->xoffset += SZ_LONG;
1074 }
1075 if(c > 2) {
1076 gopcode(OAS, f, Z, &t1);
1077 f->xoffset += SZ_LONG;
1078 }
1079 if(c > 1) {
1080 gopcode(OAS, &t2, Z, t);
1081 t->xoffset += SZ_LONG;
1082 }
1083 if(c > 2) {
1084 gopcode(OAS, &t1, Z, t);
1085 t->xoffset += SZ_LONG;
1086 }
1087 regfree(&t1);
1088 regfree(&t2);
1089 }
1090