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