]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/1c/cgen.c
merge
[plan9front.git] / sys / src / cmd / 1c / cgen.c
1 #include "gc.h"
2
3 void
4 cgen(Node *n, int result, Node *nn)
5 {
6         Node *l, *r, nod;
7         int lg, rg, xg, yg, g, o;
8         long v;
9         Prog *p1;
10
11         if(n == Z || n->type == T)
12                 return;
13         if(typesuv[n->type->etype]) {
14                 sugen(n, result, nn, n->type->width);
15                 return;
16         }
17         if(debug['g']) {
18                 if(result == D_TREE)
19                         prtree(nn, "result");
20                 else
21                         print("result = %R\n", result);
22                 prtree(n, "cgen");
23         }
24         l = n->left;
25         r = n->right;
26         o = n->op;
27         if(n->addable >= INDEXED) {
28                 if(result == D_NONE) {
29                         if(nn == Z)
30                                 switch(o) {
31                                 default:
32                                         nullwarn(Z, Z);
33                                         break;
34                                 case OINDEX:
35                                         nullwarn(l, r);
36                                         break;
37                                 }
38                         return;
39                 }
40                 gmove(n->type, nn->type, D_TREE, n, result, nn);
41                 return;
42         }
43
44         v = 0; /* set */
45         switch(o) {
46         default:
47                 diag(n, "unknown op in cgen: %O", o);
48                 break;
49
50         case OAS:
51                 if(l->op == OBIT)
52                         goto bitas;
53                 /*
54                  * recursive use of result
55                  */
56                 if(result == D_NONE)
57                 if(l->addable > INDEXED)
58                 if(l->complex < FNX) {
59                         cgen(r, D_TREE, l);
60                         break;
61                 }
62
63                 /*
64                  * function calls on both sides
65                  */
66                 if(l->complex >= FNX && r->complex >= FNX) {
67                         cgen(r, D_TOS, r);
68                         v = argoff;
69                         lg = regaddr(result);
70                         lcgen(l, lg, Z);
71                         lg |= I_INDIR;
72                         adjsp(v - argoff);
73                         gmove(r->type, l->type, D_TOS, r, lg, l);
74                         if(result != D_NONE)
75                                 gmove(l->type, nn->type, lg, l, result, nn);
76                         regfree(lg);
77                         break;
78                 }
79
80                 rg = D_TREE;
81                 lg = D_TREE;
82                 if(r->complex >= l->complex) {
83                         /*
84                          * right side before left
85                          */
86                         if(result != D_NONE) {
87                                 rg = regalloc(n->type, result);
88                                 cgen(r, rg, n);
89                         } else
90                         if(r->complex >= FNX || r->addable < INDEXED) {
91                                 rg = regalloc(r->type, result);
92                                 cgen(r, rg, r);
93                         }
94                         if(l->addable < INDEXED) {
95                                 lg = regaddr(lg);
96                                 lcgen(l, lg, Z);
97                                 lg |= I_INDIR;
98                         }
99                 } else {
100                         /*
101                          * left before right
102                          */
103                         if(l->complex >= FNX || l->addable < INDEXED) {
104                                 lg = regaddr(lg);
105                                 lcgen(l, lg, Z);
106                                 lg |= I_INDIR;
107                         }
108                         if(result != D_NONE) {
109                                 rg = regalloc(n->type, result);
110                                 cgen(r, rg, n);
111                         } else
112                         if(r->addable < INDEXED) {
113                                 rg = regalloc(r->type, result);
114                                 cgen(r, rg, r);
115                         }
116                 }
117                 if(result != D_NONE) {
118                         gmove(n->type, l->type, rg, r, lg, l);
119                         gmove(n->type, nn->type, rg, r, result, nn);
120                 } else
121                         gmove(r->type, l->type, rg, r, lg, l);
122                 regfree(lg);
123                 regfree(rg);
124                 break;
125
126         bitas:
127                 n = l->left;
128                 rg = regalloc(tfield, result);
129                 if(l->complex >= r->complex) {
130                         lg = regaddr(D_NONE);
131                         lcgen(n, lg, Z);
132                         lg |= I_INDIR;
133                         cgen(r, rg, r);
134                 } else {
135                         cgen(r, rg, r);
136                         lg = regaddr(D_NONE);
137                         lcgen(n, lg, Z);
138                         lg |= I_INDIR;
139                 }
140                 g = regalloc(n->type, D_NONE);
141                 gmove(l->type, l->type, lg, l, g, l);
142                 bitstore(l, rg, lg, g, result, nn);
143                 break;
144
145         case OBIT:
146                 if(result == D_NONE) {
147                         nullwarn(l, Z);
148                         break;
149                 }
150                 g = bitload(n, D_NONE, D_NONE, result, nn);
151                 gopcode(OAS, nn->type, g, n, result, nn);
152                 regfree(g);
153                 break;
154
155         case ODOT:
156                 sugen(l, D_TREE, nodrat, l->type->width);
157                 if(result != D_NONE) {
158                         warn(n, "non-interruptable temporary");
159                         nod = *nodrat;
160                         if(!r || r->op != OCONST) {
161                                 diag(n, "DOT and no offset");
162                                 break;
163                         }
164                         nod.xoffset += r->vconst;
165                         nod.type = n->type;
166                         cgen(&nod, result, nn);
167                 }
168                 break;
169
170         case OASLDIV:
171         case OASLMOD:
172         case OASDIV:
173         case OASMOD:
174                 if(l->op == OBIT)
175                         goto asbitop;
176                 if(typefd[n->type->etype])
177                         goto asbinop;
178                 rg = D_TREE;
179                 if(l->complex >= FNX || r->complex >= FNX) {
180                         rg = D_TOS;
181                         cgen(r, rg, r);
182                         v = argoff;
183                 } else
184                 if(r->addable < INDEXED) {
185                         rg = regalloc(n->type, D_NONE);
186                         cgen(r, rg, r);
187                 }
188                 lg = D_TREE;
189                 if(!simplv(l)) {
190                         lg = regaddr(D_NONE);
191                         lcgen(l, lg, Z);        /* destroys register optimization */
192                         lg |= I_INDIR;
193                 }
194                 g = regpair(result);
195                 gmove(l->type, n->type, lg, l, g, n);
196                 if(rg == D_TOS)
197                         adjsp(v - argoff);
198                 gopcode(o, n->type, rg, r, g, n);
199                 if(o == OASLMOD || o == OASMOD)
200                         gmove(n->type, l->type, g+1, n, lg, l);
201                 else
202                         gmove(n->type, l->type, g, n, lg, l);
203                 if(result != D_NONE)
204                 if(o == OASLMOD || o == OASMOD)
205                         gmove(n->type, nn->type, g+1, n, result, nn);
206                 else
207                         gmove(n->type, nn->type, g, n, result, nn);
208                 regfree(g);
209                 regfree(g+1);
210                 regfree(lg);
211                 regfree(rg);
212                 break;
213
214         case OASXOR:
215         case OASAND:
216         case OASOR:
217                 if(l->op == OBIT)
218                         goto asbitop;
219                 if(l->complex >= FNX ||
220                    l->addable < INDEXED ||
221                    result != D_NONE ||
222                    typefd[n->type->etype])
223                         goto asbinop;
224                 rg = D_TREE;
225                 if(r->op != OCONST) {
226                         rg = regalloc(n->type, D_NONE);
227                         cgen(r, rg, r);
228                 }
229                 gopcode(o, l->type, rg, r, D_TREE, l);
230                 regfree(rg);
231                 break;
232
233         case OASADD:
234         case OASSUB:
235                 if(l->op == OBIT ||
236                    l->complex >= FNX ||
237                    l->addable < INDEXED ||
238                    result != D_NONE ||
239                    typefd[n->type->etype])
240                         goto asbinop;
241                 v = vconst(r);
242                 if(v > 0 && v <= 8) {
243                         gopcode(o, n->type, D_TREE, r, D_TREE, l);
244                         break;
245                 }
246                 rg = regalloc(n->type, D_NONE);
247                 cgen(r, rg, r);
248                 gopcode(o, n->type, rg, r, D_TREE, l);
249                 regfree(rg);
250                 break;
251
252         case OASLSHR:
253         case OASASHR:
254         case OASASHL:
255                 if(l->op == OBIT ||
256                    l->complex >= FNX ||
257                    l->addable < INDEXED ||
258                    result != D_NONE ||
259                    typefd[n->type->etype])
260                         goto asbinop;
261                 rg = D_TREE;
262                 v = vconst(r);
263                 if(v <= 0 || v > 8) {
264                         rg = regalloc(n->type, D_NONE);
265                         cgen(r, rg, r);
266                 }
267                 lg = regalloc(n->type, D_NONE);
268                 cgen(l, lg, l);
269                 gopcode(o, n->type, rg, r, lg, l);
270                 gmove(n->type, n->type, lg, l, D_TREE, l);
271                 regfree(lg);
272                 regfree(rg);
273                 break;
274
275         case OASLMUL:
276         case OASMUL:
277         asbinop:
278                 if(l->op == OBIT)
279                         goto asbitop;
280                 rg = D_TREE;
281                 if(l->complex >= FNX || r->complex >= FNX) {
282                         rg = D_TOS;
283                         cgen(r, rg, r);
284                         v = argoff;
285                 } else
286                 if(r->addable < INDEXED) {
287                         rg = regalloc(n->type, D_NONE);
288                         cgen(r, rg, r);
289                 } else {
290                         if(o == OASLSHR || o == OASASHR || o == OASASHL) {
291                                 v = vconst(r);
292                                 if(v <= 0 || v > 8) {
293                                         rg = regalloc(n->type, D_NONE);
294                                         cgen(r, rg, r);
295                                 }
296                         }
297                 }
298                 lg = D_TREE;
299                 if(!simplv(l)) {
300                         lg = regaddr(D_NONE);
301                         lcgen(l, lg, Z);        /* destroys register optimization */
302                         lg |= I_INDIR;
303                 }
304                 g = regalloc(n->type, result);
305                 gmove(l->type, n->type, lg, l, g, n);
306                 if(rg == D_TOS)
307                         adjsp(v - argoff);
308                 if(o == OASXOR)
309                         if(rg == D_TREE) {
310                                 rg = regalloc(n->type, D_NONE);
311                                 cgen(r, rg, r);
312                         }
313                 if(o == OASXOR || o == OASLSHR || o == OASASHR || o == OASASHL)
314                         if(rg == D_TOS) {
315                                 rg = regalloc(n->type, D_NONE);
316                                 gmove(n->type, n->type, D_TOS, n, rg, n);
317                         }
318                 gopcode(o, n->type, rg, r, g, n);
319                 gmove(n->type, l->type, g, n, lg, l);
320                 if(result != D_NONE)
321                         gmove(n->type, nn->type, g, n, result, nn);
322                 regfree(g);
323                 regfree(lg);
324                 regfree(rg);
325                 break;
326
327         asbitop:
328                 rg = regaddr(D_NONE);
329                 lg = regalloc(tfield, D_NONE);
330                 if(l->complex >= r->complex) {
331                         g = bitload(l, lg, rg, result, nn);
332                         xg = regalloc(r->type, D_NONE);
333                         cgen(r, xg, nn);
334                 } else {
335                         xg = regalloc(r->type, D_NONE);
336                         cgen(r, xg, nn);
337                         g = bitload(l, lg, rg, result, nn);
338                 }
339
340                 if(!typefd[n->type->etype]) {
341                         if(o == OASLDIV || o == OASDIV) {
342                                 yg = regpair(result);
343                                 gmove(tfield, n->type, g, l, yg, n);
344                                 gopcode(o, n->type, xg, r, yg, n);
345                                 gmove(n->type, tfield, yg, n, g, l);
346                                 regfree(yg);
347                                 regfree(yg+1);
348
349                                 regfree(xg);
350                                 bitstore(l, g, rg, lg, D_NONE, nn);
351                                 break;
352                         }
353                         if(o == OASLMOD || o == OASMOD) {
354                                 yg = regpair(result);
355                                 gmove(tfield, n->type, g, l, yg, n);
356                                 gopcode(o, n->type, xg, r, yg, n);
357                                 gmove(n->type, tfield, yg+1, n, g, l);
358                                 regfree(yg);
359                                 regfree(yg+1);
360
361                                 regfree(xg);
362                                 bitstore(l, g, rg, lg, D_NONE, nn);
363                                 break;
364                         }
365                 }
366
367                 yg = regalloc(n->type, result);
368                 gmove(tfield, n->type, g, l, yg, n);
369                 gopcode(o, n->type, xg, r, yg, n);
370                 gmove(n->type, tfield, yg, n, g, l);
371                 regfree(yg);
372
373                 regfree(xg);
374                 bitstore(l, g, rg, lg, D_NONE, nn);
375                 break;
376
377         case OCAST:
378                 if(result == D_NONE) {
379                         cgen(l, D_NONE, Z);
380                         break;
381                 }
382                 lg = result;
383                 if(l->complex >= FNX)
384                         lg = regret(l->type);
385                 lg = eval(l, lg);
386                 if(nocast(l->type, n->type)) {
387                         gmove(n->type, nn->type, lg, l, result, nn);
388                         regfree(lg);
389                         break;
390                 }
391                 if(nocast(n->type, nn->type)) {
392                         gmove(l->type, n->type, lg, l, result, nn);
393                         regfree(lg);
394                         break;
395                 }
396                 rg = regalloc(n->type, result);
397                 gmove(l->type, n->type, lg, l, rg, n);
398                 gmove(n->type, nn->type, rg, n, result, nn);
399                 regfree(rg);
400                 regfree(lg);
401                 break;
402
403         case OCOND:
404                 doinc(l, PRE);
405                 boolgen(l, 1, D_NONE, Z, l);
406                 p1 = p;
407
408                 inargs++;
409                 doinc(r->left, PRE);
410                 cgen(r->left, result, nn);
411                 doinc(r->left, POST);
412                 gbranch(OGOTO);
413                 patch(p1, pc);
414                 p1 = p;
415
416                 doinc(r->right, PRE);
417                 cgen(r->right, result, nn);
418                 doinc(r->right, POST);
419                 patch(p1, pc);
420                 inargs--;
421                 break;
422
423         case OIND:
424                 if(result == D_NONE) {
425                         nullwarn(l, Z);
426                         break;
427                 }
428                 lg = nodalloc(types[TIND], result, &nod);
429                 nod.lineno = n->lineno;
430                 if(l->op == OADD) {
431                         if(l->left->op == OCONST) {
432                                 nod.xoffset += l->left->vconst;
433                                 l = l->right;
434                         } else
435                         if(l->right->op == OCONST) {
436                                 nod.xoffset += l->right->vconst;
437                                 l = l->left;
438                         }
439                 }
440                 cgen(l, lg, l);
441                 gmove(n->type, nn->type, D_TREE, &nod, result, nn);
442                 regfree(lg);
443                 break;
444
445         case OFUNC:
446                 v = argoff;
447                 inargs++;
448                 gargs(r);
449                 lg = D_TREE;
450                 if(l->addable < INDEXED) {
451                         lg = regaddr(result);
452                         lcgen(l, lg, Z);
453                         lg |= I_INDIR;
454                 }
455                 inargs--;
456                 doinc(r, POST);
457                 doinc(l, POST);
458                 gopcode(OFUNC, types[TCHAR], D_NONE, Z, lg, l);
459                 regfree(lg);
460                 if(inargs)
461                         adjsp(v - argoff);
462                 if(result != D_NONE) {
463                         lg = regret(n->type);
464                         gmove(n->type, nn->type, lg, n, result, nn);
465                 }
466                 break;
467
468         case OLDIV:
469         case OLMOD:
470         case ODIV:
471         case OMOD:
472                 if(result == D_NONE) {
473                         nullwarn(l, r);
474                         break;
475                 }
476                 if(typefd[n->type->etype])
477                         goto binop;
478                 if(r->addable >= INDEXED && r->complex < FNX) {
479                         lg = regpair(result);
480                         cgen(l, lg, l);
481                         rg = D_TREE;
482                 } else {
483                         cgen(r, D_TOS, r);
484                         v = argoff;
485                         lg = regpair(result);
486                         cgen(l, lg, l);
487                         adjsp(v - argoff);
488                         rg = D_TOS;
489                 }
490                 gopcode(o, n->type, rg, r, lg, l);
491                 if(o == OMOD || o == OLMOD)
492                         gmove(l->type, nn->type, lg+1, l, result, nn);
493                 else
494                         gmove(l->type, nn->type, lg, l, result, nn);
495                 regfree(lg);
496                 regfree(lg+1);
497                 break;
498
499         case OMUL:
500         case OLMUL:
501                 if(l->op == OCONST)
502                         if(mulcon(r, l, result, nn))
503                                 break;
504                 if(r->op == OCONST)
505                         if(mulcon(l, r, result, nn))
506                                 break;
507                 if(debug['M'])
508                         print("%L multiply\n", n->lineno);
509                 goto binop;
510
511         case OAND:
512                 if(r->op == OCONST)
513                 if(typeil[n->type->etype])
514                 if(l->op == OCAST) {
515                         if(typec[l->left->type->etype])
516                         if(!(r->vconst & ~0xff)) {
517                                 l = l->left;
518                                 goto binop;
519                         }
520                         if(typeh[l->left->type->etype])
521                         if(!(r->vconst & ~0xffff)) {
522                                 l = l->left;
523                                 goto binop;
524                         }
525                 }
526                 goto binop;
527
528         case OADD:
529                 if(result == D_TOS)
530                 if(r->addable >= INDEXED)
531                 if(l->op == OCONST)
532                 if(typeil[l->type->etype]) {
533                         v = l->vconst;
534                         if(v > -32768 && v < 32768) {
535                                 rg = regaddr(D_NONE);
536                                 gmove(r->type, r->type, D_TREE, r, rg, r);
537                                 gopcode(OADDR, types[TSHORT], D_NONE, Z, rg, r);
538                                 p->to.offset = v;
539                                 p->to.type |= I_INDIR;
540                                 regfree(rg);
541                                 break;
542                         }
543                 }
544
545         case OSUB:
546                 if(result == D_TOS)
547                 if(l->addable >= INDEXED)
548                 if(r->op == OCONST)
549                 if(typeil[r->type->etype]) {
550                         v = r->vconst;
551                         if(v > -32768 && v < 32768) {
552                                 if(n->op == OSUB)
553                                         v = -v;
554                                 lg = regaddr(D_NONE);
555                                 gmove(l->type, l->type, D_TREE, l, lg, l);
556                                 gopcode(OADDR, types[TSHORT], D_NONE, Z, lg, l);
557                                 p->to.offset = v;
558                                 p->to.type |= I_INDIR;
559                                 regfree(lg);
560                                 break;
561                         }
562                 }
563                 goto binop;
564
565         case OOR:
566         case OXOR:
567         binop:
568                 if(result == D_NONE) {
569                         nullwarn(l, r);
570                         break;
571                 }
572                 if(l->complex >= FNX && r->complex >= FNX) {
573                         cgen(r, D_TOS, r);
574                         v = argoff;
575                         lg = regalloc(l->type, result);
576                         cgen(l, lg, l);
577                         adjsp(v - argoff);
578                         if(o == OXOR) {
579                                 rg = regalloc(r->type, D_NONE);
580                                 gmove(r->type, r->type, D_TOS, r, rg, r);
581                                 gopcode(o, n->type, rg, r, lg, l);
582                                 regfree(rg);
583                         } else
584                                 gopcode(o, n->type, D_TOS, r, lg, l);
585                         gmove(n->type, nn->type, lg, l, result, nn);
586                         regfree(lg);
587                         break;
588                 }
589                 if(l->complex >= r->complex) {
590                         if(l->op == OADDR && (o == OADD || o == OSUB))
591                                 lg = regaddr(result);
592                         else
593                                 lg = regalloc(l->type, result);
594                         cgen(l, lg, l);
595                         rg = eval(r, D_NONE);
596                 } else {
597                         rg = regalloc(r->type, D_NONE);
598                         cgen(r, rg, r);
599                         lg = regalloc(l->type, result);
600                         cgen(l, lg, l);
601                 }
602                 if(o == OXOR) {
603                         if(rg == D_TREE) {
604                                 rg = regalloc(r->type, D_NONE);
605                                 cgen(r, rg, r);
606                         }
607                         if(rg == D_TOS) {
608                                 rg = regalloc(r->type, D_NONE);
609                                 gmove(r->type, r->type, D_TOS, r, rg, r);
610                         }
611                 }
612                 gopcode(o, n->type, rg, r, lg, l);
613                 gmove(n->type, nn->type, lg, l, result, nn);
614                 regfree(lg);
615                 regfree(rg);
616                 break;
617
618         case OASHL:
619                 if(r->op == OCONST)
620                         if(shlcon(l, r, result, nn))
621                                 break;
622         case OLSHR:
623         case OASHR:
624                 if(result == D_NONE) {
625                         nullwarn(l, r);
626                         break;
627                 }
628
629                 if(l->complex >= FNX && r->complex >= FNX) {
630                         cgen(r, D_TOS, r);
631                         v = argoff;
632                         lg = regalloc(l->type, result);
633                         cgen(l, lg, l);
634                         adjsp(v - argoff);
635                         rg = regalloc(r->type, D_NONE);
636                         gopcode(OAS, r->type, D_TOS, r, rg, r);
637                         gopcode(n->op, n->type, rg, r, lg, l);
638                         gmove(n->type, nn->type, lg, l, result, nn);
639                         regfree(lg);
640                         regfree(rg);
641                         break;
642                 }
643                 if(l->complex >= r->complex) {
644                         lg = regalloc(l->type, result);
645                         cgen(l, lg, l);
646                         v = vconst(r);
647                         if(v <= 0 || v > 8) {
648                                 rg = regalloc(r->type, D_NONE);
649                                 cgen(r, rg, r);
650                         } else
651                                 rg = eval(r, D_NONE);
652                 } else {
653                         rg = regalloc(r->type, D_NONE);
654                         cgen(r, rg, r);
655                         lg = regalloc(l->type, result);
656                         cgen(l, lg, l);
657                 }
658                 gopcode(o, n->type, rg, r, lg, l);
659                 gmove(n->type, nn->type, lg, l, result, nn);
660                 regfree(lg);
661                 regfree(rg);
662                 break;
663
664         case ONEG:
665         case OCOM:
666                 if(result == D_NONE) {
667                         nullwarn(l, Z);
668                         break;
669                 }
670                 lg = regalloc(l->type, result);
671                 cgen(l, lg, l);
672                 gopcode(o, l->type, D_NONE, Z, lg, l);
673                 gmove(n->type, nn->type, lg, l, result, nn);
674                 regfree(lg);
675                 break;
676
677         case OADDR:
678                 if(result == D_NONE) {
679                         nullwarn(l, Z);
680                         break;
681                 }
682                 lcgen(l, result, nn);
683                 break;
684
685         case OEQ:
686         case ONE:
687         case OLE:
688         case OLT:
689         case OGE:
690         case OGT:
691         case OLO:
692         case OLS:
693         case OHI:
694         case OHS:
695                 if(result == D_NONE) {
696                         nullwarn(l, r);
697                         break;
698                 }
699                 boolgen(n, 1, result, nn, Z);
700                 break;
701
702         case OANDAND:
703         case OOROR:
704                 boolgen(n, 1, result, nn, Z);
705                 if(result == D_NONE)
706                         patch(p, pc);
707                 break;
708
709         case OCOMMA:
710                 cgen(l, D_NONE, l);
711                 doinc(l, POST);
712                 doinc(r, PRE);
713                 cgen(r, result, nn);
714                 break;
715
716         case ONOT:
717                 if(result == D_NONE) {
718                         nullwarn(l, Z);
719                         break;
720                 }
721                 boolgen(n, 1, result, nn, Z);
722                 break;
723
724         case OPOSTINC:
725         case OPOSTDEC:
726                 v = 1;
727                 if(l->type->etype == TIND)
728                         v = l->type->link->width;
729                 if(o == OPOSTDEC)
730                         v = -v;
731                 if(l->op == OBIT)
732                         goto bitinc;
733                 if(nn == Z)
734                         goto pre;
735
736                 lg = D_TREE;
737                 if(l->addable < INDEXED) {
738                         lg = regaddr(D_NONE);
739                         lcgen(l, lg, Z);
740                         lg |= I_INDIR;
741                 }
742                 if(result != D_NONE)
743                         gmove(l->type, nn->type, lg, l, result, nn);
744                 if(typefd[n->type->etype]) {
745                         rg = regalloc(n->type, D_NONE);
746                         gmove(l->type, l->type, lg, l, rg, l);
747                         gopcode(o, n->type, D_CONST, nodconst(1), rg, l);
748                         gmove(l->type, l->type, rg, l, lg, l);
749                         regfree(rg);
750                 } else {
751                         if(v < 0)
752                                 gopcode(o, n->type, D_CONST, nodconst(-v), lg, l);
753                         else
754                                 gopcode(o, n->type, D_CONST, nodconst(v), lg, l);
755                 }
756                 regfree(lg);
757                 break;
758
759         case OPREINC:
760         case OPREDEC:
761                 v = 1;
762                 if(l->type->etype == TIND)
763                         v = l->type->link->width;
764                 if(o == OPREDEC)
765                         v = -v;
766                 if(l->op == OBIT)
767                         goto bitinc;
768
769         pre:
770                 lg = D_TREE;
771                 if(l->addable < INDEXED) {
772                         lg = regaddr(D_NONE);
773                         lcgen(l, lg, Z);
774                         lg |= I_INDIR;
775                 }
776                 if(typefd[n->type->etype]) {
777                         rg = regalloc(n->type, D_NONE);
778                         gmove(l->type, l->type, lg, l, rg, l);
779                         gopcode(o, n->type, D_CONST, nodconst(1), rg, l);
780                         gmove(l->type, l->type, rg, l, lg, l);
781                         regfree(rg);
782                 } else {
783                         if(v < 0)
784                                 gopcode(o, n->type, D_CONST, nodconst(-v), lg, l);
785                         else
786                                 gopcode(o, n->type, D_CONST, nodconst(v), lg, l);
787                 }
788                 if(result != D_NONE)
789                         gmove(l->type, nn->type, lg, l, result, nn);
790                 regfree(lg);
791                 break;
792
793         bitinc:
794                 rg = regaddr(D_NONE);
795                 lg = regalloc(tfield, D_NONE);
796                 if(result != D_NONE && (o == OPOSTINC || o == OPOSTDEC)) {
797                         g = bitload(l, lg, rg, D_NONE, nn);
798                         if(nn != Z)
799                                 gmove(l->type, nn->type, g, l, result, nn);
800                         if(v < 0)
801                                 gopcode(o, n->type, D_CONST, nodconst(-v), g, n);
802                         else
803                                 gopcode(o, n->type, D_CONST, nodconst(v), g, n);
804                         bitstore(l, g, rg, lg, D_NONE, nn);
805                         break;
806                 }
807                 g = bitload(l, lg, rg, result, nn);
808                 if(v < 0)
809                         gopcode(o, n->type, D_CONST, nodconst(-v), g, n);
810                 else
811                         gopcode(o, n->type, D_CONST, nodconst(v), g, n);
812                 if(result != D_NONE)
813                         gmove(l->type, nn->type, g, l, result, nn);
814                 bitstore(l, g, rg, lg, D_NONE, nn);
815                 break;
816         }
817 }
818
819 void
820 lcgen(Node *n, int result, Node *nn)
821 {
822         Node rn;
823         Prog *p1;
824         int lg;
825
826         if(n == Z || n->type == T)
827                 return;
828         if(debug['g']) {
829                 if(result == D_TREE)
830                         prtree(nn, "result");
831                 else
832                         print("result = %R\n", result);
833                 prtree(n, "lcgen");
834         }
835         if(nn == Z) {
836                 nn = &rn;
837                 nn->type = types[TIND];
838         }
839         switch(n->op) {
840         case OCOMMA:
841                 cgen(n->left, D_NONE, n->left);
842                 doinc(n->left, POST);
843                 doinc(n->right, PRE);
844                 lcgen(n->right, result, nn);
845                 break;
846
847         case OCOND:
848                 doinc(n->left, PRE);
849                 boolgen(n->left, 1, D_NONE, Z, n->left);
850                 p1 = p;
851
852                 inargs++;
853                 doinc(n->right->left, PRE);
854                 lcgen(n->right->left, result, nn);
855                 doinc(n->right->left, POST);
856                 gbranch(OGOTO);
857                 patch(p1, pc);
858                 p1 = p;
859
860                 doinc(n->right->right, PRE);
861                 lcgen(n->right->right, result, nn);
862                 doinc(n->right->right, POST);
863                 patch(p1, pc);
864                 inargs--;
865                 break;
866
867         case OIND:
868                 if(n->addable >= INDEXED) {
869                         if(result >= D_A0 && result < D_A0+NREG) {
870                                 gopcode(OADDR, types[TLONG], D_TREE, n, result, nn);
871                                 break;
872                         }
873                         if(result == D_TOS) {
874                                 gopcode(OADDR, types[TSHORT], D_NONE, nn, D_TREE, n);
875                                 break;
876                         }
877                 }
878                 cgen(n->left, result, nn);
879                 break;
880
881         default:
882                 if(n->addable < INDEXED) {
883                         diag(n, "unknown op in lcgen: %O", n->op);
884                         break;
885                 }
886                 if(result >= D_A0 && result < D_A0+NREG) {
887                         gopcode(OADDR, types[TLONG], D_TREE, n, result, nn);
888                         break;
889                 }
890                 if(result == D_TOS) {
891                         gopcode(OADDR, types[TSHORT], D_NONE, nn, D_TREE, n);
892                         break;
893                 }
894                 lg = regaddr(result);
895                 gopcode(OADDR, types[TLONG], D_TREE, n, lg, nn);
896                 gopcode(OAS, nn->type, lg, nn, result, nn);
897                 regfree(lg);
898                 break;
899         }
900 }
901
902 void
903 bcgen(Node *n, int true)
904 {
905
906         boolgen(n, true, D_NONE, Z, Z);
907 }
908
909 void
910 boolgen(Node *n, int true, int result, Node *nn, Node *post)
911 {
912         Prog *p1, *p2;
913         Node *l, *r;
914         int lg, rg, fp, o;
915         long v;
916
917         if(debug['g']) {
918                 if(result == D_TREE)
919                         prtree(nn, "result");
920                 else
921                         print("result = %R\n", result);
922                 prtree(n, "boolgen");
923         }
924         l = n->left;
925         r = n->right;
926         switch(n->op) {
927
928         default:
929                 lg = eval(n, result);
930                 if(lg >= D_A0 && lg < D_A0+NREG) {
931                         rg = regalloc(types[TLONG], D_NONE);
932                         gopcode(OAS, types[TLONG], lg, n, rg, Z);
933                         regfree(rg);
934                 } else
935                         gopcode(OTST, n->type, D_NONE, Z, lg, n);
936                 regfree(lg);
937                 o = ONE;
938                 fp = typefd[n->type->etype];
939                 goto genbool;
940
941         case OCONST:
942                 fp = vconst(n);
943                 if(!true)
944                         fp = !fp;
945                 gbranch(OGOTO);
946                 if(fp) {
947                         p1 = p;
948                         gbranch(OGOTO);
949                         patch(p1, pc);
950                 }
951                 goto com;
952
953         case ONOT:
954                 boolgen(l, !true, result, nn, post);
955                 break;
956
957         case OCOND:
958                 doinc(l, PRE);
959                 boolgen(l, 1, D_NONE, Z, l);
960                 p1 = p;
961
962                 inargs++;
963                 doinc(r->left, PRE);
964                 boolgen(r->left, true, result, nn, r->left);
965                 if(result != D_NONE) {
966                         doinc(r->left, POST);
967                         gbranch(OGOTO);
968                         patch(p1, pc);
969                         p1 = p;
970
971                         doinc(r->right, PRE);
972                         boolgen(r->right, !true, result, nn, r->right);
973                         doinc(r->right, POST);
974                         patch(p1, pc);
975                         inargs--;
976                         break;
977                 }
978                 p2 = p;
979                 gbranch(OGOTO);
980                 patch(p1, pc);
981                 p1 = p;
982
983                 doinc(r->right, PRE);
984                 boolgen(r->right, !true, result, nn, r->right);
985                 patch(p2, pc);
986                 p2 = p;
987                 if(doinc(post, POST|TEST)) {
988                         lg = regalloc(types[TSHORT], D_NONE);
989                         gopcode(OAS, types[TSHORT], D_CCR, Z, lg, Z);
990                         doinc(post, POST);
991                         gopcode(OAS, types[TSHORT], lg, Z, D_CCR, Z);
992                         regfree(lg);
993                 }
994                 gbranch(OGOTO);
995                 patch(p1, pc);
996                 patch(p2, pc);
997                 inargs--;
998                 goto com;
999
1000         case OANDAND:
1001                 if(!true)
1002                         goto caseor;
1003
1004         caseand:
1005                 doinc(l, PRE);
1006                 boolgen(l, true, D_NONE, Z, l);
1007                 p1 = p;
1008                 inargs++;
1009                 doinc(r, PRE);
1010                 boolgen(r, !true, D_NONE, Z, r);
1011                 p2 = p;
1012                 patch(p1, pc);
1013                 gbranch(OGOTO);
1014                 patch(p2, pc);
1015                 inargs--;
1016                 goto com;
1017
1018         case OOROR:
1019                 if(!true)
1020                         goto caseand;
1021
1022         caseor:
1023                 doinc(l, PRE);
1024                 boolgen(l, !true, D_NONE, Z, l);
1025                 p1 = p;
1026                 inargs++;
1027                 doinc(r, PRE);
1028                 boolgen(r, !true, D_NONE, Z, r);
1029                 p2 = p;
1030                 gbranch(OGOTO);
1031                 patch(p1, pc);
1032                 patch(p2, pc);
1033                 inargs--;
1034                 goto com;
1035
1036         case OEQ:
1037         case ONE:
1038                 if(vconst(l) == 0) {
1039                         if(n->op == ONE) {
1040                                 boolgen(r, true, result, nn, post);
1041                                 break;
1042                         }
1043                         boolgen(r, !true, result, nn, post);
1044                         break;
1045                 }
1046
1047         case OLE:
1048         case OLT:
1049         case OGE:
1050         case OGT:
1051         case OHI:
1052         case OHS:
1053         case OLO:
1054         case OLS:
1055                 fp = typefd[r->type->etype];
1056                 if(l->op == OCONST) {
1057                         v = vconst(l);
1058                         if(v == 0) {    /* tst instruction */
1059                                 o = invrel[relindex(n->op)];
1060                                 rg = eval(r, result);
1061                                 gopcode(OTST, r->type, D_NONE, Z, rg, r);
1062                                 regfree(rg);
1063                                 goto genbool;
1064                         }
1065                         if(!fp) {       /* cmpi and movq, saves about .5% both time and space */
1066                                 if(v < 128 && v >= -128 &&
1067                                    ewidth[r->type->etype] == SZ_LONG) {
1068                                         rg = eval(r, result);
1069                                         lg = regalloc(l->type, D_NONE);
1070                                         cgen(l, lg, l);
1071                                         o = n->op;
1072                                         gopcode(o, l->type, lg, l, rg, r);
1073                                         regfree(lg);
1074                                         regfree(rg);
1075                                         goto genbool;
1076                                 }
1077                                 o = invrel[relindex(n->op)];
1078                                 rg = eval(r, result);
1079                                 gopcode(o, r->type, rg, r, D_TREE, l);
1080                                 regfree(rg);
1081                                 goto genbool;
1082                         }
1083                 }
1084                 lg = D_TOS;
1085                 if(r->complex < FNX)
1086                         lg = regalloc(l->type, lg);
1087                 cgen(l, lg, l);
1088                 v = argoff;
1089                 rg = eval(r, result);
1090                 if(lg == D_TOS) {
1091                         adjsp(v - argoff);
1092                         lg = regalloc(l->type, lg);
1093                         gopcode(OAS, l->type, D_TOS, l, lg, l);
1094                 }
1095                 o = n->op;
1096                 gopcode(o, l->type, lg, l, rg, r);
1097                 regfree(lg);
1098                 regfree(rg);
1099
1100         genbool:
1101                 if(true)
1102                         o = comrel[relindex(o)];
1103                 if(doinc(post, POST|TEST)) {
1104                         lg = regalloc(types[TSHORT], D_NONE);
1105                         gopcode(OAS, types[TSHORT], D_CCR, Z, lg, Z);
1106                         doinc(post, POST);
1107                         gopcode(OAS, types[TSHORT], lg, Z, D_CCR, Z);
1108                         regfree(lg);
1109                 }
1110                 gbranch(o);
1111                 if(fp)
1112                         fpbranch();
1113
1114         com:
1115                 if(result == D_NONE)
1116                         break;
1117                 p1 = p;
1118                 gopcode(OAS, nn->type, D_CONST, nodconst(1), result, nn);
1119                 gbranch(OGOTO);
1120                 p2 = p;
1121                 patch(p1, pc);
1122                 gopcode(OAS, nn->type, D_CONST, nodconst(0), result, nn);
1123                 patch(p2, pc);
1124                 break;
1125         }
1126 }
1127
1128 void
1129 sugen(Node *n, int result, Node *nn, long w)
1130 {
1131         long s, v, o;
1132         int lg, rg, ng;
1133         Prog *p1;
1134         Node *l, *r, nod;
1135         Type *t;
1136
1137         if(n == Z || n->type == T)
1138                 return;
1139         if(debug['g']) {
1140                 if(result == D_TREE)
1141                         prtree(nn, "result");
1142                 else
1143                         print("result = %R width = %ld\n", result, w);
1144                 prtree(n, "sugen");
1145         }
1146         s = argoff;
1147         if(result == D_TREE) {
1148                 if(nn == nodrat)
1149                         if(w > nrathole)
1150                                 nrathole = w;
1151         }
1152
1153         if(n->addable >= INDEXED && n->op != OCONST)
1154                 goto copy;
1155         switch(n->op) {
1156         default:
1157                 diag(n, "unknown op in sugen: %O", n->op);
1158                 break;
1159
1160         case OCONST:
1161                 if(n->type && typev[n->type->etype]) {
1162                         if(result == D_NONE) {
1163                                 nullwarn(n->left, Z);
1164                                 break;
1165                         }
1166
1167                         lg = regaddr(D_NONE);
1168                         if(result == D_TOS) {
1169                                 adjsp(s - argoff + w);
1170                                 gopcode(OADDR, types[TIND], result, nn, lg, n);
1171                         } else
1172                         if(result == D_TREE) {
1173                                 lcgen(nn, lg, Z);
1174                         } else
1175                                 diag(n, "unknown su result: %R", result);
1176
1177                         gopcode(OAS, types[TLONG], D_CONST, nodconst((long)(n->vconst>>32)),
1178                                 lg|I_INDINC, n);
1179                         gopcode(OAS, types[TLONG], D_CONST, nodconst((long)(n->vconst)),
1180                                 lg|I_INDINC, n);
1181                         regfree(lg);
1182                         break;
1183                 }
1184                 goto copy;
1185
1186         case ODOT:
1187                 l = n->left;
1188                 sugen(l, D_TREE, nodrat, l->type->width);
1189                 if(result != D_NONE) {
1190                         warn(n, "non-interruptable temporary");
1191                         nod = *nodrat;
1192                         r = n->right;
1193                         if(!r || r->op != OCONST) {
1194                                 diag(n, "DOT and no offset");
1195                                 break;
1196                         }
1197                         nod.xoffset += r->vconst;
1198                         nod.type = n->type;
1199                         sugen(&nod, result, nn, w);
1200                 }
1201                 break;
1202
1203         case OIND:
1204                 if(result == D_NONE) {
1205                         nullwarn(n->left, Z);
1206                         break;
1207                 }
1208                 goto copy;
1209
1210         case OSTRUCT:
1211                 lg = nodalloc(types[TIND], result, &nod);
1212                 nod.lineno = n->lineno;
1213                 if(result == D_TREE)
1214                         lcgen(nn, lg, Z);
1215                 else
1216                 if(result == D_TOS) {
1217                         adjsp(s - argoff + w);
1218                         gopcode(OADDR, types[TIND], result, nn, lg, n);
1219                 } else
1220                         diag(n, "unknown su result: %R", result);
1221                 o = 0;
1222                 r = n->left;
1223                 for(t = n->type->link; t != T; t = t->down) {
1224                         l = r;                  
1225                         if(r->op == OLIST) {
1226                                 l = r->left;
1227                                 r = r->right;
1228                         }
1229                         nod.type = t;
1230                         if(l->complex < FNX) {
1231                                 nod.xoffset = 0;
1232                                 if(o != t->offset) {
1233                                         gopcode(OADD, types[TIND], D_CONST,
1234                                                 nodconst(t->offset-o), lg, Z);
1235                                         o = t->offset;
1236                                 }
1237                                 cgen(l, D_TREE, &nod);
1238                                 continue;
1239                         }
1240                         nod.xoffset = t->offset - o;
1241                         gopcode(OAS, types[TIND], lg, Z, D_TOS, Z);
1242                         s = argoff;
1243                         if(typesuv[t->etype]) {
1244                                 sugen(l, D_TREE, nodrat, t->width);
1245                                 adjsp(s - argoff);
1246                                 gopcode(OAS, types[TIND], D_TOS, Z, lg, Z);
1247                                 warn(n, "non-interruptable temporary");
1248                                 sugen(nodrat, D_TREE, &nod, t->width);
1249                                 continue;
1250                         }
1251                         rg = regalloc(t, D_NONE);
1252                         cgen(l, rg, l);
1253                         adjsp(s - argoff);
1254                         gopcode(OAS, types[TIND], D_TOS, Z, lg, Z);
1255                         gopcode(OAS, t, rg, Z, D_TREE, &nod);
1256                         regfree(rg);
1257                 }
1258                 regfree(lg);
1259                 break;
1260
1261         case OAS:
1262                 if(result == D_NONE) {
1263                         sugen(n->right, D_TREE, n->left, w);
1264                         break;
1265                 }
1266                 sugen(n->right, D_TREE, nodrat, w);     /* could do better */
1267                 warn(n, "non-interruptable temporary");
1268                 sugen(nodrat, D_TREE, n->left, w);
1269                 sugen(nodrat, result, nn, w);
1270                 break;
1271
1272         case OFUNC:
1273                 if(result == D_NONE) {
1274                         sugen(n, D_TREE, nodrat, w);
1275                         break;
1276                 }
1277                 inargs++;
1278                 /* prepare zero-th arg: address of result */
1279                 if(result == D_TOS) {
1280                         adjsp(s - argoff + w);
1281                         v = argoff;
1282                         gargs(n->right);
1283                         gopcode(OADDR, types[TSHORT], D_NONE, nn, result, nn);
1284                         p->to.type = D_STACK;
1285                         p->to.offset = argoff - v;
1286                 } else
1287                 if(result == D_TREE) {
1288                         v = argoff;
1289                         gargs(n->right);
1290                         if(nn->complex >= FNX) {
1291                                 rg = regalloc(types[TIND], regret(types[TIND]));
1292                                 lcgen(nn, rg, Z);
1293                                 gopcode(OAS, types[TIND], rg, Z, D_TOS, Z);
1294                                 regfree(rg);
1295                         } else
1296                                 lcgen(nn, D_TOS, Z);
1297                 } else {
1298                         diag(n, "unknown result in FUNC sugen");
1299                         break;
1300                 }
1301                 argoff += types[TIND]->width;
1302                 l = n->left;
1303                 lg = D_TREE;
1304                 if(l->addable < INDEXED) {
1305                         lg = regaddr(result);
1306                         lcgen(l, lg, Z);
1307                         lg |= I_INDIR;
1308                 }
1309                 inargs--;
1310                 doinc(n->right, POST);
1311                 doinc(n->left, POST);
1312                 gopcode(OFUNC, types[TCHAR], D_NONE, Z, lg, l);
1313                 regfree(lg);
1314                 if(inargs)
1315                         adjsp(v - argoff);
1316                 break;
1317
1318         case OCOND:
1319                 doinc(n->left, PRE);
1320                 boolgen(n->left, 1, D_NONE, Z, n->left);
1321                 p1 = p;
1322
1323                 inargs++;
1324                 doinc(n->right->left, PRE);
1325                 sugen(n->right->left, result, nn, w);
1326                 doinc(n->right->left, POST);
1327                 gbranch(OGOTO);
1328                 patch(p1, pc);
1329                 p1 = p;
1330
1331                 doinc(n->right->right, PRE);
1332                 sugen(n->right->right, result, nn, w);
1333                 doinc(n->right->right, POST);
1334                 patch(p1, pc);
1335                 inargs--;
1336                 break;
1337
1338         case OCOMMA:
1339                 cgen(n->left, D_NONE, n->left);
1340                 doinc(n->left, POST);
1341                 doinc(n->right, PRE);
1342                 sugen(n->right, result, nn, w);
1343                 break;
1344         }
1345         return;
1346
1347 copy:
1348         if(result == D_NONE)
1349                 return;
1350         rg = regaddr(D_NONE);
1351         lcgen(n, rg, Z);
1352
1353         lg = regaddr(D_NONE);
1354         if(result == D_TOS) {
1355                 adjsp(s - argoff + w);
1356                 gopcode(OADDR, types[TIND], result, nn, lg, n);
1357         } else
1358         if(result == D_TREE) {
1359                 if(nn->complex >= FNX) {
1360                         gopcode(OAS, types[TIND], rg, n, D_TOS, n);
1361                         s = argoff;
1362                         lcgen(nn, lg, Z);
1363                         adjsp(s - argoff);
1364                         gopcode(OAS, types[TIND], D_TOS, n, rg, n);
1365                 } else
1366                         lcgen(nn, lg, Z);
1367         } else
1368                 diag(n, "unknown su result: %R", result);
1369
1370         if(w % SZ_LONG)
1371                 diag(Z, "sucopy width not 0%%%d", SZ_LONG);
1372         v = w / SZ_LONG;
1373         if(v & 1) {
1374                 gopcode(OAS, types[TLONG], rg|I_INDINC, n, lg|I_INDINC, n);
1375                 v--;
1376         }
1377         if(v > 6) {
1378                 ng = regalloc(types[TLONG], D_NONE);
1379                 gopcode(OAS, types[TLONG], D_CONST, nodconst(v/2-1), ng, n);
1380                 v = pc;
1381                 gopcode(OAS, types[TLONG], rg|I_INDINC, n, lg|I_INDINC, n);
1382                 gopcode(OAS, types[TLONG], rg|I_INDINC, n, lg|I_INDINC, n);
1383                 gbranch(OGT);
1384                 patch(p, v);
1385                 p->from.type = ng;
1386                 p->as = ADBF;
1387                 regfree(ng);
1388         } else
1389                 while(v > 0) {
1390                         gopcode(OAS, types[TLONG], rg|I_INDINC, n, lg|I_INDINC, n);
1391                         v--;
1392                 }
1393
1394         regfree(lg);
1395         regfree(rg);
1396 }