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