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