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