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