]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/8c/sgen.c
6c, 8c: Fix nocast cast bug which prevents address arithmetic from being computed...
[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                         l->type = l->left->type;
173                         n->op = OADDR;
174                         n->left = l;
175                         n->right = Z;
176                         n->addable = 8;
177                         break;
178                 }
179                 break;
180
181         case OINDEX:
182                 xcom(l);
183                 xcom(r);
184                 n->addable = 9;
185                 break;
186
187         case OIND:
188                 xcom(l);
189                 if(l->op == OADDR) {
190                         l = l->left;
191                         l->type = n->type;
192                         *n = *l;
193                         return;
194                 }
195                 switch(l->addable) {
196                 case 20:
197                         n->addable = 21;
198                         break;
199                 case 1:
200                         n->addable = 11;
201                         break;
202                 case 13:
203                         n->addable = 10;
204                         break;
205                 }
206                 break;
207
208         case OASHL:
209                 xcom(l);
210                 xcom(r);
211                 indexshift(n);
212                 break;
213
214         case OMUL:
215         case OLMUL:
216                 xcom(l);
217                 xcom(r);
218                 g = vlog(l);
219                 if(g >= 0) {
220                         n->left = r;
221                         n->right = l;
222                         r = n->right;
223                 }
224                 g = vlog(r);
225                 if(g >= 0) {
226                         n->op = OASHL;
227                         r->vconst = g;
228                         r->type = types[TINT];
229                         indexshift(n);
230                         break;
231                 }
232                 commute(n);
233                 break;
234
235         case OASLDIV:
236                 xcom(l);
237                 xcom(r);
238                 g = vlog(r);
239                 if(g >= 0) {
240                         n->op = OASLSHR;
241                         r->vconst = g;
242                         r->type = types[TINT];
243                 }
244                 break;
245
246         case OLDIV:
247                 xcom(l);
248                 xcom(r);
249                 g = vlog(r);
250                 if(g >= 0) {
251                         n->op = OLSHR;
252                         r->vconst = g;
253                         r->type = types[TINT];
254                         indexshift(n);
255                         break;
256                 }
257                 break;
258
259         case OASLMOD:
260                 xcom(l);
261                 xcom(r);
262                 g = vlog(r);
263                 if(g >= 0) {
264                         n->op = OASAND;
265                         r->vconst--;
266                 }
267                 break;
268
269         case OLMOD:
270                 xcom(l);
271                 xcom(r);
272                 g = vlog(r);
273                 if(g >= 0) {
274                         n->op = OAND;
275                         r->vconst--;
276                 }
277                 break;
278
279         case OASMUL:
280         case OASLMUL:
281                 xcom(l);
282                 xcom(r);
283                 g = vlog(r);
284                 if(g >= 0) {
285                         n->op = OASASHL;
286                         r->vconst = g;
287                 }
288                 break;
289
290         case OLSHR:
291         case OASHR:
292                 xcom(l);
293                 xcom(r);
294                 indexshift(n);
295                 break;
296
297         case OOR:
298                 xcom(l);
299                 xcom(r);
300                 if(typechl[n->type->etype])
301                         rolor(n);
302                 break;
303
304         default:
305                 if(l != Z)
306                         xcom(l);
307                 if(r != Z)
308                         xcom(r);
309                 break;
310         }
311 brk:
312         if(n->addable >= 10)
313                 return;
314         l = n->left;
315         r = n->right;
316         if(l != Z)
317                 n->complex = l->complex;
318         if(r != Z) {
319                 if(r->complex == n->complex)
320                         n->complex = r->complex+1;
321                 else
322                 if(r->complex > n->complex)
323                         n->complex = r->complex;
324         }
325         if(n->complex == 0)
326                 n->complex++;
327
328         if(com64(n))
329                 return;
330
331         switch(n->op) {
332
333         case OFUNC:
334                 n->complex = FNX;
335                 break;
336
337         case OLMOD:
338         case OMOD:
339         case OLMUL:
340         case OLDIV:
341         case OMUL:
342         case ODIV:
343         case OASLMUL:
344         case OASLDIV:
345         case OASLMOD:
346         case OASMUL:
347         case OASDIV:
348         case OASMOD:
349                 if(r->complex >= l->complex) {
350                         n->complex = l->complex + 3;
351                         if(r->complex > n->complex)
352                                 n->complex = r->complex;
353                 } else {
354                         n->complex = r->complex + 3;
355                         if(l->complex > n->complex)
356                                 n->complex = l->complex;
357                 }
358                 break;
359
360         case OROL:
361         case OLSHR:
362         case OASHL:
363         case OASHR:
364         case OASLSHR:
365         case OASASHL:
366         case OASASHR:
367                 if(r->complex >= l->complex) {
368                         n->complex = l->complex + 2;
369                         if(r->complex > n->complex)
370                                 n->complex = r->complex;
371                 } else {
372                         n->complex = r->complex + 2;
373                         if(l->complex > n->complex)
374                                 n->complex = l->complex;
375                 }
376                 break;
377
378         case OADD:
379         case OXOR:
380         case OAND:
381         case OOR:
382                 /*
383                  * immediate operators, make const on right
384                  */
385                 if(l->op == OCONST) {
386                         n->left = r;
387                         n->right = l;
388                 }
389                 break;
390
391         case OEQ:
392         case ONE:
393         case OLE:
394         case OLT:
395         case OGE:
396         case OGT:
397         case OHI:
398         case OHS:
399         case OLO:
400         case OLS:
401                 /*
402                  * compare operators, make const on left
403                  */
404                 if(r->op == OCONST) {
405                         n->left = r;
406                         n->right = l;
407                         n->op = invrel[relindex(n->op)];
408                 }
409                 break;
410         }
411 }
412
413 void
414 indx(Node *n)
415 {
416         Node *l, *r;
417
418         if(debug['x'])
419                 prtree(n, "indx");
420
421         l = n->left;
422         r = n->right;
423         if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
424                 n->right = l;
425                 n->left = r;
426                 l = r;
427                 r = n->right;
428         }
429         if(l->addable != 7) {
430                 idx.regtree = l;
431                 idx.scale = 1;
432         } else
433         if(l->right->addable == 20) {
434                 idx.regtree = l->left;
435                 idx.scale = 1 << l->right->vconst;
436         } else
437         if(l->left->addable == 20) {
438                 idx.regtree = l->right;
439                 idx.scale = 1 << l->left->vconst;
440         } else
441                 diag(n, "bad index");
442
443         idx.basetree = r;
444         if(debug['x']) {
445                 print("scale = %d\n", idx.scale);
446                 prtree(idx.regtree, "index");
447                 prtree(idx.basetree, "base");
448         }
449 }