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