Commit | Line | Data |
---|---|---|
d428e572 SJ |
1 | # include "mfile2" |
2 | ||
3 | ||
4 | int fldsz, fldshf; | |
5 | ||
6 | static int mamask[] = { /* masks for matching dope with shapes */ | |
7 | SIMPFLG, /* OPSIMP */ | |
8 | SIMPFLG|ASGFLG, /* ASG OPSIMP */ | |
9 | COMMFLG, /* OPCOMM */ | |
10 | COMMFLG|ASGFLG, /* ASG OPCOMM */ | |
11 | MULFLG, /* OPMUL */ | |
12 | MULFLG|ASGFLG, /* ASG OPMUL */ | |
13 | DIVFLG, /* OPDIV */ | |
14 | DIVFLG|ASGFLG, /* ASG OPDIV */ | |
15 | UTYPE, /* OPUNARY */ | |
16 | TYFLG, /* ASG OPUNARY is senseless */ | |
17 | LTYPE, /* OPLEAF */ | |
18 | TYFLG, /* ASG OPLEAF is senseless */ | |
19 | 0, /* OPANY */ | |
20 | ASGOPFLG|ASGFLG, /* ASG OPANY */ | |
21 | LOGFLG, /* OPLOG */ | |
22 | TYFLG, /* ASG OPLOG is senseless */ | |
23 | FLOFLG, /* OPFLOAT */ | |
24 | FLOFLG|ASGFLG, /* ASG OPFLOAT */ | |
25 | SHFFLG, /* OPSHFT */ | |
26 | SHFFLG|ASGFLG, /* ASG OPSHIFT */ | |
27 | SPFLG, /* OPLTYPE */ | |
28 | TYFLG, /* ASG OPLTYPE is senseless */ | |
29 | }; | |
30 | ||
31 | int sdebug = 0; | |
32 | ||
33 | tshape( p, shape ) NODE *p; { | |
34 | /* return true if shape is appropriate for the node p | |
35 | side effect for SFLD is to set up fldsz,etc */ | |
36 | register o, mask; | |
37 | ||
38 | o = p->op; | |
39 | ||
40 | if( sdebug ){ | |
41 | printf( "tshape( %o, %o), op = %d\n", p, shape, o ); | |
42 | } | |
43 | ||
44 | if( shape & SPECIAL ){ | |
45 | ||
46 | switch( shape ){ | |
47 | ||
48 | case SZERO: | |
49 | case SONE: | |
50 | case SMONE: | |
51 | if( o != ICON || p->name[0] ) return(0); | |
52 | if( p->lval == 0 && shape == SZERO ) return(1); | |
53 | else if( p->lval == 1 && shape == SONE ) return(1); | |
54 | else if( p->lval == -1 && shape == SMONE ) return(1); | |
55 | else return(0); | |
56 | ||
57 | default: | |
58 | return( special( p, shape ) ); | |
59 | } | |
60 | } | |
61 | ||
62 | if( shape & SANY ) return(1); | |
63 | ||
64 | if( (shape&INTEMP) && shtemp(p) ) return(1); | |
65 | ||
66 | if( (shape&SWADD) && (o==NAME||o==OREG) ){ | |
67 | if( BYTEOFF(p->lval) ) return(0); | |
68 | } | |
69 | ||
70 | switch( o ){ | |
71 | ||
72 | case NAME: | |
73 | return( shape&SNAME ); | |
74 | case ICON: | |
75 | mask = SCON; | |
76 | return( shape & mask ); | |
77 | ||
78 | case FLD: | |
79 | if( shape & SFLD ){ | |
80 | if( !flshape( p->left ) ) return(0); | |
81 | /* it is a FIELD shape; make side-effects */ | |
82 | o = p->rval; | |
83 | fldsz = UPKFSZ(o); | |
84 | # ifdef RTOLBYTES | |
85 | fldshf = UPKFOFF(o); | |
86 | # else | |
87 | fldshf = SZINT - fldsz - UPKFOFF(o); | |
88 | # endif | |
89 | return(1); | |
90 | } | |
91 | return(0); | |
92 | ||
93 | case CCODES: | |
94 | return( shape&SCC ); | |
95 | ||
96 | case REG: | |
97 | /* distinctions: | |
98 | SAREG any scalar register | |
99 | STAREG any temporary scalar register | |
100 | SBREG any lvalue (index) register | |
101 | STBREG any temporary lvalue register | |
102 | */ | |
103 | mask = isbreg( p->rval ) ? SBREG : SAREG; | |
104 | if( istreg( p->rval ) && busy[p->rval]<=1 ) mask |= mask==SAREG ? STAREG : STBREG; | |
105 | return( shape & mask ); | |
106 | ||
107 | case OREG: | |
108 | return( shape & SOREG ); | |
109 | ||
110 | case UNARY MUL: | |
111 | /* return STARNM or STARREG or 0 */ | |
112 | return( shumul(p->left) & shape ); | |
113 | ||
114 | } | |
115 | ||
116 | return(0); | |
117 | } | |
118 | ||
119 | int tdebug = 0; | |
120 | ||
121 | ttype( t, tword ) TWORD t; { | |
122 | /* does the type t match tword */ | |
123 | ||
124 | if( tword & TANY ) return(1); | |
125 | ||
126 | if( tdebug ){ | |
127 | printf( "ttype( %o, %o )\n", t, tword ); | |
128 | } | |
129 | if( ISPTR(t) && (tword&TPTRTO) ) { | |
130 | do { | |
131 | t = DECREF(t); | |
132 | } while ( ISARY(t) ); | |
133 | /* arrays that are left are usually only | |
134 | in structure references... */ | |
135 | return( ttype( t, tword&(~TPTRTO) ) ); | |
136 | } | |
137 | if( t != BTYPE(t) ) return( tword & TPOINT ); /* TPOINT means not simple! */ | |
138 | if( tword & TPTRTO ) return(0); | |
139 | ||
140 | switch( t ){ | |
141 | ||
142 | case CHAR: | |
143 | return( tword & TCHAR ); | |
144 | case SHORT: | |
145 | return( tword & TSHORT ); | |
146 | case STRTY: | |
147 | case UNIONTY: | |
148 | return( tword & TSTRUCT ); | |
149 | case INT: | |
150 | return( tword & TINT ); | |
151 | case UNSIGNED: | |
152 | return( tword & TUNSIGNED ); | |
153 | case USHORT: | |
154 | return( tword & TUSHORT ); | |
155 | case UCHAR: | |
156 | return( tword & TUCHAR ); | |
157 | case ULONG: | |
158 | return( tword & TULONG ); | |
159 | case LONG: | |
160 | return( tword & TLONG ); | |
161 | case FLOAT: | |
162 | return( tword & TFLOAT ); | |
163 | case DOUBLE: | |
164 | return( tword & TDOUBLE ); | |
165 | } | |
166 | ||
167 | return(0); | |
168 | } | |
169 | ||
170 | struct optab *rwtable; | |
171 | ||
172 | struct optab *opptr[DSIZE]; | |
173 | ||
174 | setrew(){ | |
175 | /* set rwtable to first value which allows rewrite */ | |
176 | register struct optab *q; | |
177 | register int i; | |
178 | ||
179 | for( q = table; q->op != FREE; ++q ){ | |
180 | if( q->needs == REWRITE ){ | |
181 | rwtable = q; | |
182 | goto more; | |
183 | } | |
184 | } | |
185 | cerror( "bad setrew" ); | |
186 | ||
187 | ||
188 | more: | |
189 | for( i=0; i<DSIZE; ++i ){ | |
190 | if( dope[i] ){ /* there is an op... */ | |
191 | for( q=table; q->op != FREE; ++q ){ | |
192 | /* beware; things like LTYPE that match | |
193 | multiple things in the tree must | |
194 | not try to look at the NIL at this | |
195 | stage of things! Put something else | |
196 | first in table.c */ | |
197 | /* at one point, the operator matching was 15% of the | |
198 | total comile time; thus, the function | |
199 | call that was here was removed... | |
200 | */ | |
201 | ||
202 | if( q->op < OPSIMP ){ | |
203 | if( q->op==i ) break; | |
204 | } | |
205 | else { | |
206 | register opmtemp; | |
207 | if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){ | |
208 | if( i==NAME || i==ICON || i==OREG ) break; | |
209 | else if( shltype( i, NIL ) ) break; | |
210 | } | |
211 | else if( (dope[i]&(opmtemp|ASGFLG)) == opmtemp ) break; | |
212 | } | |
213 | } | |
214 | opptr[i] = q; | |
215 | } | |
216 | } | |
217 | } | |
218 | ||
219 | match( p, cookie ) NODE *p; { | |
220 | /* called by: order, gencall | |
221 | look for match in table and generate code if found unless | |
222 | entry specified REWRITE. | |
223 | returns MDONE, MNOPE, or rewrite specification from table */ | |
224 | ||
225 | register struct optab *q; | |
226 | register NODE *r; | |
227 | ||
228 | rcount(); | |
229 | if( cookie == FORREW ) q = rwtable; | |
230 | else q = opptr[p->op]; | |
231 | ||
232 | for( ; q->op != FREE; ++q ){ | |
233 | ||
234 | /* at one point the call that was here was over 15% of the total time; | |
235 | thus the function call was expanded inline */ | |
236 | if( q->op < OPSIMP ){ | |
237 | if( q->op!=p->op ) continue; | |
238 | } | |
239 | else { | |
240 | register opmtemp; | |
241 | if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){ | |
242 | if( p->op!=NAME && p->op!=ICON && p->op!= OREG && | |
243 | ! shltype( p->op, p ) ) continue; | |
244 | } | |
245 | else if( (dope[p->op]&(opmtemp|ASGFLG)) != opmtemp ) continue; | |
246 | } | |
247 | ||
248 | if( !(q->visit & cookie ) ) continue; | |
249 | r = getlr( p, 'L' ); /* see if left child matches */ | |
250 | if( !tshape( r, q->lshape ) ) continue; | |
251 | if( !ttype( r->type, q->ltype ) ) continue; | |
252 | r = getlr( p, 'R' ); /* see if right child matches */ | |
253 | if( !tshape( r, q->rshape ) ) continue; | |
254 | if( !ttype( r->type, q->rtype ) ) continue; | |
255 | ||
256 | /* REWRITE means no code from this match but go ahead | |
257 | and rewrite node to help future match */ | |
258 | if( q->needs & REWRITE ) return( q->rewrite ); | |
259 | if( !allo( p, q ) ) continue; /* if can't generate code, skip entry */ | |
260 | ||
261 | /* resources are available */ | |
262 | ||
263 | expand( p, cookie, q->cstring ); /* generate code */ | |
264 | reclaim( p, q->rewrite, cookie ); | |
265 | ||
266 | return(MDONE); | |
267 | ||
268 | } | |
269 | ||
270 | return(MNOPE); | |
271 | } | |
272 | ||
273 | int rtyflg = 0; | |
274 | ||
275 | expand( p, cookie, cp ) NODE *p; register char *cp; { | |
276 | /* generate code by interpreting table entry */ | |
277 | ||
278 | CONSZ val; | |
279 | ||
280 | rtyflg = 0; | |
281 | ||
282 | for( ; *cp; ++cp ){ | |
283 | switch( *cp ){ | |
284 | ||
285 | default: | |
286 | PUTCHAR( *cp ); | |
287 | continue; /* this is the usual case... */ | |
288 | ||
289 | case 'T': | |
290 | /* rewrite register type is suppressed */ | |
291 | rtyflg = 1; | |
292 | continue; | |
293 | ||
294 | case 'Z': /* special machine dependent operations */ | |
295 | zzzcode( p, *++cp ); | |
296 | continue; | |
297 | ||
298 | case 'F': /* this line deleted if FOREFF is active */ | |
299 | if( cookie & FOREFF ) while( *++cp != '\n' ) ; /* VOID */ | |
300 | continue; | |
301 | ||
302 | case 'S': /* field size */ | |
303 | printf( "%d", fldsz ); | |
304 | continue; | |
305 | ||
306 | case 'H': /* field shift */ | |
307 | printf( "%d", fldshf ); | |
308 | continue; | |
309 | ||
310 | case 'M': /* field mask */ | |
311 | case 'N': /* complement of field mask */ | |
312 | val = 1; | |
313 | val <<= fldsz; | |
314 | --val; | |
315 | val <<= fldshf; | |
316 | adrcon( *cp=='M' ? val : ~val ); | |
317 | continue; | |
318 | ||
319 | case 'L': /* output special label field */ | |
320 | printf( "%d", p->label ); | |
321 | continue; | |
322 | ||
323 | case 'O': /* opcode string */ | |
324 | hopcode( *++cp, p->op ); | |
325 | continue; | |
326 | ||
327 | case 'B': /* byte offset in word */ | |
328 | val = getlr(p,*++cp)->lval; | |
329 | val = BYTEOFF(val); | |
330 | printf( CONFMT, val ); | |
331 | continue; | |
332 | ||
333 | case 'C': /* for constant value only */ | |
334 | conput( getlr( p, *++cp ) ); | |
335 | continue; | |
336 | ||
337 | case 'I': /* in instruction */ | |
338 | insput( getlr( p, *++cp ) ); | |
339 | continue; | |
340 | ||
341 | case 'A': /* address of */ | |
342 | adrput( getlr( p, *++cp ) ); | |
343 | continue; | |
344 | ||
345 | case 'U': /* for upper half of address, only */ | |
346 | upput( getlr( p, *++cp ) ); | |
347 | continue; | |
348 | ||
349 | } | |
350 | ||
351 | } | |
352 | ||
353 | } | |
354 | ||
355 | NODE * | |
356 | getlr( p, c ) NODE *p; { | |
357 | ||
358 | /* return the pointer to the left or right side of p, or p itself, | |
359 | depending on the optype of p */ | |
360 | ||
361 | switch( c ) { | |
362 | ||
363 | case '1': | |
364 | case '2': | |
365 | case '3': | |
366 | return( &resc[c-'1'] ); | |
367 | ||
368 | case 'L': | |
369 | return( optype( p->op ) == LTYPE ? p : p->left ); | |
370 | ||
371 | case 'R': | |
372 | return( optype( p->op ) != BITYPE ? p : p->right ); | |
373 | ||
374 | } | |
375 | cerror( "bad getlr: %c", c ); | |
376 | /* NOTREACHED */ | |
377 | } |