]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/8c/sgen.c
awk: make empty FS unicodely-correct.
[plan9front.git] / sys / src / cmd / 8c / sgen.c
1 #include "gc.h"
2
3 void
4 noretval(int n)
5 {
6
7         if(n & 1) {
8                 gins(ANOP, Z, Z);
9                 p->to.type = REGRET;
10         }
11         if(n & 2) {
12                 gins(ANOP, Z, Z);
13                 p->to.type = FREGRET;
14         }
15         if((n&3) == 3)
16         if(thisfn && thisfn->link && typefd[thisfn->link->etype])
17                 gins(AFLDZ, Z, Z);
18 }
19
20 /* welcome to commute */
21 static void
22 commute(Node *n)
23 {
24         Node *l, *r;
25
26         l = n->left;
27         r = n->right;
28         if(r->complex > l->complex) {
29                 n->left = r;
30                 n->right = l;
31         }
32 }
33
34 void
35 indexshift(Node *n)
36 {
37         int g;
38
39         if(!typechlp[n->type->etype])
40                 return;
41         simplifyshift(n);
42         if(n->op == OASHL && n->right->op == OCONST){
43                 g = vconst(n->right);
44                 if(g >= 0 && g < 4)
45                         n->addable = 7;
46         }
47 }
48
49 /*
50  *      calculate addressability as follows
51  *              NAME ==> 10/11          name+value(SB/SP)
52  *              REGISTER ==> 12         register
53  *              CONST ==> 20            $value
54  *              *(20) ==> 21            value
55  *              &(10) ==> 13            $name+value(SB)
56  *              &(11) ==> 1             $name+value(SP)
57  *              (13) + (20) ==> 13      fold constants
58  *              (1) + (20) ==> 1        fold constants
59  *              *(13) ==> 10            back to name
60  *              *(1) ==> 11             back to name
61  *
62  *              (20) * (X) ==> 7        multiplier in indexing
63  *              (X,7) + (13,1) ==> 8    adder in indexing (addresses)
64  *              (8) ==> &9(OINDEX)      index, almost addressable
65  *
66  *      calculate complexity (number of registers)
67  */
68 void
69 xcom(Node *n)
70 {
71         Node *l, *r;
72         int g;
73
74         if(n == Z)
75                 return;
76         l = n->left;
77         r = n->right;
78         n->complex = 0;
79         n->addable = 0;
80         switch(n->op) {
81         case OCONST:
82                 n->addable = 20;
83                 break;
84
85         case ONAME:
86                 n->addable = 10;
87                 if(n->class == CPARAM || n->class == CAUTO)
88                         n->addable = 11;
89                 break;
90
91         case OEXREG:
92                 n->addable = 12;
93                 break;
94
95         case OREGISTER:
96                 n->addable = 12;
97                 break;
98
99         case OINDREG:
100                 n->addable = 12;
101                 break;
102
103         case OADDR:
104                 xcom(l);
105                 if(l->addable == 10)
106                         n->addable = 13;
107                 else
108                 if(l->addable == 11)
109                         n->addable = 1;
110                 break;
111
112         case OADD:
113                 xcom(l);
114                 xcom(r);
115                 if(n->type->etype != TIND &&
116                    !(l->type->etype == TIND && r->type->etype == TIND))
117                         break;
118
119                 switch(r->addable) {
120                 case 20:
121                         switch(l->addable) {
122                         case 1:
123                         case 13:
124                         commadd:
125                                 l->type = n->type;
126                                 *n = *l;
127                                 l = new(0, Z, Z);
128                                 *l = *(n->left);
129                                 l->xoffset += r->vconst;
130                                 n->left = l;
131                                 goto brk;
132                         }
133                         break;
134
135                 case 1:
136                 case 13:
137                 case 10:
138                 case 11:
139                         /* l is the base, r is the index */
140                         if(l->addable != 20)
141                                 n->addable = 8;
142                         break;
143                 }
144                 switch(l->addable) {
145                 case 20:
146                         switch(r->addable) {
147                         case 13:
148                         case 1:
149                                 r = n->left;
150                                 l = n->right;
151                                 n->left = l;
152                                 n->right = r;
153                                 goto commadd;
154                         }
155                         break;
156
157                 case 13:
158                 case 1:
159                 case 10:
160                 case 11:
161                         /* r is the base, l is the index */
162                         if(r->addable != 20)
163                                 n->addable = 8;
164                         break;
165                 }
166                 if(n->addable == 8 && !side(n)) {
167                         indx(n);
168                         l = new1(OINDEX, idx.basetree, idx.regtree);
169                         l->scale = idx.scale;
170                         l->addable = 9;
171                         l->complex = l->right->complex;
172                         if(l->complex == 0)
173                                 l->complex++;
174                         l->type = l->left->type;
175                         n->op = OADDR;
176                         n->left = l;
177                         n->right = Z;
178                         n->addable = 8;
179                         break;
180                 }
181                 break;
182
183         case OINDEX:
184                 xcom(l);
185                 xcom(r);
186                 n->addable = 9;
187                 break;
188
189         case OIND:
190                 xcom(l);
191                 if(l->op == OADDR) {
192                         l = l->left;
193                         l->type = n->type;
194                         *n = *l;
195                         return;
196                 }
197                 switch(l->addable) {
198                 case 20:
199                         n->addable = 21;
200                         break;
201                 case 1:
202                         n->addable = 11;
203                         break;
204                 case 13:
205                         n->addable = 10;
206                         break;
207                 }
208                 break;
209
210         case OASHL:
211                 xcom(l);
212                 xcom(r);
213                 indexshift(n);
214                 break;
215
216         case OMUL:
217         case OLMUL:
218                 xcom(l);
219                 xcom(r);
220                 g = vlog(l);
221                 if(g >= 0) {
222                         n->left = r;
223                         n->right = l;
224                         r = n->right;
225                 }
226                 g = vlog(r);
227                 if(g >= 0) {
228                         n->op = OASHL;
229                         r->vconst = g;
230                         r->type = types[TINT];
231                         indexshift(n);
232                         break;
233                 }
234                 commute(n);
235                 break;
236
237         case OASLDIV:
238                 xcom(l);
239                 xcom(r);
240                 g = vlog(r);
241                 if(g >= 0) {
242                         n->op = OASLSHR;
243                         r->vconst = g;
244                         r->type = types[TINT];
245                 }
246                 break;
247
248         case OLDIV:
249                 xcom(l);
250                 xcom(r);
251                 g = vlog(r);
252                 if(g >= 0) {
253                         n->op = OLSHR;
254                         r->vconst = g;
255                         r->type = types[TINT];
256                         indexshift(n);
257                         break;
258                 }
259                 break;
260
261         case OASLMOD:
262                 xcom(l);
263                 xcom(r);
264                 g = vlog(r);
265                 if(g >= 0) {
266                         n->op = OASAND;
267                         r->vconst--;
268                 }
269                 break;
270
271         case OLMOD:
272                 xcom(l);
273                 xcom(r);
274                 g = vlog(r);
275                 if(g >= 0) {
276                         n->op = OAND;
277                         r->vconst--;
278                 }
279                 break;
280
281         case OASMUL:
282         case OASLMUL:
283                 xcom(l);
284                 xcom(r);
285                 g = vlog(r);
286                 if(g >= 0) {
287                         n->op = OASASHL;
288                         r->vconst = g;
289                 }
290                 break;
291
292         case OLSHR:
293         case OASHR:
294                 xcom(l);
295                 xcom(r);
296                 indexshift(n);
297                 break;
298
299         case OOR:
300                 xcom(l);
301                 xcom(r);
302                 if(typechl[n->type->etype])
303                         rolor(n);
304                 break;
305
306         default:
307                 if(l != Z)
308                         xcom(l);
309                 if(r != Z)
310                         xcom(r);
311                 break;
312         }
313 brk:
314         if(n->addable >= 10)
315                 return;
316         l = n->left;
317         r = n->right;
318         if(l != Z)
319                 n->complex = l->complex;
320         if(r != Z) {
321                 if(r->complex == n->complex)
322                         n->complex = r->complex+1;
323                 else
324                 if(r->complex > n->complex)
325                         n->complex = r->complex;
326         }
327         if(n->complex == 0)
328                 n->complex++;
329
330         if(com64(n))
331                 return;
332
333         switch(n->op) {
334
335         case OFUNC:
336                 n->complex = FNX;
337                 break;
338
339         case OLMOD:
340         case OMOD:
341         case OLMUL:
342         case OLDIV:
343         case OMUL:
344         case ODIV:
345         case OASLMUL:
346         case OASLDIV:
347         case OASLMOD:
348         case OASMUL:
349         case OASDIV:
350         case OASMOD:
351                 if(r->complex >= l->complex) {
352                         n->complex = l->complex + 3;
353                         if(r->complex > n->complex)
354                                 n->complex = r->complex;
355                 } else {
356                         n->complex = r->complex + 3;
357                         if(l->complex > n->complex)
358                                 n->complex = l->complex;
359                 }
360                 break;
361
362         case OROL:
363         case OLSHR:
364         case OASHL:
365         case OASHR:
366         case OASLSHR:
367         case OASASHL:
368         case OASASHR:
369                 if(r->complex >= l->complex) {
370                         n->complex = l->complex + 2;
371                         if(r->complex > n->complex)
372                                 n->complex = r->complex;
373                 } else {
374                         n->complex = r->complex + 2;
375                         if(l->complex > n->complex)
376                                 n->complex = l->complex;
377                 }
378                 break;
379
380         case OADD:
381         case OXOR:
382         case OAND:
383         case OOR:
384                 /*
385                  * immediate operators, make const on right
386                  */
387                 if(l->op == OCONST) {
388                         n->left = r;
389                         n->right = l;
390                 }
391                 break;
392
393         case OEQ:
394         case ONE:
395         case OLE:
396         case OLT:
397         case OGE:
398         case OGT:
399         case OHI:
400         case OHS:
401         case OLO:
402         case OLS:
403                 /*
404                  * compare operators, make const on left
405                  */
406                 if(r->op == OCONST) {
407                         n->left = r;
408                         n->right = l;
409                         n->op = invrel[relindex(n->op)];
410                 }
411                 break;
412         }
413 }
414
415 void
416 indx(Node *n)
417 {
418         Node *l, *r;
419
420         if(debug['x'])
421                 prtree(n, "indx");
422
423         l = n->left;
424         r = n->right;
425         if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
426                 n->right = l;
427                 n->left = r;
428                 l = r;
429                 r = n->right;
430         }
431         if(l->addable != 7) {
432                 idx.regtree = l;
433                 idx.scale = 1;
434         } else
435         if(l->right->addable == 20) {
436                 idx.regtree = l->left;
437                 idx.scale = 1 << l->right->vconst;
438         } else
439         if(l->left->addable == 20) {
440                 idx.regtree = l->right;
441                 idx.scale = 1 << l->left->vconst;
442         } else
443                 diag(n, "bad index");
444
445         idx.basetree = r;
446         if(debug['x']) {
447                 print("scale = %d\n", idx.scale);
448                 prtree(idx.regtree, "index");
449                 prtree(idx.basetree, "base");
450         }
451 }