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