166ea3b60Sralph #ifndef lint
2*24da39faSdonn static char *sccsid ="@(#)match.c 4.7 (Berkeley) 12/10/87";
366ea3b60Sralph #endif lint
466ea3b60Sralph
5fa32d6d5Sralph # include "pass2.h"
6b3f8992cSralph
7b3f8992cSralph # ifdef WCARD1
8b3f8992cSralph # ifdef WCARD2
9b3f8992cSralph # define NOINDIRECT
10b3f8992cSralph # endif
11b3f8992cSralph # endif
12b3f8992cSralph
13b3f8992cSralph extern vdebug;
14b3f8992cSralph
15b3f8992cSralph int fldsz, fldshf;
16b3f8992cSralph
17b3f8992cSralph static int mamask[] = { /* masks for matching dope with shapes */
18b3f8992cSralph SIMPFLG, /* OPSIMP */
19b3f8992cSralph SIMPFLG|ASGFLG, /* ASG OPSIMP */
20b3f8992cSralph COMMFLG, /* OPCOMM */
21b3f8992cSralph COMMFLG|ASGFLG, /* ASG OPCOMM */
22b3f8992cSralph MULFLG, /* OPMUL */
23b3f8992cSralph MULFLG|ASGFLG, /* ASG OPMUL */
24b3f8992cSralph DIVFLG, /* OPDIV */
25b3f8992cSralph DIVFLG|ASGFLG, /* ASG OPDIV */
26b3f8992cSralph UTYPE, /* OPUNARY */
27b3f8992cSralph TYFLG, /* ASG OPUNARY is senseless */
28b3f8992cSralph LTYPE, /* OPLEAF */
29b3f8992cSralph TYFLG, /* ASG OPLEAF is senseless */
30b3f8992cSralph 0, /* OPANY */
31b3f8992cSralph ASGOPFLG|ASGFLG, /* ASG OPANY */
32b3f8992cSralph LOGFLG, /* OPLOG */
33b3f8992cSralph TYFLG, /* ASG OPLOG is senseless */
34b3f8992cSralph FLOFLG, /* OPFLOAT */
35b3f8992cSralph FLOFLG|ASGFLG, /* ASG OPFLOAT */
36b3f8992cSralph SHFFLG, /* OPSHFT */
37b3f8992cSralph SHFFLG|ASGFLG, /* ASG OPSHIFT */
38b3f8992cSralph SPFLG, /* OPLTYPE */
39b3f8992cSralph TYFLG, /* ASG OPLTYPE is senseless */
40b3f8992cSralph };
41b3f8992cSralph
42b3f8992cSralph int sdebug = 0;
43b3f8992cSralph
tshape(p,shape)44b3f8992cSralph tshape( p, shape ) NODE *p; {
45b3f8992cSralph /* return true if shape is appropriate for the node p
46b3f8992cSralph side effect for SFLD is to set up fldsz,etc */
47b3f8992cSralph register o, mask;
48b3f8992cSralph
49b3f8992cSralph o = p->in.op;
50b3f8992cSralph
51b3f8992cSralph # ifndef BUG3
52b3f8992cSralph if( sdebug ){
53d07e5cf1Smckusick printf( "tshape( %o, ", p );
54d07e5cf1Smckusick prcook( shape );
55d07e5cf1Smckusick printf( " ) op = %s\n", opst[o] );
56b3f8992cSralph }
57b3f8992cSralph # endif
58b3f8992cSralph
59b3f8992cSralph if( shape & SPECIAL ){
60b3f8992cSralph
61b3f8992cSralph switch( shape ){
62b3f8992cSralph case SZERO:
63b3f8992cSralph case SONE:
64b3f8992cSralph case SMONE:
65b3f8992cSralph case SSCON:
66b3f8992cSralph case SCCON:
67573966a3Sdonn case SMCON:
68b3f8992cSralph if( o != ICON || p->in.name[0] ) return(0);
69573966a3Sdonn }
70573966a3Sdonn
71573966a3Sdonn switch( shape ){
72573966a3Sdonn
73573966a3Sdonn case SZERO:
74573966a3Sdonn return( p->tn.lval == 0 );
75573966a3Sdonn case SONE:
76573966a3Sdonn return( p->tn.lval == 1 );
77573966a3Sdonn case SMONE:
78573966a3Sdonn return( p->tn.lval == -1 );
79573966a3Sdonn case SSCON:
80573966a3Sdonn return( p->tn.lval > -32769 && p->tn.lval < 32768 );
81573966a3Sdonn case SCCON:
82573966a3Sdonn return( p->tn.lval > -129 && p->tn.lval < 128 );
83573966a3Sdonn case SMCON:
84573966a3Sdonn return( p->tn.lval < 0 );
85b3f8992cSralph
86b3f8992cSralph case SSOREG: /* non-indexed OREG */
87b3f8992cSralph if( o == OREG && !R2TEST(p->tn.rval) ) return(1);
88b3f8992cSralph else return(0);
89b3f8992cSralph
90b3f8992cSralph default:
91b3f8992cSralph # ifdef MULTILEVEL
92b3f8992cSralph if( shape & MULTILEVEL )
93b3f8992cSralph return( mlmatch(p,shape,0) );
94b3f8992cSralph else
95b3f8992cSralph # endif
96b3f8992cSralph return( special( p, shape ) );
97b3f8992cSralph }
98b3f8992cSralph }
99b3f8992cSralph
100b3f8992cSralph if( shape & SANY ) return(1);
101b3f8992cSralph
102b3f8992cSralph if( (shape&INTEMP) && shtemp(p) ) return(1);
103b3f8992cSralph
104b3f8992cSralph if( (shape&SWADD) && (o==NAME||o==OREG) ){
105b3f8992cSralph if( BYTEOFF(p->tn.lval) ) return(0);
106b3f8992cSralph }
107b3f8992cSralph
108b3f8992cSralph # ifdef WCARD1
109b3f8992cSralph if( shape & WCARD1 )
110b3f8992cSralph return( wcard1(p) & shape );
111b3f8992cSralph # endif
112b3f8992cSralph
113b3f8992cSralph # ifdef WCARD2
114b3f8992cSralph if( shape & WCARD2 )
115b3f8992cSralph return( wcard2(p) & shape );
116b3f8992cSralph # endif
117b3f8992cSralph switch( o ){
118b3f8992cSralph
119b3f8992cSralph case NAME:
120b3f8992cSralph return( shape&SNAME );
121b3f8992cSralph case ICON:
122b3f8992cSralph mask = SCON;
123b3f8992cSralph return( shape & mask );
124b3f8992cSralph
125b3f8992cSralph case FLD:
126b3f8992cSralph if( shape & SFLD ){
127b3f8992cSralph if( !flshape( p->in.left ) ) return(0);
128b3f8992cSralph /* it is a FIELD shape; make side-effects */
129b3f8992cSralph o = p->tn.rval;
130b3f8992cSralph fldsz = UPKFSZ(o);
131b3f8992cSralph # ifdef RTOLBYTES
132b3f8992cSralph fldshf = UPKFOFF(o);
133b3f8992cSralph # else
134b3f8992cSralph fldshf = SZINT - fldsz - UPKFOFF(o);
135b3f8992cSralph # endif
136b3f8992cSralph return(1);
137b3f8992cSralph }
138b3f8992cSralph return(0);
139b3f8992cSralph
140b3f8992cSralph case CCODES:
141b3f8992cSralph return( shape&SCC );
142b3f8992cSralph
143b3f8992cSralph case REG:
144b3f8992cSralph /* distinctions:
145b3f8992cSralph SAREG any scalar register
146b3f8992cSralph STAREG any temporary scalar register
147b3f8992cSralph SBREG any lvalue (index) register
148b3f8992cSralph STBREG any temporary lvalue register
149b3f8992cSralph */
150b3f8992cSralph mask = isbreg( p->tn.rval ) ? SBREG : SAREG;
151*24da39faSdonn if( istreg( p->tn.rval ) && !ISBUSY(p->tn.rval) ) mask |= mask==SAREG ? STAREG : STBREG;
152b3f8992cSralph return( shape & mask );
153b3f8992cSralph
154b3f8992cSralph case OREG:
155b3f8992cSralph return( shape & SOREG );
156b3f8992cSralph
157b3f8992cSralph # ifndef NOINDIRECT
158b3f8992cSralph case UNARY MUL:
159b3f8992cSralph /* return STARNM or STARREG or 0 */
160b3f8992cSralph return( shumul(p->in.left) & shape );
161b3f8992cSralph # endif
162b3f8992cSralph
163b3f8992cSralph }
164b3f8992cSralph
165b3f8992cSralph return(0);
166b3f8992cSralph }
167b3f8992cSralph
168b3f8992cSralph int tdebug = 0;
169b3f8992cSralph
ttype(t,tword)170b3f8992cSralph ttype( t, tword ) TWORD t; {
171b3f8992cSralph /* does the type t match tword */
172b3f8992cSralph
173b3f8992cSralph if( tword & TANY ) return(1);
174b3f8992cSralph
175b3f8992cSralph if( t == UNDEF ) t=INT; /* void functions eased thru tables */
176b3f8992cSralph # ifndef BUG3
177b3f8992cSralph if( tdebug ){
178b3f8992cSralph printf( "ttype( %o, %o )\n", t, tword );
179b3f8992cSralph }
180b3f8992cSralph # endif
181b3f8992cSralph if( ISPTR(t) && (tword&TPTRTO) ) {
182b3f8992cSralph do {
183b3f8992cSralph t = DECREF(t);
184b3f8992cSralph } while ( ISARY(t) );
185b3f8992cSralph /* arrays that are left are usually only
186b3f8992cSralph in structure references... */
187b3f8992cSralph return( ttype( t, tword&(~TPTRTO) ) );
188b3f8992cSralph }
189b3f8992cSralph if( t != BTYPE(t) ) return( tword & TPOINT ); /* TPOINT means not simple! */
190b3f8992cSralph if( tword & TPTRTO ) return(0);
191b3f8992cSralph
192b3f8992cSralph switch( t ){
193b3f8992cSralph
194b3f8992cSralph case CHAR:
195b3f8992cSralph return( tword & TCHAR );
196b3f8992cSralph case SHORT:
197b3f8992cSralph return( tword & TSHORT );
198b3f8992cSralph case STRTY:
199b3f8992cSralph case UNIONTY:
200b3f8992cSralph return( tword & TSTRUCT );
201b3f8992cSralph case INT:
202b3f8992cSralph return( tword & TINT );
203b3f8992cSralph case UNSIGNED:
204b3f8992cSralph return( tword & TUNSIGNED );
205b3f8992cSralph case USHORT:
206b3f8992cSralph return( tword & TUSHORT );
207b3f8992cSralph case UCHAR:
208b3f8992cSralph return( tword & TUCHAR );
209b3f8992cSralph case ULONG:
210b3f8992cSralph return( tword & TULONG );
211b3f8992cSralph case LONG:
212b3f8992cSralph return( tword & TLONG );
213b3f8992cSralph case FLOAT:
214b3f8992cSralph return( tword & TFLOAT );
215b3f8992cSralph case DOUBLE:
216b3f8992cSralph return( tword & TDOUBLE );
217b3f8992cSralph }
218b3f8992cSralph
219b3f8992cSralph return(0);
220b3f8992cSralph }
221b3f8992cSralph
222b3f8992cSralph struct optab *rwtable;
223b3f8992cSralph
224b3f8992cSralph struct optab *opptr[DSIZE];
225b3f8992cSralph
setrew()226b3f8992cSralph setrew(){
227b3f8992cSralph /* set rwtable to first value which allows rewrite */
228b3f8992cSralph register struct optab *q;
229b3f8992cSralph register int i;
230b3f8992cSralph
231b3f8992cSralph # ifdef MULTILEVEL
232b3f8992cSralph /* also initialize multi-level tree links */
233b3f8992cSralph mlinit();
234b3f8992cSralph # endif
235b3f8992cSralph
236b3f8992cSralph for( q = table; q->op != FREE; ++q ){
237b3f8992cSralph if( q->needs == REWRITE ){
238b3f8992cSralph rwtable = q;
239b3f8992cSralph goto more;
240b3f8992cSralph }
241b3f8992cSralph }
242b3f8992cSralph cerror( "bad setrew" );
243b3f8992cSralph
244b3f8992cSralph
245b3f8992cSralph more:
246b3f8992cSralph for( i=0; i<DSIZE; ++i ){
247b3f8992cSralph if( dope[i] ){ /* there is an op... */
248b3f8992cSralph for( q=table; q->op != FREE; ++q ){
249b3f8992cSralph /* beware; things like LTYPE that match
250b3f8992cSralph multiple things in the tree must
251b3f8992cSralph not try to look at the NIL at this
252b3f8992cSralph stage of things! Put something else
253b3f8992cSralph first in table.c */
254b3f8992cSralph /* at one point, the operator matching was 15% of the
255b3f8992cSralph total comile time; thus, the function
256b3f8992cSralph call that was here was removed...
257b3f8992cSralph */
258b3f8992cSralph
259b3f8992cSralph if( q->op < OPSIMP ){
260b3f8992cSralph if( q->op==i ) break;
261b3f8992cSralph }
262b3f8992cSralph else {
263b3f8992cSralph register opmtemp;
264b3f8992cSralph if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){
265b3f8992cSralph if( i==NAME || i==ICON || i==OREG ) break;
266b3f8992cSralph else if( shltype( i, NIL ) ) break;
267b3f8992cSralph }
268b3f8992cSralph else if( (dope[i]&(opmtemp|ASGFLG)) == opmtemp ) break;
269b3f8992cSralph }
270b3f8992cSralph }
271b3f8992cSralph opptr[i] = q;
272b3f8992cSralph }
273b3f8992cSralph }
274b3f8992cSralph }
275b3f8992cSralph
276*24da39faSdonn #ifdef MATCHSTATS
277*24da39faSdonn struct matchstats {
278*24da39faSdonn unsigned ms_total;
279*24da39faSdonn unsigned ms_opsimp;
280*24da39faSdonn unsigned ms_opglob;
281*24da39faSdonn unsigned ms_cookie;
282*24da39faSdonn unsigned ms_shape;
283*24da39faSdonn unsigned ms_type;
284*24da39faSdonn unsigned ms_rewrite;
285*24da39faSdonn unsigned ms_allo;
286*24da39faSdonn unsigned ms_done;
287*24da39faSdonn unsigned ms_nope;
288*24da39faSdonn } ms;
289*24da39faSdonn #define CMS(x) { ++x; continue; }
290*24da39faSdonn #else
291*24da39faSdonn #define CMS(x) continue;
292*24da39faSdonn #endif
293*24da39faSdonn
match(p,cookie)294b3f8992cSralph match( p, cookie ) NODE *p; {
295b3f8992cSralph /* called by: order, gencall
296b3f8992cSralph look for match in table and generate code if found unless
297b3f8992cSralph entry specified REWRITE.
298b3f8992cSralph returns MDONE, MNOPE, or rewrite specification from table */
299b3f8992cSralph
300b3f8992cSralph register struct optab *q;
301b3f8992cSralph register NODE *r;
302b3f8992cSralph
303b3f8992cSralph rcount();
304b3f8992cSralph if( cookie == FORREW ) q = rwtable;
305b3f8992cSralph else q = opptr[p->in.op];
306b3f8992cSralph
307b3f8992cSralph for( ; q->op != FREE; ++q ){
308b3f8992cSralph
309b3f8992cSralph /* at one point the call that was here was over 15% of the total time;
310b3f8992cSralph thus the function call was expanded inline */
311*24da39faSdonn #ifdef MATCHSTATS
312*24da39faSdonn ++ms.ms_total;
313*24da39faSdonn #endif
314b3f8992cSralph if( q->op < OPSIMP ){
315*24da39faSdonn if( q->op!=p->in.op ) CMS(ms.ms_opsimp)
316b3f8992cSralph }
317b3f8992cSralph else {
318b3f8992cSralph register opmtemp;
319b3f8992cSralph if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){
320b3f8992cSralph if( p->in.op!=NAME && p->in.op!=ICON && p->in.op!= OREG &&
321*24da39faSdonn ! shltype( p->in.op, p ) ) CMS(ms.ms_opglob)
322b3f8992cSralph }
323*24da39faSdonn else if( (dope[p->in.op]&(opmtemp|ASGFLG)) != opmtemp ) CMS(ms.ms_opglob)
324b3f8992cSralph }
325b3f8992cSralph
326*24da39faSdonn if( !(q->visit & cookie ) ) CMS(ms.ms_cookie)
327b3f8992cSralph r = getlr( p, 'L' ); /* see if left child matches */
328*24da39faSdonn if( !tshape( r, q->lshape ) ) CMS(ms.ms_shape)
329*24da39faSdonn if( !ttype( r->in.type, q->ltype ) ) CMS(ms.ms_type)
330b3f8992cSralph r = getlr( p, 'R' ); /* see if right child matches */
331*24da39faSdonn if( !tshape( r, q->rshape ) ) CMS(ms.ms_shape)
332*24da39faSdonn if( !ttype( r->in.type, q->rtype ) ) CMS(ms.ms_type)
333b3f8992cSralph
334b3f8992cSralph /* REWRITE means no code from this match but go ahead
335b3f8992cSralph and rewrite node to help future match */
336*24da39faSdonn if( q->needs & REWRITE ) {
337*24da39faSdonn #ifdef MATCHSTATS
338*24da39faSdonn ++ms.ms_rewrite;
339*24da39faSdonn #endif
340*24da39faSdonn return( q->rewrite );
341*24da39faSdonn }
342*24da39faSdonn if( !allo( p, q ) ) CMS(ms.ms_allo) /* if can't generate code, skip entry */
343b3f8992cSralph
344b3f8992cSralph /* resources are available */
345b3f8992cSralph
346b3f8992cSralph expand( p, cookie, q->cstring ); /* generate code */
347b3f8992cSralph reclaim( p, q->rewrite, cookie );
348*24da39faSdonn #ifdef MATCHSTATS
349*24da39faSdonn ++ms.ms_done;
350*24da39faSdonn #endif
351b3f8992cSralph
352b3f8992cSralph return(MDONE);
353b3f8992cSralph
354b3f8992cSralph }
355b3f8992cSralph
356*24da39faSdonn #ifdef MATCHSTATS
357*24da39faSdonn ++ms.ms_nope;
358*24da39faSdonn #endif
359*24da39faSdonn
360b3f8992cSralph return(MNOPE);
361b3f8992cSralph }
362b3f8992cSralph
363b3f8992cSralph int rtyflg = 0;
364b3f8992cSralph
expand(p,cookie,cp)365b3f8992cSralph expand( p, cookie, cp ) NODE *p; register char *cp; {
366b3f8992cSralph /* generate code by interpreting table entry */
367b3f8992cSralph
36866ea3b60Sralph # ifdef NEWZZZ
369b3f8992cSralph register char c;
37066ea3b60Sralph # endif
371b3f8992cSralph CONSZ val;
372b3f8992cSralph
373b3f8992cSralph rtyflg = 0;
374b3f8992cSralph
375b3f8992cSralph for( ; *cp; ++cp ){
376b3f8992cSralph switch( *cp ){
377b3f8992cSralph
378b3f8992cSralph default:
379b3f8992cSralph PUTCHAR( *cp );
380b3f8992cSralph continue; /* this is the usual case... */
381b3f8992cSralph
382b3f8992cSralph case 'T':
383b3f8992cSralph /* rewrite register type is suppressed */
384b3f8992cSralph rtyflg = 1;
385b3f8992cSralph continue;
386b3f8992cSralph
387b3f8992cSralph case 'Z': /* special machine dependent operations */
388b3f8992cSralph # ifdef NEWZZZ
389b3f8992cSralph switch( c = *++cp ) {
390b3f8992cSralph
391b3f8992cSralph case '1':
392b3f8992cSralph case '2':
393b3f8992cSralph case '3':
394b3f8992cSralph case 'R':
395b3f8992cSralph case 'L': /* get down first */
396b3f8992cSralph zzzcode( getlr( p, c ), *++cp );
397b3f8992cSralph break;
398b3f8992cSralph default: /* normal zzzcode processing otherwise */
399b3f8992cSralph zzzcode( p, c );
400b3f8992cSralph break;
401b3f8992cSralph }
402b3f8992cSralph # else
403b3f8992cSralph zzzcode( p, *++cp );
404b3f8992cSralph # endif
405b3f8992cSralph continue;
406b3f8992cSralph
407b3f8992cSralph case 'F': /* this line deleted if FOREFF is active */
408b3f8992cSralph if( cookie & FOREFF ) while( *++cp != '\n' ) ; /* VOID */
409b3f8992cSralph continue;
410b3f8992cSralph
411b3f8992cSralph case 'S': /* field size */
412b3f8992cSralph printf( "%d", fldsz );
413b3f8992cSralph continue;
414b3f8992cSralph
415b3f8992cSralph case 'H': /* field shift */
416b3f8992cSralph printf( "%d", fldshf );
417b3f8992cSralph continue;
418b3f8992cSralph
419b3f8992cSralph case 'M': /* field mask */
420b3f8992cSralph case 'N': /* complement of field mask */
421b3f8992cSralph val = 1;
422b3f8992cSralph val <<= fldsz;
423b3f8992cSralph --val;
424b3f8992cSralph val <<= fldshf;
425b3f8992cSralph adrcon( *cp=='M' ? val : ~val );
426b3f8992cSralph continue;
427b3f8992cSralph
428b3f8992cSralph case 'L': /* output special label field */
429b3f8992cSralph printf( "%d", p->bn.label );
430b3f8992cSralph continue;
431b3f8992cSralph
432b3f8992cSralph case 'O': /* opcode string */
433b3f8992cSralph hopcode( *++cp, p->in.op );
434b3f8992cSralph continue;
435b3f8992cSralph
436b3f8992cSralph case 'B': /* byte offset in word */
437b3f8992cSralph val = getlr(p,*++cp)->tn.lval;
438b3f8992cSralph val = BYTEOFF(val);
439b3f8992cSralph printf( CONFMT, val );
440b3f8992cSralph continue;
441b3f8992cSralph
442b3f8992cSralph case 'C': /* for constant value only */
443b3f8992cSralph conput( getlr( p, *++cp ) );
444b3f8992cSralph continue;
445b3f8992cSralph
446b3f8992cSralph case 'I': /* in instruction */
447b3f8992cSralph insput( getlr( p, *++cp ) );
448b3f8992cSralph continue;
449b3f8992cSralph
450b3f8992cSralph case 'A': /* address of */
451b3f8992cSralph adrput( getlr( p, *++cp ) );
452b3f8992cSralph continue;
453b3f8992cSralph
454b3f8992cSralph case 'U': /* for upper half of address, only */
4551ac2a01bSsam upput( getlr( p, *++cp ), SZLONG );
456b3f8992cSralph continue;
457b3f8992cSralph
458b3f8992cSralph }
459b3f8992cSralph
460b3f8992cSralph }
461b3f8992cSralph
462b3f8992cSralph }
463b3f8992cSralph
464b3f8992cSralph NODE *
getlr(p,c)465b3f8992cSralph getlr( p, c ) NODE *p; {
466b3f8992cSralph
467b3f8992cSralph /* return the pointer to the left or right side of p, or p itself,
468b3f8992cSralph depending on the optype of p */
469b3f8992cSralph
470b3f8992cSralph switch( c ) {
471b3f8992cSralph
472b3f8992cSralph case '1':
473b3f8992cSralph case '2':
474b3f8992cSralph case '3':
475b3f8992cSralph return( &resc[c-'1'] );
476b3f8992cSralph
477b3f8992cSralph case 'L':
478b3f8992cSralph return( optype( p->in.op ) == LTYPE ? p : p->in.left );
479b3f8992cSralph
480b3f8992cSralph case 'R':
481b3f8992cSralph return( optype( p->in.op ) != BITYPE ? p : p->in.right );
482b3f8992cSralph
483b3f8992cSralph }
484b3f8992cSralph cerror( "bad getlr: %c", c );
485b3f8992cSralph /* NOTREACHED */
486b3f8992cSralph }
487b3f8992cSralph # ifdef MULTILEVEL
488b3f8992cSralph
489b3f8992cSralph union mltemplate{
490b3f8992cSralph struct ml_head{
491b3f8992cSralph int tag; /* identifies class of tree */
492b3f8992cSralph int subtag; /* subclass of tree */
493b3f8992cSralph union mltemplate * nexthead; /* linked by mlinit() */
494b3f8992cSralph } mlhead;
495b3f8992cSralph struct ml_node{
496b3f8992cSralph int op; /* either an operator or op description */
497b3f8992cSralph int nshape; /* shape of node */
498b3f8992cSralph /* both op and nshape must match the node.
499b3f8992cSralph * where the work is to be done entirely by
500b3f8992cSralph * op, nshape can be SANY, visa versa, op can
501b3f8992cSralph * be OPANY.
502b3f8992cSralph */
503b3f8992cSralph int ntype; /* type descriptor from mfile2 */
504b3f8992cSralph } mlnode;
505b3f8992cSralph };
506b3f8992cSralph
507b3f8992cSralph # define MLSZ 30
508b3f8992cSralph
509b3f8992cSralph extern union mltemplate mltree[];
510b3f8992cSralph int mlstack[MLSZ];
511b3f8992cSralph int *mlsp; /* pointing into mlstack */
512b3f8992cSralph NODE * ststack[MLSZ];
513b3f8992cSralph NODE **stp; /* pointing into ststack */
514b3f8992cSralph
mlinit()515b3f8992cSralph mlinit(){
516b3f8992cSralph union mltemplate **lastlink;
517b3f8992cSralph register union mltemplate *n;
518b3f8992cSralph register mlop;
519b3f8992cSralph
520b3f8992cSralph lastlink = &(mltree[0].nexthead);
521b3f8992cSralph n = &mltree[0];
522b3f8992cSralph for( ; (n++)->mlhead.tag != 0;
523b3f8992cSralph *lastlink = ++n, lastlink = &(n->mlhead.nexthead) ){
524b3f8992cSralph # ifndef BUG3
525b3f8992cSralph if( vdebug )printf("mlinit: %d\n",(n-1)->mlhead.tag);
526b3f8992cSralph # endif
527b3f8992cSralph /* wander thru a tree with a stack finding
528b3f8992cSralph * its structure so the next header can be located.
529b3f8992cSralph */
530b3f8992cSralph mlsp = mlstack;
531b3f8992cSralph
532b3f8992cSralph for( ;; ++n ){
533b3f8992cSralph if( (mlop = n->mlnode.op) < OPSIMP ){
534b3f8992cSralph switch( optype(mlop) ){
535b3f8992cSralph
536b3f8992cSralph default:
537b3f8992cSralph cerror("(1)unknown opcode: %o",mlop);
538b3f8992cSralph case BITYPE:
539b3f8992cSralph goto binary;
540b3f8992cSralph case UTYPE:
541b3f8992cSralph break;
542b3f8992cSralph case LTYPE:
543b3f8992cSralph goto leaf;
544b3f8992cSralph }
545b3f8992cSralph }
546b3f8992cSralph else{
547b3f8992cSralph if( mamask[mlop-OPSIMP] &
548b3f8992cSralph (SIMPFLG|COMMFLG|MULFLG|DIVFLG|LOGFLG|FLOFLG|SHFFLG) ){
549b3f8992cSralph binary:
550b3f8992cSralph *mlsp++ = BITYPE;
551b3f8992cSralph }
552b3f8992cSralph else if( ! (mamask[mlop-OPSIMP] & UTYPE) ){/* includes OPANY */
553b3f8992cSralph
554b3f8992cSralph leaf:
555b3f8992cSralph if( mlsp == mlstack )
556b3f8992cSralph goto tree_end;
557b3f8992cSralph else if ( *--mlsp != BITYPE )
558b3f8992cSralph cerror("(1)bad multi-level tree descriptor around mltree[%d]",
559b3f8992cSralph n-mltree);
560b3f8992cSralph }
561b3f8992cSralph }
562b3f8992cSralph }
563b3f8992cSralph tree_end: /* n points to final leaf */
564b3f8992cSralph ;
565b3f8992cSralph }
566b3f8992cSralph # ifndef BUG3
567b3f8992cSralph if( vdebug > 3 ){
568b3f8992cSralph printf("mltree={\n");
569b3f8992cSralph for( n= &(mltree[0]); n->mlhead.tag != 0; ++n)
570b3f8992cSralph printf("%o: %d, %d, %o,\n",n,
571b3f8992cSralph n->mlhead.tag,n->mlhead.subtag,n->mlhead.nexthead);
572b3f8992cSralph printf(" }\n");
573b3f8992cSralph }
574b3f8992cSralph # endif
575b3f8992cSralph }
576b3f8992cSralph
mlmatch(subtree,target,subtarget)577b3f8992cSralph mlmatch( subtree, target, subtarget ) NODE * subtree; int target,subtarget;{
578b3f8992cSralph /*
579b3f8992cSralph * does subtree match a multi-level tree with
580b3f8992cSralph * tag "target"? Return zero on failure,
581b3f8992cSralph * non-zero subtag on success (or MDONE if
582b3f8992cSralph * there is a zero subtag field).
583b3f8992cSralph */
584b3f8992cSralph union mltemplate *head; /* current template header */
585b3f8992cSralph register union mltemplate *n; /* node being matched */
586b3f8992cSralph NODE * st; /* subtree being matched */
587b3f8992cSralph register int mlop;
588b3f8992cSralph
589b3f8992cSralph # ifndef BUG3
590b3f8992cSralph if( vdebug ) printf("mlmatch(%o,%d)\n",subtree,target);
591b3f8992cSralph # endif
592b3f8992cSralph for( head = &(mltree[0]); head->mlhead.tag != 0;
593b3f8992cSralph head=head->mlhead.nexthead){
594b3f8992cSralph # ifndef BUG3
595b3f8992cSralph if( vdebug > 1 )printf("mlmatch head(%o) tag(%d)\n",
596b3f8992cSralph head->mlhead.tag);
597b3f8992cSralph # endif
598b3f8992cSralph if( head->mlhead.tag != target )continue;
599b3f8992cSralph if( subtarget && head->mlhead.subtag != subtarget)continue;
600b3f8992cSralph # ifndef BUG3
601b3f8992cSralph if( vdebug ) printf("mlmatch for %d\n",target);
602b3f8992cSralph # endif
603b3f8992cSralph
604b3f8992cSralph /* potential for match */
605b3f8992cSralph
606b3f8992cSralph n = head + 1;
607b3f8992cSralph st = subtree;
608b3f8992cSralph stp = ststack;
609b3f8992cSralph mlsp = mlstack;
610b3f8992cSralph /* compare n->op, ->nshape, ->ntype to
611b3f8992cSralph * the subtree node st
612b3f8992cSralph */
613b3f8992cSralph for( ;; ++n ){ /* for each node in multi-level template */
614b3f8992cSralph /* opmatch */
615b3f8992cSralph if( n->op < OPSIMP ){
616b3f8992cSralph if( st->op != n->op )break;
617b3f8992cSralph }
618b3f8992cSralph else {
619b3f8992cSralph register opmtemp;
620b3f8992cSralph if((opmtemp=mamask[n->op-OPSIMP])&SPFLG){
621b3f8992cSralph if(st->op!=NAME && st->op!=ICON && st->op!=OREG &&
622b3f8992cSralph ! shltype(st->op,st)) break;
623b3f8992cSralph }
624b3f8992cSralph else if((dope[st->op]&(opmtemp|ASGFLG))!=opmtemp) break;
625b3f8992cSralph }
626b3f8992cSralph /* check shape and type */
627b3f8992cSralph
628b3f8992cSralph if( ! tshape( st, n->mlnode.nshape ) ) break;
629b3f8992cSralph if( ! ttype( st->type, n->mlnode.ntype ) ) break;
630b3f8992cSralph
631b3f8992cSralph /* that node matched, let's try another */
632b3f8992cSralph /* must advance both st and n and halt at right time */
633b3f8992cSralph
634b3f8992cSralph if( (mlop = n->mlnode.op) < OPSIMP ){
635b3f8992cSralph switch( optype(mlop) ){
636b3f8992cSralph
637b3f8992cSralph default:
638b3f8992cSralph cerror("(2)unknown opcode: %o",mlop);
639b3f8992cSralph case BITYPE:
640b3f8992cSralph goto binary;
641b3f8992cSralph case UTYPE:
642b3f8992cSralph st = st->left;
643b3f8992cSralph break;
644b3f8992cSralph case LTYPE:
645b3f8992cSralph goto leaf;
646b3f8992cSralph }
647b3f8992cSralph }
648b3f8992cSralph else{
649b3f8992cSralph if( mamask[mlop - OPSIMP] &
650b3f8992cSralph (SIMPFLG|COMMFLG|MULFLG|DIVFLG|LOGFLG|FLOFLG|SHFFLG) ){
651b3f8992cSralph binary:
652b3f8992cSralph *mlsp++ = BITYPE;
653b3f8992cSralph *stp++ = st;
654b3f8992cSralph st = st->left;
655b3f8992cSralph }
656b3f8992cSralph else if( ! (mamask[mlop-OPSIMP] & UTYPE) ){/* includes OPANY */
657b3f8992cSralph
658b3f8992cSralph leaf:
659b3f8992cSralph if( mlsp == mlstack )
660b3f8992cSralph goto matched;
661b3f8992cSralph else if ( *--mlsp != BITYPE )
662b3f8992cSralph cerror("(2)bad multi-level tree descriptor around mltree[%d]",
663b3f8992cSralph n-mltree);
664b3f8992cSralph st = (*--stp)->right;
665b3f8992cSralph }
666b3f8992cSralph else /* UNARY */ st = st->left;
667b3f8992cSralph }
668b3f8992cSralph continue;
669b3f8992cSralph
670b3f8992cSralph matched:
671b3f8992cSralph /* complete multi-level match successful */
672b3f8992cSralph # ifndef BUG3
673b3f8992cSralph if( vdebug ) printf("mlmatch() success\n");
674b3f8992cSralph # endif
675b3f8992cSralph if( head->mlhead.subtag == 0 ) return( MDONE );
676b3f8992cSralph else {
677b3f8992cSralph # ifndef BUG3
678b3f8992cSralph if( vdebug )printf("\treturns %d\n",
679b3f8992cSralph head->mlhead.subtag );
680b3f8992cSralph # endif
681b3f8992cSralph return( head->mlhead.subtag );
682b3f8992cSralph }
683b3f8992cSralph }
684b3f8992cSralph }
685b3f8992cSralph return( 0 );
686b3f8992cSralph }
687b3f8992cSralph # endif
688