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