xref: /original-bsd/old/pcc/mip/match.c (revision 24da39fa)
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