]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cc/scon.c
ip/ipconfig: use ewrite() to enable routing command for sendra
[plan9front.git] / sys / src / cmd / cc / scon.c
1 #include "cc.h"
2
3 static Node*
4 acast(Type *t, Node *n)
5 {
6         if(n->type->etype != t->etype || n->op == OBIT) {
7                 n = new1(OCAST, n, Z);
8                 if(nocast(n->left->type, t))
9                         *n = *n->left;
10                 n->type = t;
11         }
12         return n;
13 }
14
15
16 void
17 evconst(Node *n)
18 {
19         Node *l, *r;
20         int et, isf;
21         vlong v;
22         double d;
23
24         if(n == Z || n->type == T)
25                 return;
26
27         et = n->type->etype;
28         isf = typefd[et];
29
30         l = n->left;
31         r = n->right;
32
33         d = 0;
34         v = 0;
35
36         switch(n->op) {
37         default:
38                 return;
39
40         case ONEG:
41                 if(isf)
42                         d = -l->fconst;
43                 else
44                         v = -l->vconst;
45                 break;
46
47         case OCOM:
48                 v = ~l->vconst;
49                 break;
50
51         case OCAST:
52                 if(et == TVOID)
53                         return;
54                 et = l->type->etype;
55                 if(isf) {
56                         if(typefd[et])
57                                 d = l->fconst;
58                         else
59                                 d = l->vconst;
60                 } else {
61                         if(typefd[et])
62                                 v = l->fconst;
63                         else
64                                 v = convvtox(l->vconst, n->type->etype);
65                 }
66                 break;
67
68         case OCONST:
69                 break;
70
71         case OADD:
72                 if(isf)
73                         d = l->fconst + r->fconst;
74                 else {
75                         v = l->vconst + r->vconst;
76                 }
77                 break;
78
79         case OSUB:
80                 if(isf)
81                         d = l->fconst - r->fconst;
82                 else
83                         v = l->vconst - r->vconst;
84                 break;
85
86         case OMUL:
87                 if(isf)
88                         d = l->fconst * r->fconst;
89                 else {
90                         v = l->vconst * r->vconst;
91                 }
92                 break;
93
94         case OLMUL:
95                 v = (uvlong)l->vconst * (uvlong)r->vconst;
96                 break;
97
98
99         case ODIV:
100                 if(vconst(r) == 0) {
101                         warn(n, "divide by zero");
102                         return;
103                 }
104                 if(isf)
105                         d = l->fconst / r->fconst;
106                 else
107                         v = l->vconst / r->vconst;
108                 break;
109
110         case OLDIV:
111                 if(vconst(r) == 0) {
112                         warn(n, "divide by zero");
113                         return;
114                 }
115                 v = (uvlong)l->vconst / (uvlong)r->vconst;
116                 break;
117
118         case OMOD:
119                 if(vconst(r) == 0) {
120                         warn(n, "modulo by zero");
121                         return;
122                 }
123                 v = l->vconst % r->vconst;
124                 break;
125
126         case OLMOD:
127                 if(vconst(r) == 0) {
128                         warn(n, "modulo by zero");
129                         return;
130                 }
131                 v = (uvlong)l->vconst % (uvlong)r->vconst;
132                 break;
133
134         case OAND:
135                 v = l->vconst & r->vconst;
136                 break;
137
138         case OOR:
139                 v = l->vconst | r->vconst;
140                 break;
141
142         case OXOR:
143                 v = l->vconst ^ r->vconst;
144                 break;
145
146         case OLSHR:
147                 v = (uvlong)l->vconst >> r->vconst;
148                 break;
149
150         case OASHR:
151                 v = l->vconst >> r->vconst;
152                 break;
153
154         case OASHL:
155                 v = l->vconst << r->vconst;
156                 break;
157
158         case OLO:
159                 v = (uvlong)l->vconst < (uvlong)r->vconst;
160                 break;
161
162         case OLT:
163                 if(typefd[l->type->etype])
164                         v = l->fconst < r->fconst;
165                 else
166                         v = l->vconst < r->vconst;
167                 break;
168
169         case OHI:
170                 v = (uvlong)l->vconst > (uvlong)r->vconst;
171                 break;
172
173         case OGT:
174                 if(typefd[l->type->etype])
175                         v = l->fconst > r->fconst;
176                 else
177                         v = l->vconst > r->vconst;
178                 break;
179
180         case OLS:
181                 v = (uvlong)l->vconst <= (uvlong)r->vconst;
182                 break;
183
184         case OLE:
185                 if(typefd[l->type->etype])
186                         v = l->fconst <= r->fconst;
187                 else
188                         v = l->vconst <= r->vconst;
189                 break;
190
191         case OHS:
192                 v = (uvlong)l->vconst >= (uvlong)r->vconst;
193                 break;
194
195         case OGE:
196                 if(typefd[l->type->etype])
197                         v = l->fconst >= r->fconst;
198                 else
199                         v = l->vconst >= r->vconst;
200                 break;
201
202         case OEQ:
203                 if(typefd[l->type->etype])
204                         v = l->fconst == r->fconst;
205                 else
206                         v = l->vconst == r->vconst;
207                 break;
208
209         case ONE:
210                 if(typefd[l->type->etype])
211                         v = l->fconst != r->fconst;
212                 else
213                         v = l->vconst != r->vconst;
214                 break;
215
216         case ONOT:
217                 if(typefd[l->type->etype])
218                         v = !l->fconst;
219                 else
220                         v = !l->vconst;
221                 break;
222
223         case OANDAND:
224                 if(typefd[l->type->etype])
225                         v = l->fconst && r->fconst;
226                 else
227                         v = l->vconst && r->vconst;
228                 break;
229
230         case OOROR:
231                 if(typefd[l->type->etype])
232                         v = l->fconst || r->fconst;
233                 else
234                         v = l->vconst || r->vconst;
235                 break;
236         }
237         if(isf) {
238                 n->fconst = d;
239         } else {
240                 n->vconst = convvtox(v, n->type->etype);
241         }
242         n->oldop = n->op;
243         n->op = OCONST;
244 }
245
246 void
247 acom(Node *n)
248 {
249         Type *t;
250         Node *l, *r;
251         int i;
252
253         switch(n->op)
254         {
255
256         case ONAME:
257         case OCONST:
258         case OSTRING:
259         case OINDREG:
260         case OREGISTER:
261                 return;
262
263         case ONEG:
264                 l = n->left;
265                 if(addo(n) && addo(l))
266                         break;
267                 acom(l);
268                 return;
269
270         case OADD:
271         case OSUB:
272         case OMUL:
273                 l = n->left;
274                 r = n->right;
275                 if(addo(n)) {
276                         if(addo(r))
277                                 break;
278                         if(addo(l))
279                                 break;
280                 }
281                 acom(l);
282                 acom(r);
283                 return;
284
285         default:
286                 l = n->left;
287                 r = n->right;
288                 if(l != Z)
289                         acom(l);
290                 if(r != Z)
291                         acom(r);
292                 return;
293         }
294
295         /* bust terms out */
296         t = n->type;
297         term[0].mult = 0;
298         term[0].node = Z;
299         nterm = 1;
300         acom1(1, n);
301         if(debug['m'])
302         for(i=0; i<nterm; i++) {
303                 print("%d %3lld ", i, term[i].mult);
304                 prtree1(term[i].node, 1, 0);
305         }
306         if(nterm < NTERM)
307                 acom2(n, t);
308         n->type = t;
309 }
310
311 int
312 acomcmp1(const void *a1, const void *a2)
313 {
314         vlong c1, c2;
315         Term *t1, *t2;
316
317         t1 = (Term*)a1;
318         t2 = (Term*)a2;
319         c1 = t1->mult;
320         if(c1 < 0)
321                 c1 = -c1;
322         c2 = t2->mult;
323         if(c2 < 0)
324                 c2 = -c2;
325         if(c1 > c2)
326                 return 1;
327         if(c1 < c2)
328                 return -1;
329         c1 = 1;
330         if(t1->mult < 0)
331                 c1 = 0;
332         c2 = 1;
333         if(t2->mult < 0)
334                 c2 = 0;
335         if(c2 -= c1)
336                 return c2;
337         if(t2 > t1)
338                 return 1;
339         return -1;
340 }
341
342 int
343 acomcmp2(const void *a1, const void *a2)
344 {
345         vlong c1, c2;
346         Term *t1, *t2;
347
348         t1 = (Term*)a1;
349         t2 = (Term*)a2;
350         c1 = t1->mult;
351         c2 = t2->mult;
352         if(c1 > c2)
353                 return 1;
354         if(c1 < c2)
355                 return -1;
356         if(t2 > t1)
357                 return 1;
358         return -1;
359 }
360
361 void
362 acom2(Node *n, Type *t)
363 {
364         Node *l, *r;
365         Term trm[NTERM];
366         int et, nt, i, j;
367         vlong c1, c2;
368
369         /*
370          * copy into automatic
371          */
372         c2 = 0;
373         nt = nterm;
374         for(i=0; i<nt; i++)
375                 trm[i] = term[i];
376         /*
377          * recur on subtrees
378          */
379         j = 0;
380         for(i=1; i<nt; i++) {
381                 c1 = trm[i].mult;
382                 if(c1 == 0)
383                         continue;
384                 l = trm[i].node;
385                 if(l != Z) {
386                         j = 1;
387                         acom(l);
388                 }
389         }
390         c1 = trm[0].mult;
391         if(j == 0) {
392                 n->oldop = n->op;
393                 n->op = OCONST;
394                 n->vconst = c1;
395                 return;
396         }
397         et = t->etype;
398
399         /*
400          * prepare constant term,
401          * combine it with an addressing term
402          */
403         if(c1 != 0) {
404                 l = new1(OCONST, Z, Z);
405                 l->type = t;
406                 l->vconst = c1;
407                 trm[0].mult = 1;
408                 for(i=1; i<nt; i++) {
409                         if(trm[i].mult != 1)
410                                 continue;
411                         r = trm[i].node;
412                         if(r->op != OADDR)
413                                 continue;
414                         r->type = t;
415                         l = new1(OADD, r, l);
416                         l->type = t;
417                         trm[i].mult = 0;
418                         break;
419                 }
420                 trm[0].node = l;
421         }
422         /*
423          * look for factorable terms
424          * c1*i + c1*c2*j -> c1*(i + c2*j)
425          */
426         qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp1);
427         for(i=nt-1; i>=0; i--) {
428                 c1 = trm[i].mult;
429                 if(c1 < 0)
430                         c1 = -c1;
431                 if(c1 <= 1)
432                         continue;
433                 for(j=i+1; j<nt; j++) {
434                         c2 = trm[j].mult;
435                         if(c2 < 0)
436                                 c2 = -c2;
437                         if(c2 <= 1)
438                                 continue;
439                         if(c2 % c1)
440                                 continue;
441                         r = trm[j].node;
442                         if(r->type->etype != et)
443                                 r = acast(t, r);
444                         c2 = trm[j].mult/trm[i].mult;
445                         if(c2 != 1 && c2 != -1) {
446                                 r = new1(OMUL, r, new(OCONST, Z, Z));
447                                 r->type = t;
448                                 r->right->type = t;
449                                 r->right->vconst = c2;
450                         }
451                         l = trm[i].node;
452                         if(l->type->etype != et)
453                                 l = acast(t, l);
454                         r = new1(OADD, l, r);
455                         r->type = t;
456                         if(c2 == -1)
457                                 r->op = OSUB;
458                         trm[i].node = r;
459                         trm[j].mult = 0;
460                 }
461         }
462         if(debug['m']) {
463                 print("\n");
464                 for(i=0; i<nt; i++) {
465                         print("%d %3lld ", i, trm[i].mult);
466                         prtree1(trm[i].node, 1, 0);
467                 }
468         }
469
470         /*
471          * put it all back together
472          */
473         qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp2);
474         l = Z;
475         for(i=nt-1; i>=0; i--) {
476                 c1 = trm[i].mult;
477                 if(c1 == 0)
478                         continue;
479                 r = trm[i].node;
480                 if(r->type->etype != et || r->op == OBIT)
481                         r = acast(t, r);
482                 if(c1 != 1 && c1 != -1) {
483                         r = new1(OMUL, r, new(OCONST, Z, Z));
484                         r->type = t;
485                         r->right->type = t;
486                         if(c1 < 0) {
487                                 r->right->vconst = -c1;
488                                 c1 = -1;
489                         } else {
490                                 r->right->vconst = c1;
491                                 c1 = 1;
492                         }
493                 }
494                 if(l == Z) {
495                         l = r;
496                         c2 = c1;
497                         continue;
498                 }
499                 if(c1 < 0)
500                         if(c2 < 0)
501                                 l = new1(OADD, l, r);
502                         else
503                                 l = new1(OSUB, l, r);
504                 else
505                         if(c2 < 0) {
506                                 l = new1(OSUB, r, l);
507                                 c2 = 1;
508                         } else
509                                 l = new1(OADD, l, r);
510                 l->type = t;
511         }
512         if(c2 < 0) {
513                 r = new1(OCONST, 0, 0);
514                 r->vconst = 0;
515                 r->type = t;
516                 l = new1(OSUB, r, l);
517                 l->type = t;
518         }
519         *n = *l;
520 }
521
522 void
523 acom1(vlong v, Node *n)
524 {
525         Node *l, *r;
526
527         if(v == 0 || nterm >= NTERM)
528                 return;
529         if(!addo(n)) {
530                 if(n->op == OCONST)
531                 if(!typefd[n->type->etype]) {
532                         term[0].mult += v*n->vconst;
533                         return;
534                 }
535                 term[nterm].mult = v;
536                 term[nterm].node = n;
537                 nterm++;
538                 return;
539         }
540         switch(n->op) {
541
542         case OCAST:
543                 acom1(v, n->left);
544                 break;
545
546         case ONEG:
547                 acom1(-v, n->left);
548                 break;
549
550         case OADD:
551                 acom1(v, n->left);
552                 acom1(v, n->right);
553                 break;
554
555         case OSUB:
556                 acom1(v, n->left);
557                 acom1(-v, n->right);
558                 break;
559
560         case OMUL:
561                 l = n->left;
562                 r = n->right;
563                 if(l->op == OCONST)
564                 if(!typefd[n->type->etype]) {
565                         acom1(v*l->vconst, r);
566                         break;
567                 }
568                 if(r->op == OCONST)
569                 if(!typefd[n->type->etype]) {
570                         acom1(v*r->vconst, l);
571                         break;
572                 }
573                 break;
574
575         default:
576                 diag(n, "not addo");
577         }
578 }
579
580 int
581 addo(Node *n)
582 {
583
584         if(n != Z)
585         if(!typefd[n->type->etype])
586         if(!typev[n->type->etype] || ewidth[TVLONG] == ewidth[TIND])
587         switch(n->op) {
588
589         case OCAST:
590                 if(nilcast(n->left->type, n->type))
591                         return 1;
592                 break;
593
594         case ONEG:
595         case OADD:
596         case OSUB:
597                 return 1;
598
599         case OMUL:
600                 if(n->left->op == OCONST)
601                         return 1;
602                 if(n->right->op == OCONST)
603                         return 1;
604         }
605         return 0;
606 }