Pristine Ack-5.5
[Ack-5.5.git] / mach / proto / cg / compute.c
1 #ifndef NORCSID
2 static char rcsid[] = "$Id: compute.c,v 2.4 1994/06/24 13:23:22 ceriel Exp $";
3 #endif
4
5 #include "assert.h"
6 #include "param.h"
7 #include "tables.h"
8 #include "types.h"
9 #include <cg_pattern.h>
10 #include "data.h"
11 #include "result.h"
12 #include "glosym.h"
13 #include "extern.h"
14
15 /*
16  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
17  * See the copyright notice in the ACK home directory, in the file "Copyright".
18  *
19  * Author: Hans van Staveren
20  */
21
22 #define LLEAF 01
23 #define LDEF  02
24 #define RLEAF 04
25 #define RDEF  010
26 #define LLDEF LLEAF|LDEF
27 #define RLDEF RLEAF|RDEF
28
29 char opdesc[] = {
30         0,                      /* EX_TOKFIELD */
31         0,                      /* EX_ARG */
32         0,                      /* EX_CON */
33         0,                      /* EX_ALLREG */
34         LLDEF|RLDEF,            /* EX_SAMESIGN */
35         LLDEF|RLDEF,            /* EX_SFIT */
36         LLDEF|RLDEF,            /* EX_UFIT */
37         0,                      /* EX_ROM */
38         LLDEF|RLDEF,            /* EX_NCPEQ */
39         LLDEF|RLDEF,            /* EX_SCPEQ */
40         LLDEF|RLDEF,            /* EX_RCPEQ */
41         LLDEF|RLDEF,            /* EX_NCPNE */
42         LLDEF|RLDEF,            /* EX_SCPNE */
43         LLDEF|RLDEF,            /* EX_RCPNE */
44         LLDEF|RLDEF,            /* EX_NCPGT */
45         LLDEF|RLDEF,            /* EX_NCPGE */
46         LLDEF|RLDEF,            /* EX_NCPLT */
47         LLDEF|RLDEF,            /* EX_NCPLE */
48         LLDEF,                  /* EX_OR2 */
49         LLDEF,                  /* EX_AND2 */
50         LLDEF|RLDEF,            /* EX_PLUS */
51         LLDEF|RLDEF,            /* EX_CAT */
52         LLDEF|RLDEF,            /* EX_MINUS */
53         LLDEF|RLDEF,            /* EX_TIMES */
54         LLDEF|RLDEF,            /* EX_DIVIDE */
55         LLDEF|RLDEF,            /* EX_MOD */
56         LLDEF|RLDEF,            /* EX_LSHIFT */
57         LLDEF|RLDEF,            /* EX_RSHIFT */
58         LLDEF,                  /* EX_NOT */
59         LLDEF,                  /* EX_COMP */
60         0,                      /* EX_COST */
61         0,                      /* EX_STRING */
62         LLEAF,                  /* EX_DEFINED */
63         0,                      /* EX_SUBREG */
64         LLDEF,                  /* EX_TOSTRING */
65         LLDEF,                  /* EX_UMINUS */
66         0,                      /* EX_REG */
67         0,                      /* EX_LOWW */
68         0,                      /* EX_HIGHW */
69         LLDEF,                  /* EX_INREG */
70         LLDEF,                  /* EX_REGVAR */
71 };
72
73 string salloc(),strcpy(),strcat();
74
75 string mycat(s1,s2) string s1,s2; {
76         register string s;
77
78         s=salloc(strlen(s1)+strlen(s2));
79         strcpy(s,s1);
80         strcat(s,s2);
81         return(s);
82 }
83
84 string mystrcpy(s) string s; {
85         register string r;
86
87         r=salloc(strlen(s));
88         strcpy(r,s);
89         return(r);
90 }
91
92 char digstr[21][15];
93
94 string tostring(n) word n; {
95         char buf[25];
96
97         if (n>=-20 && n<=20 && (n&1)==0) {
98                 if (digstr[(n>>1)+10][0]==0)
99                         sprintf(digstr[(n>>1)+10],WRD_FMT,n);
100                 return(digstr[(n>>1)+10]);
101         }
102         sprintf(buf,WRD_FMT,n);
103         return(mystrcpy(buf));
104 }
105
106 result_t undefres= {EV_UNDEF};
107
108 result_t compute(node) register node_p node; {
109         result_t leaf1,leaf2,result;
110         token_p tp;
111         int desc;
112         long mask,tmp;
113         int i,tmpreg;
114         glosym_p gp;
115
116         desc=opdesc[node->ex_operator];
117         if (desc&LLEAF) {
118                 leaf1 = compute(&enodes[node->ex_lnode]);
119                 if (desc&LDEF && leaf1.e_typ==EV_UNDEF)
120                         return(undefres);
121         }
122         if (desc&RLEAF) {
123                 leaf2 = compute(&enodes[node->ex_rnode]);
124                 if (desc&RDEF && leaf2.e_typ==EV_UNDEF)
125                         return(undefres);
126         }
127         result.e_typ=EV_INT;
128         switch(node->ex_operator) {
129         default:        assert(FALSE);
130         case EX_TOKFIELD:
131                 if (node->ex_lnode!=0)
132                         tp = &fakestack[stackheight-node->ex_lnode];
133                 else
134                         tp = curtoken;
135                 switch(result.e_typ = tokens[tp->t_token].t_type[node->ex_rnode-1]) {
136                 default:
137                         assert(FALSE);
138                 case EV_INT:
139                         result.e_v.e_con = tp->t_att[node->ex_rnode-1].aw;
140                         break;
141                 case EV_STR:
142                         result.e_v.e_str = tp->t_att[node->ex_rnode-1].as;
143                         break;
144                 case EV_REG:
145                         result.e_v.e_reg = tp->t_att[node->ex_rnode-1].ar;
146                         break;
147                 }
148                 return(result);
149         case EX_ARG:
150                 return(dollar[node->ex_lnode-1]);
151         case EX_CON:
152                 result.e_typ = EV_INT;
153                 result.e_v.e_con = ((long) node->ex_rnode << 16) | ((long)node->ex_lnode&0xffff);
154                 return(result);
155         case EX_REG:
156                 result.e_typ = EV_REG;
157                 result.e_v.e_reg = node->ex_lnode;
158                 return(result);
159         case EX_ALLREG:
160                 result.e_typ = EV_REG;
161                 result.e_v.e_reg = allreg[node->ex_lnode-1];
162 #if MAXMEMBERS!=0
163                 if (node->ex_rnode!=0)
164                         result.e_v.e_reg = machregs[result.e_v.e_reg].
165                                 r_members[node->ex_rnode-1];
166 #endif
167                 return(result);
168         case EX_SAMESIGN:
169         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
170                 result.e_typ = EV_INT;
171                 if (leaf1.e_v.e_con>=0)
172                         result.e_v.e_con= leaf2.e_v.e_con>=0;
173                 else
174                         result.e_v.e_con= leaf2.e_v.e_con<0;
175                 return(result);
176         case EX_SFIT:
177         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
178                 mask = 0xFFFFFFFFL;
179                 for (i=0;i<leaf2.e_v.e_con-1;i++)
180                         mask &= ~(1<<i);
181                 tmp = leaf1.e_v.e_con&mask;
182                 result.e_v.e_con = tmp==0||tmp==mask;
183                 return(result);
184         case EX_UFIT:
185         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
186                 mask = 0xFFFFFFFFL;
187                 for (i=0;i<leaf2.e_v.e_con;i++)
188                         mask &= ~(1<<i);
189                 result.e_v.e_con = (leaf1.e_v.e_con&mask)==0;
190                 return(result);
191         case EX_ROM:
192                 assert(node->ex_rnode>=0 &&node->ex_rnode<MAXROM);
193                 leaf2=dollar[node->ex_lnode];
194                 if (leaf2.e_typ != EV_STR)
195                         return(undefres);
196                 gp = lookglo(leaf2.e_v.e_str);
197                 if (gp == (glosym_p) 0)
198                         return(undefres);
199                 if ((gp->gl_rom[MAXROM]&(1<<node->ex_rnode))==0)
200                         return(undefres);
201                 result.e_v.e_con = gp->gl_rom[node->ex_rnode];
202                 return(result);
203         case EX_LOWW:
204                 result.e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper&0xFFFF;
205                 return(result);
206         case EX_HIGHW:
207                 result.e_v.e_con = saveemp[node->ex_lnode].em_u.em_loper>>16;
208                 return(result);
209         case EX_NCPEQ:
210         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
211                 result.e_v.e_con = leaf1.e_v.e_con==leaf2.e_v.e_con;
212                 return(result);
213         case EX_SCPEQ:
214         assert(leaf1.e_typ == EV_STR && leaf2.e_typ == EV_STR);
215                 result.e_v.e_con = !strcmp(leaf1.e_v.e_str,leaf2.e_v.e_str);
216                 return(result);
217         case EX_RCPEQ:
218         assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG);
219                 result.e_v.e_con = leaf1.e_v.e_reg==leaf2.e_v.e_reg;
220                 return(result);
221         case EX_NCPNE:
222         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
223                 result.e_v.e_con = leaf1.e_v.e_con!=leaf2.e_v.e_con;
224                 return(result);
225         case EX_SCPNE:
226         assert(leaf1.e_typ == EV_STR && leaf2.e_typ == EV_STR);
227                 result.e_v.e_con = strcmp(leaf1.e_v.e_str,leaf2.e_v.e_str);
228                 return(result);
229         case EX_RCPNE:
230         assert(leaf1.e_typ == EV_REG && leaf2.e_typ == EV_REG);
231                 result.e_v.e_con = leaf1.e_v.e_reg!=leaf2.e_v.e_reg;
232                 return(result);
233         case EX_NCPGT:
234         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
235                 result.e_v.e_con = leaf1.e_v.e_con>leaf2.e_v.e_con;
236                 return(result);
237         case EX_NCPGE:
238         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
239                 result.e_v.e_con = leaf1.e_v.e_con>=leaf2.e_v.e_con;
240                 return(result);
241         case EX_NCPLT:
242         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
243                 result.e_v.e_con = leaf1.e_v.e_con<leaf2.e_v.e_con;
244                 return(result);
245         case EX_NCPLE:
246         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
247                 result.e_v.e_con = leaf1.e_v.e_con<=leaf2.e_v.e_con;
248                 return(result);
249         case EX_OR2:
250         assert(leaf1.e_typ == EV_INT);
251                 if (leaf1.e_v.e_con==0)
252                         return(compute(&enodes[node->ex_rnode]));
253                 return(leaf1);
254         case EX_AND2:
255         assert(leaf1.e_typ == EV_INT);
256                 if (leaf1.e_v.e_con!=0)
257                         return(compute(&enodes[node->ex_rnode]));
258                 return(leaf1);
259         case EX_PLUS:
260         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
261                 result.e_v.e_con=leaf1.e_v.e_con+leaf2.e_v.e_con;
262                 return(result);
263         case EX_CAT:
264         assert(leaf1.e_typ == EV_STR && leaf2.e_typ == EV_STR);
265                 result.e_typ = EV_STR;
266                 result.e_v.e_str = mycat(leaf1.e_v.e_str,leaf2.e_v.e_str);
267                 return(result);
268         case EX_MINUS:
269         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
270                 result.e_v.e_con = leaf1.e_v.e_con - leaf2.e_v.e_con;
271                 return(result);
272         case EX_TIMES:
273         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
274                 result.e_v.e_con = leaf1.e_v.e_con * leaf2.e_v.e_con;
275                 return(result);
276         case EX_DIVIDE:
277         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
278                 result.e_v.e_con = leaf1.e_v.e_con / leaf2.e_v.e_con;
279                 return(result);
280         case EX_MOD:
281         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
282                 result.e_v.e_con = leaf1.e_v.e_con % leaf2.e_v.e_con;
283                 return(result);
284         case EX_LSHIFT:
285         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
286                 result.e_v.e_con = leaf1.e_v.e_con << leaf2.e_v.e_con;
287                 return(result);
288         case EX_RSHIFT:
289         assert(leaf1.e_typ == EV_INT && leaf2.e_typ == EV_INT);
290                 result.e_v.e_con = leaf1.e_v.e_con >> leaf2.e_v.e_con;
291                 return(result);
292         case EX_NOT:
293         assert(leaf1.e_typ == EV_INT);
294                 result.e_v.e_con = !leaf1.e_v.e_con;
295                 return(result);
296         case EX_COMP:
297         assert(leaf1.e_typ == EV_INT);
298                 result.e_v.e_con = ~leaf1.e_v.e_con;
299                 return(result);
300         case EX_COST:
301                 if (node->ex_rnode==0)
302                         return(compute(&enodes[tokens[node->ex_lnode].t_cost.c_size]));
303                 else
304                         return(compute(&enodes[tokens[node->ex_lnode].t_cost.c_time]));
305         case EX_STRING:
306                 result.e_typ = EV_STR;
307                 result.e_v.e_str = codestrings[node->ex_lnode];
308                 return(result);
309         case EX_DEFINED:
310                 result.e_v.e_con=leaf1.e_typ!=EV_UNDEF;
311                 return(result);
312         case EX_SUBREG:
313                 result.e_typ = EV_REG;
314                 tp= &fakestack[stackheight-node->ex_lnode];
315                 assert(tp->t_token == -1);
316                 tmpreg= tp->t_att[0].ar;
317 #if MAXMEMBERS!=0
318                 if (node->ex_rnode)
319                         tmpreg=machregs[tmpreg].r_members[node->ex_rnode-1];
320 #endif
321                 result.e_v.e_reg=tmpreg;
322                 return(result);
323         case EX_TOSTRING:
324         assert(leaf1.e_typ == EV_INT);
325                 result.e_typ = EV_STR;
326                 result.e_v.e_str = tostring(leaf1.e_v.e_con);
327                 return(result);
328 #ifdef REGVARS
329         case EX_INREG:
330         assert(leaf1.e_typ == EV_INT);
331                 i = isregvar((long) leaf1.e_v.e_con);
332                 if (i<0)
333                         result.e_v.e_con = 0;
334                 else if (i==0)
335                         result.e_v.e_con = 1;
336                 else
337                         result.e_v.e_con = 2;
338                 return(result);
339         case EX_REGVAR:
340         assert(leaf1.e_typ == EV_INT);
341                 i = isregvar((long) leaf1.e_v.e_con);
342                 if (i<=0) 
343                         return(undefres);
344                 result.e_typ = EV_REG;
345                 result.e_v.e_reg=i;
346                 return(result);
347 #endif
348         case EX_UMINUS:
349         assert(leaf1.e_typ == EV_INT);
350                 result.e_v.e_con = -leaf1.e_v.e_con;
351                 return(result);
352         }
353 }