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