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