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