]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/1c/sgen.c
ircrc: freenode -> oftc
[plan9front.git] / sys / src / cmd / 1c / sgen.c
1 #include "gc.h"
2
3 void
4 codgen(Node *n, Node *nn)
5 {
6         Prog *sp;
7
8         argoff = 0;
9         inargs = 0;
10         for(;; nn = nn->left) {
11                 if(nn == Z) {
12                         diag(Z, "cant find function name");
13                         return;
14                 }
15                 if(nn->op == ONAME)
16                         break;
17         }
18         nearln = nn->lineno;
19         gpseudo(ATEXT, nn->sym, D_CONST, stkoff);
20         sp = p;
21
22         retok = 0;
23         gen(n);
24         if(!retok)
25                 if(thisfn->link->etype != TVOID)
26                         warn(Z, "no return at end of function: %s", nn->sym->name);
27
28         noretval(3);
29         gbranch(ORETURN);
30         if(!debug['N'] || debug['R'] || debug['P'])
31                 regopt(sp);
32 }
33
34 void
35 gen(Node *n)
36 {
37         Node *l;
38         Prog *sp, *spc, *spb;
39         Case *cn;
40         long sbc, scc;
41         int snbreak;
42         int g, o;
43
44 loop:
45         if(n == Z)
46                 return;
47         nearln = n->lineno;
48         o = n->op;
49         if(debug['G'])
50                 if(o != OLIST)
51                         print("%L %O\n", nearln, o);
52
53         retok = 0;
54         switch(o) {
55
56         default:
57                 complex(n);
58                 doinc(n, PRE);
59                 cgen(n, D_NONE, n);
60                 doinc(n, POST);
61                 break;
62
63         case OLIST:
64                 gen(n->left);
65
66         rloop:
67                 n = n->right;
68                 goto loop;
69
70         case ORETURN:
71                 retok = 1;
72                 complex(n);
73                 if(n->type == T)
74                         break;
75                 l = n->left;
76                 if(l == Z) {
77                         noretval(3);
78                         gbranch(ORETURN);
79                         break;
80                 }
81                 doinc(l, PRE);
82                 if(typesuv[n->type->etype]) {
83                         sugen(l, D_TREE, nodret, n->type->width);
84                         doinc(l, POST);
85                         noretval(3);
86                         gbranch(ORETURN);
87                         break;
88                 }
89                 g = regalloc(n->type, regret(n->type));
90                 cgen(l, g, n);
91                 doinc(l, POST);
92                 if(typefd[n->type->etype])
93                         noretval(1);
94                 else
95                         noretval(2);
96                 gbranch(ORETURN);
97                 regfree(g);
98                 break;
99
100         case OLABEL:
101                 l = n->left;
102                 if(l) {
103                         l->xoffset = pc;
104                         if(l->label)
105                                 patch(l->label, pc);
106                 }
107                 gbranch(OGOTO); /* prevent self reference in reg */
108                 patch(p, pc);
109                 goto rloop;
110
111         case OGOTO:
112                 retok = 1;
113                 n = n->left;
114                 if(n == Z)
115                         return;
116                 if(n->complex == 0) {
117                         diag(Z, "label undefined: %s", n->sym->name);
118                         return;
119                 }
120                 gbranch(OGOTO);
121                 if(n->xoffset) {
122                         patch(p, n->xoffset);
123                         return;
124                 }
125                 if(n->label)
126                         patch(n->label, pc-1);
127                 n->label = p;
128                 return;
129
130         case OCASE:
131                 l = n->left;
132                 if(cases == C)
133                         diag(n, "case/default outside a switch");
134                 if(l == Z) {
135                         casf();
136                         cases->val = 0;
137                         cases->def = 1;
138                         cases->label = pc;
139                         setsp();;
140                         goto rloop;
141                 }
142                 complex(l);
143                 if(l->type == T)
144                         goto rloop;
145                 if(l->op == OCONST)
146                 if(typechl[l->type->etype]) {
147                         casf();
148                         cases->val = l->vconst;
149                         cases->def = 0;
150                         cases->label = pc;
151                         setsp();
152                         goto rloop;
153                 }
154                 diag(n, "case expression must be integer constant");
155                 goto rloop;
156
157         case OSWITCH:
158                 l = n->left;
159                 complex(l);
160                 doinc(l, PRE);
161                 if(l->type == T)
162                         break;
163                 if(!typechl[l->type->etype]) {
164                         diag(n, "switch expression must be integer");
165                         break;
166                 }
167                 g = regalloc(types[TLONG], D_NONE);
168                 n->type = types[TLONG];
169                 cgen(l, g, n);
170                 regfree(g);
171                 doinc(l, POST);
172                 setsp();
173                 gbranch(OGOTO);         /* entry */
174                 sp = p;
175
176                 cn = cases;
177                 cases = C;
178                 casf();
179
180                 sbc = breakpc;
181                 breakpc = pc;
182                 snbreak = nbreak;
183                 nbreak = 0;
184                 gbranch(OGOTO);
185                 spb = p;
186
187                 gen(n->right);
188                 gbranch(OGOTO);
189                 patch(p, breakpc);
190                 nbreak++;
191
192                 patch(sp, pc);
193                 doswit(g, l);
194
195                 patch(spb, pc);
196                 cases = cn;
197                 breakpc = sbc;
198                 nbreak = snbreak;
199                 setsp();
200                 break;
201
202         case OWHILE:
203         case ODWHILE:
204                 l = n->left;
205                 gbranch(OGOTO);         /* entry */
206                 sp = p;
207
208                 scc = continpc;
209                 continpc = pc;
210                 gbranch(OGOTO);
211                 spc = p;
212
213                 sbc = breakpc;
214                 breakpc = pc;
215                 snbreak = nbreak;
216                 nbreak = 0;
217                 gbranch(OGOTO);
218                 spb = p;
219
220                 patch(spc, pc);
221                 if(n->op == OWHILE)
222                         patch(sp, pc);
223                 bcomplex(l);    /* test */
224                 patch(p, breakpc);
225                 if(l->op != OCONST || vconst(l) == 0)
226                         nbreak++;
227
228                 if(n->op == ODWHILE)
229                         patch(sp, pc);
230                 gen(n->right);          /* body */
231                 gbranch(OGOTO);
232                 patch(p, continpc);
233
234                 patch(spb, pc);
235                 continpc = scc;
236                 breakpc = sbc;
237                 if(nbreak == 0)
238                         retok = 1;
239                 nbreak = snbreak;
240                 break;
241
242         case OFOR:
243                 l = n->left;
244                 gen(l->right->left);    /* init */
245                 gbranch(OGOTO);                 /* entry */
246                 sp = p;
247
248                 scc = continpc;
249                 continpc = pc;
250                 gbranch(OGOTO);
251                 spc = p;
252
253                 sbc = breakpc;
254                 breakpc = pc;
255                 snbreak = nbreak;
256                 nbreak = 0;
257                 gbranch(OGOTO);
258                 spb = p;
259
260                 patch(spc, pc);
261                 gen(l->right->right);   /* inc */
262                 patch(sp, pc);  
263                 if(l->left != Z) {      /* test */
264                         bcomplex(l->left);
265                         patch(p, breakpc);
266                         if(l->left->op != OCONST || vconst(l->left) == 0)
267                                 nbreak++;
268                 }
269                 gen(n->right);          /* body */
270                 gbranch(OGOTO);
271                 patch(p, continpc);
272
273                 patch(spb, pc);
274                 continpc = scc;
275                 breakpc = sbc;
276                 if(nbreak == 0)
277                         retok = 1;
278                 nbreak = snbreak;
279                 break;
280
281         case OCONTINUE:
282                 if(continpc < 0) {
283                         diag(n, "continue not in a loop");
284                         break;
285                 }
286                 gbranch(OGOTO);
287                 patch(p, continpc);
288                 break;
289
290         case OBREAK:
291                 if(breakpc < 0) {
292                         diag(n, "break not in a loop");
293                         break;
294                 }
295                 gbranch(OGOTO);
296                 patch(p, breakpc);
297                 nbreak++;
298                 break;
299
300         case OIF:
301                 l = n->left;
302                 bcomplex(l);
303                 sp = p;
304                 if(n->right->left != Z)
305                         gen(n->right->left);
306                 if(n->right->right != Z) {
307                         gbranch(OGOTO);
308                         patch(sp, pc);
309                         sp = p;
310                         gen(n->right->right);
311                 }
312                 patch(sp, pc);
313                 break;
314
315         case OSET:
316         case OUSED:
317                 usedset(n->left, o);
318                 break;
319         }
320 }
321
322 void
323 usedset(Node *n, int o)
324 {
325         if(n->op == OLIST) {
326                 usedset(n->left, o);
327                 usedset(n->right, o);
328                 return;
329         }
330         complex(n);
331         switch(n->op) {
332         case OADDR:     /* volatile */
333                 gopcode(OTST, types[TINT], D_TREE, n, D_NONE, Z);
334                 p->as = ANOP;
335                 break;
336         case ONAME:
337                 if(o == OSET)
338                         gopcode(OTST, types[TINT], D_NONE, Z, D_TREE, n);
339                 else
340                         gopcode(OTST, types[TINT], D_TREE, n, D_NONE, Z);
341                 p->as = ANOP;
342                 break;
343         }
344 }
345
346 void
347 noretval(int n)
348 {
349
350         if(n & 1) {
351                 gopcode(OTST, types[TINT], D_NONE, Z, regret(types[TLONG]), Z);
352                 p->as = ANOP;
353         }
354         if(n & 2) {
355                 gopcode(OTST, types[TINT], D_NONE, Z, regret(types[TDOUBLE]), Z);
356                 p->as = ANOP;
357         }
358 }
359
360 /*
361  *      calculate addressability as follows
362  *              REGISTER ==> 12         register
363  *              NAME ==> 11             name+value(SB/SP)
364  *                      note that 10 is no longer generated
365  *              CONST ==> 20            $value
366  *              *(20) ==> 21            value
367  *              &(10) ==> 12            $name+value(SB)
368  *              &(11) ==> 1             $name+value(SP)
369  *              (12) + (20) ==> 12      fold constants
370  *              (1) + (20) ==> 1        fold constants
371  *              *(12) ==> 10            back to name
372  *              *(1) ==> 11             back to name
373  *
374  *              (2,10,11) + (20) ==> 2  indirect w offset
375  *              (2) ==> &13
376  *              *(10,11) ==> 13         indirect, no index
377  *
378  *              (20) * (X) ==> 7        multiplier in indexing
379  *              (X,7) + (12,1) ==> 8    adder in indexing (addresses)
380  *              (X,7) + (10,11,2) ==> 8 adder in indexing (names)
381  *              (8) ==> &9              index, almost addressable
382  *
383  *              (X)++ ==> X             fake addressability
384  *
385  *      calculate complexity (number of registers)
386  */
387 void
388 xcom(Node *n)
389 {
390         Node *l, *r;
391         int g;
392
393         if(n == Z)
394                 return;
395         l = n->left;
396         r = n->right;
397         n->complex = 0;
398         n->addable = 0;
399         switch(n->op) {
400         case OCONST:
401                 n->addable = 20;
402                 break;
403
404         case ONAME:
405                 n->addable = 11;        /* difference to make relocatable */
406                 break;
407
408         case OREGISTER:
409                 n->addable = 12;
410                 break;
411
412         case OADDR:
413                 xcom(l);
414                 if(l->addable == 10)
415                         n->addable = 12;
416                 else
417                 if(l->addable == 11)
418                         n->addable = 1;
419                 break;
420
421         case OADD:
422                 xcom(l);
423                 xcom(r);
424                 if(n->type->etype != TIND)
425                         break;
426
427                 if(l->addable == 20)
428                 switch(r->addable) {
429                 case 12:
430                 case 1:
431                         n->addable = r->addable;
432                         goto brk;
433                 }
434                 if(r->addable == 20)
435                 switch(l->addable) {
436                 case 12:
437                 case 1:
438                         n->addable = l->addable;
439                         goto brk;
440                 }
441                 break;
442
443         case OIND:
444                 xcom(l);
445                 if(l->op == OADDR) {
446                         l = l->left;
447                         l->type = n->type;
448                         *n = *l;
449                         return;
450                 }
451                 switch(l->addable) {
452                 case 20:
453                         n->addable = 21;
454                         break;
455                 case 1:
456                         n->addable = 11;
457                         break;
458                 case 12:
459                         n->addable = 10;
460                         break;
461                 }
462                 break;
463
464         case OASHL:
465                 xcom(l);
466                 xcom(r);
467                 if(typev[n->type->etype])
468                         break;
469                 g = vconst(r);
470                 if(g >= 0 && g < 4)
471                         n->addable = 7;
472                 break;
473
474         case OMUL:
475         case OLMUL:
476                 xcom(l);
477                 xcom(r);
478                 if(typev[n->type->etype])
479                         break;
480                 g = vlog(r);
481                 if(g >= 0) {
482                         n->op = OASHL;
483                         r->vconst = g;
484                         if(g < 4)
485                                 n->addable = 7;
486                         break;
487                 }
488                 g = vlog(l);
489                 if(g >= 0) {
490                         n->left = r;
491                         n->right = l;
492                         l = r;
493                         r = n->right;
494                         n->op = OASHL;
495                         r->vconst = g;
496                         if(g < 4)
497                                 n->addable = 7;
498                         break;
499                 }
500                 break;
501
502         case ODIV:
503         case OLDIV:
504                 xcom(l);
505                 xcom(r);
506                 if(typev[n->type->etype])
507                         break;
508                 g = vlog(r);
509                 if(g >= 0) {
510                         if(n->op == ODIV)
511                                 n->op = OASHR;
512                         else
513                                 n->op = OLSHR;
514                         r->vconst = g;
515                 }
516                 break;
517
518         case OSUB:
519                 xcom(l);
520                 xcom(r);
521                 if(typev[n->type->etype])
522                         break;
523                 if(vconst(l) == 0) {
524                         n->op = ONEG;
525                         n->left = r;
526                         n->right = Z;
527                 }
528                 break;
529
530         case OXOR:
531                 xcom(l);
532                 xcom(r);
533                 if(typev[n->type->etype])
534                         break;
535                 if(vconst(l) == -1) {
536                         n->op = OCOM;
537                         n->left = r;
538                         n->right = Z;
539                 }
540                 break;
541
542         case OASMUL:
543         case OASLMUL:
544                 xcom(l);
545                 xcom(r);
546                 if(typev[n->type->etype])
547                         break;
548                 g = vlog(r);
549                 if(g >= 0) {
550                         n->op = OASASHL;
551                         r->vconst = g;
552                 }
553                 goto aseae;
554
555         case OASDIV:
556         case OASLDIV:
557                 xcom(l);
558                 xcom(r);
559                 if(typev[n->type->etype])
560                         break;
561                 g = vlog(r);
562                 if(g >= 0) {
563                         if(n->op == OASDIV)
564                                 n->op = OASASHR;
565                         else
566                                 n->op = OASLSHR;
567                         r->vconst = g;
568                 }
569                 goto aseae;
570
571         case OASLMOD:
572         case OASMOD:
573                 xcom(l);
574                 xcom(r);
575                 if(typev[n->type->etype])
576                         break;
577
578         aseae:          /* hack that there are no byte/short mul/div operators */
579                 if(n->type->etype == TCHAR || n->type->etype == TSHORT) {
580                         n->right = new1(OCAST, n->right, Z);
581                         n->right->type = types[TLONG];
582                         n->type = types[TLONG];
583                 }
584                 if(n->type->etype == TUCHAR || n->type->etype == TUSHORT) {
585                         n->right = new1(OCAST, n->right, Z);
586                         n->right->type = types[TULONG];
587                         n->type = types[TULONG];
588                 }
589                 goto asop;
590
591         case OASXOR:
592         case OASOR:
593         case OASADD:
594         case OASSUB:
595         case OASLSHR:
596         case OASASHR:
597         case OASASHL:
598         case OASAND:
599         case OAS:
600                 xcom(l);
601                 xcom(r);
602                 if(typev[n->type->etype])
603                         break;
604
605         asop:
606                 if(l->addable > INDEXED &&
607                    l->complex < FNX &&
608                    r && r->complex < FNX)
609                         n->addable = l->addable;
610                 break;
611
612         case OPOSTINC:
613         case OPREINC:
614         case OPOSTDEC:
615         case OPREDEC:
616                 xcom(l);
617                 if(typev[n->type->etype])
618                         break;
619                 if(l->addable > INDEXED &&
620                    l->complex < FNX)
621                         n->addable = l->addable;
622                 break;
623
624         default:
625                 if(l != Z)
626                         xcom(l);
627                 if(r != Z)
628                         xcom(r);
629                 break;
630         }
631
632 brk:
633         n->complex = 0;
634         if(n->addable >= 10)
635                 return;
636         if(l != Z)
637                 n->complex = l->complex;
638         if(r != Z) {
639                 if(r->complex == n->complex)
640                         n->complex = r->complex+1;
641                 else
642                 if(r->complex > n->complex)
643                         n->complex = r->complex;
644         }
645         if(n->complex == 0)
646                 n->complex++;
647
648         if(com64(n))
649                 return;
650
651         switch(n->op) {
652
653         case OFUNC:
654                 n->complex = FNX;
655                 break;
656
657         case OADD:
658         case OMUL:
659         case OLMUL:
660         case OXOR:
661         case OAND:
662         case OOR:
663                 /*
664                  * symmetric operators, make right side simple
665                  * if same, put constant on left to get movq
666                  */
667                 if(r->complex > l->complex ||
668                   (r->complex == l->complex && r->addable == 20)) {
669                         n->left = r;
670                         n->right = l;
671                 }
672                 break;
673
674         case OLE:
675         case OLT:
676         case OGE:
677         case OGT:
678         case OEQ:
679         case ONE:
680                 /*
681                  * relational operators, make right side simple
682                  * if same, put constant on left to get movq
683                  */
684                 if(r->complex > l->complex || r->addable == 20) {
685                         n->left = r;
686                         n->right = l;
687                         n->op = invrel[relindex(n->op)];
688                 }
689                 break;
690         }
691 }
692
693 void
694 bcomplex(Node *n)
695 {
696
697         complex(n);
698         if(n->type != T)
699         if(tcompat(n, T, n->type, tnot))
700                 n->type = T;
701         if(n->type != T) {
702                 bool64(n);
703                 doinc(n, PRE);
704                 boolgen(n, 1, D_NONE, Z, n);
705         } else
706                 gbranch(OGOTO);
707 }
708
709 Node*
710 nodconst(long v)
711 {
712
713         return (Node*)v;
714 }