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