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