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