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