xref: /csrg-svn/old/pcc/mip/match.c (revision 32809)
117745Sralph #ifndef lint
2*32809Sdonn static char *sccsid ="@(#)match.c	4.7 (Berkeley) 12/10/87";
317745Sralph #endif lint
417745Sralph 
518392Sralph # include "pass2.h"
617723Sralph 
717723Sralph # ifdef WCARD1
817723Sralph # ifdef WCARD2
917723Sralph # define NOINDIRECT
1017723Sralph # endif
1117723Sralph # endif
1217723Sralph 
1317723Sralph extern vdebug;
1417723Sralph 
1517723Sralph int fldsz, fldshf;
1617723Sralph 
1717723Sralph static int mamask[] = { /* masks for matching dope with shapes */
1817723Sralph 	SIMPFLG,		/* OPSIMP */
1917723Sralph 	SIMPFLG|ASGFLG,		/* ASG OPSIMP */
2017723Sralph 	COMMFLG,	/* OPCOMM */
2117723Sralph 	COMMFLG|ASGFLG,	/* ASG OPCOMM */
2217723Sralph 	MULFLG,		/* OPMUL */
2317723Sralph 	MULFLG|ASGFLG,	/* ASG OPMUL */
2417723Sralph 	DIVFLG,		/* OPDIV */
2517723Sralph 	DIVFLG|ASGFLG,	/* ASG OPDIV */
2617723Sralph 	UTYPE,		/* OPUNARY */
2717723Sralph 	TYFLG,		/* ASG OPUNARY is senseless */
2817723Sralph 	LTYPE,		/* OPLEAF */
2917723Sralph 	TYFLG,		/* ASG OPLEAF is senseless */
3017723Sralph 	0,		/* OPANY */
3117723Sralph 	ASGOPFLG|ASGFLG,	/* ASG OPANY */
3217723Sralph 	LOGFLG,		/* OPLOG */
3317723Sralph 	TYFLG,		/* ASG OPLOG is senseless */
3417723Sralph 	FLOFLG,		/* OPFLOAT */
3517723Sralph 	FLOFLG|ASGFLG,	/* ASG OPFLOAT */
3617723Sralph 	SHFFLG,		/* OPSHFT */
3717723Sralph 	SHFFLG|ASGFLG,	/* ASG OPSHIFT */
3817723Sralph 	SPFLG,		/* OPLTYPE */
3917723Sralph 	TYFLG,		/* ASG OPLTYPE is senseless */
4017723Sralph 	};
4117723Sralph 
4217723Sralph int sdebug = 0;
4317723Sralph 
tshape(p,shape)4417723Sralph tshape( p, shape ) NODE *p; {
4517723Sralph 	/* return true if shape is appropriate for the node p
4617723Sralph 	   side effect for SFLD is to set up fldsz,etc */
4717723Sralph 	register o, mask;
4817723Sralph 
4917723Sralph 	o = p->in.op;
5017723Sralph 
5117723Sralph # ifndef BUG3
5217723Sralph 	if( sdebug ){
5324403Smckusick 		printf( "tshape( %o, ", p );
5424403Smckusick 		prcook( shape );
5524403Smckusick 		printf( " ) op = %s\n", opst[o] );
5617723Sralph 		}
5717723Sralph # endif
5817723Sralph 
5917723Sralph 	if( shape & SPECIAL ){
6017723Sralph 
6117723Sralph 		switch( shape ){
6217723Sralph 		case SZERO:
6317723Sralph 		case SONE:
6417723Sralph 		case SMONE:
6517723Sralph 		case SSCON:
6617723Sralph 		case SCCON:
6732808Sdonn 		case SMCON:
6817723Sralph 			if( o != ICON || p->in.name[0] ) return(0);
6932808Sdonn 			}
7017723Sralph 
7132808Sdonn 		switch( shape ){
7232808Sdonn 
7332808Sdonn 		case SZERO:
7432808Sdonn 			return( p->tn.lval == 0 );
7532808Sdonn 		case SONE:
7632808Sdonn 			return( p->tn.lval == 1 );
7732808Sdonn 		case SMONE:
7832808Sdonn 			return( p->tn.lval == -1 );
7932808Sdonn 		case SSCON:
8032808Sdonn 			return( p->tn.lval > -32769 && p->tn.lval < 32768 );
8132808Sdonn 		case SCCON:
8232808Sdonn 			return( p->tn.lval > -129 && p->tn.lval < 128 );
8332808Sdonn 		case SMCON:
8432808Sdonn 			return( p->tn.lval < 0 );
8532808Sdonn 
8617723Sralph 		case SSOREG:	/* non-indexed OREG */
8717723Sralph 			if( o == OREG && !R2TEST(p->tn.rval) ) return(1);
8817723Sralph 			else return(0);
8917723Sralph 
9017723Sralph 		default:
9117723Sralph # ifdef MULTILEVEL
9217723Sralph 			if( shape & MULTILEVEL )
9317723Sralph 				return( mlmatch(p,shape,0) );
9417723Sralph 			else
9517723Sralph # endif
9617723Sralph 			return( special( p, shape ) );
9717723Sralph 			}
9817723Sralph 		}
9917723Sralph 
10017723Sralph 	if( shape & SANY ) return(1);
10117723Sralph 
10217723Sralph 	if( (shape&INTEMP) && shtemp(p) ) return(1);
10317723Sralph 
10417723Sralph 	if( (shape&SWADD) && (o==NAME||o==OREG) ){
10517723Sralph 		if( BYTEOFF(p->tn.lval) ) return(0);
10617723Sralph 		}
10717723Sralph 
10817723Sralph # ifdef WCARD1
10917723Sralph 	if( shape & WCARD1 )
11017723Sralph 		return( wcard1(p) & shape );
11117723Sralph # endif
11217723Sralph 
11317723Sralph # ifdef WCARD2
11417723Sralph 	if( shape & WCARD2 )
11517723Sralph 		return( wcard2(p) & shape );
11617723Sralph # endif
11717723Sralph 	switch( o ){
11817723Sralph 
11917723Sralph 	case NAME:
12017723Sralph 		return( shape&SNAME );
12117723Sralph 	case ICON:
12217723Sralph 		mask = SCON;
12317723Sralph 		return( shape & mask );
12417723Sralph 
12517723Sralph 	case FLD:
12617723Sralph 		if( shape & SFLD ){
12717723Sralph 			if( !flshape( p->in.left ) ) return(0);
12817723Sralph 			/* it is a FIELD shape; make side-effects */
12917723Sralph 			o = p->tn.rval;
13017723Sralph 			fldsz = UPKFSZ(o);
13117723Sralph # ifdef RTOLBYTES
13217723Sralph 			fldshf = UPKFOFF(o);
13317723Sralph # else
13417723Sralph 			fldshf = SZINT - fldsz - UPKFOFF(o);
13517723Sralph # endif
13617723Sralph 			return(1);
13717723Sralph 			}
13817723Sralph 		return(0);
13917723Sralph 
14017723Sralph 	case CCODES:
14117723Sralph 		return( shape&SCC );
14217723Sralph 
14317723Sralph 	case REG:
14417723Sralph 		/* distinctions:
14517723Sralph 		SAREG	any scalar register
14617723Sralph 		STAREG	any temporary scalar register
14717723Sralph 		SBREG	any lvalue (index) register
14817723Sralph 		STBREG	any temporary lvalue register
14917723Sralph 		*/
15017723Sralph 		mask = isbreg( p->tn.rval ) ? SBREG : SAREG;
151*32809Sdonn 		if( istreg( p->tn.rval ) && !ISBUSY(p->tn.rval) ) mask |= mask==SAREG ? STAREG : STBREG;
15217723Sralph 		return( shape & mask );
15317723Sralph 
15417723Sralph 	case OREG:
15517723Sralph 		return( shape & SOREG );
15617723Sralph 
15717723Sralph # ifndef NOINDIRECT
15817723Sralph 	case UNARY MUL:
15917723Sralph 		/* return STARNM or STARREG or 0 */
16017723Sralph 		return( shumul(p->in.left) & shape );
16117723Sralph # endif
16217723Sralph 
16317723Sralph 		}
16417723Sralph 
16517723Sralph 	return(0);
16617723Sralph 	}
16717723Sralph 
16817723Sralph int tdebug = 0;
16917723Sralph 
ttype(t,tword)17017723Sralph ttype( t, tword ) TWORD t; {
17117723Sralph 	/* does the type t match tword */
17217723Sralph 
17317723Sralph 	if( tword & TANY ) return(1);
17417723Sralph 
17517723Sralph 	if( t == UNDEF ) t=INT; /* void functions eased thru tables */
17617723Sralph # ifndef BUG3
17717723Sralph 	if( tdebug ){
17817723Sralph 		printf( "ttype( %o, %o )\n", t, tword );
17917723Sralph 		}
18017723Sralph # endif
18117723Sralph 	if( ISPTR(t) && (tword&TPTRTO) ) {
18217723Sralph 		do {
18317723Sralph 			t = DECREF(t);
18417723Sralph 		} while ( ISARY(t) );
18517723Sralph 			/* arrays that are left are usually only
18617723Sralph 			   in structure references... */
18717723Sralph 		return( ttype( t, tword&(~TPTRTO) ) );
18817723Sralph 		}
18917723Sralph 	if( t != BTYPE(t) ) return( tword & TPOINT ); /* TPOINT means not simple! */
19017723Sralph 	if( tword & TPTRTO ) return(0);
19117723Sralph 
19217723Sralph 	switch( t ){
19317723Sralph 
19417723Sralph 	case CHAR:
19517723Sralph 		return( tword & TCHAR );
19617723Sralph 	case SHORT:
19717723Sralph 		return( tword & TSHORT );
19817723Sralph 	case STRTY:
19917723Sralph 	case UNIONTY:
20017723Sralph 		return( tword & TSTRUCT );
20117723Sralph 	case INT:
20217723Sralph 		return( tword & TINT );
20317723Sralph 	case UNSIGNED:
20417723Sralph 		return( tword & TUNSIGNED );
20517723Sralph 	case USHORT:
20617723Sralph 		return( tword & TUSHORT );
20717723Sralph 	case UCHAR:
20817723Sralph 		return( tword & TUCHAR );
20917723Sralph 	case ULONG:
21017723Sralph 		return( tword & TULONG );
21117723Sralph 	case LONG:
21217723Sralph 		return( tword & TLONG );
21317723Sralph 	case FLOAT:
21417723Sralph 		return( tword & TFLOAT );
21517723Sralph 	case DOUBLE:
21617723Sralph 		return( tword & TDOUBLE );
21717723Sralph 		}
21817723Sralph 
21917723Sralph 	return(0);
22017723Sralph 	}
22117723Sralph 
22217723Sralph struct optab *rwtable;
22317723Sralph 
22417723Sralph struct optab *opptr[DSIZE];
22517723Sralph 
setrew()22617723Sralph setrew(){
22717723Sralph 	/* set rwtable to first value which allows rewrite */
22817723Sralph 	register struct optab *q;
22917723Sralph 	register int i;
23017723Sralph 
23117723Sralph # ifdef MULTILEVEL
23217723Sralph 	/* also initialize multi-level tree links */
23317723Sralph 	mlinit();
23417723Sralph # endif
23517723Sralph 
23617723Sralph 	for( q = table; q->op != FREE; ++q ){
23717723Sralph 		if( q->needs == REWRITE ){
23817723Sralph 			rwtable = q;
23917723Sralph 			goto more;
24017723Sralph 			}
24117723Sralph 		}
24217723Sralph 	cerror( "bad setrew" );
24317723Sralph 
24417723Sralph 
24517723Sralph 	more:
24617723Sralph 	for( i=0; i<DSIZE; ++i ){
24717723Sralph 		if( dope[i] ){ /* there is an op... */
24817723Sralph 			for( q=table; q->op != FREE; ++q ){
24917723Sralph 				/*  beware; things like LTYPE that match
25017723Sralph 				    multiple things in the tree must
25117723Sralph 				    not try to look at the NIL at this
25217723Sralph 				    stage of things!  Put something else
25317723Sralph 				    first in table.c  */
25417723Sralph 				/* at one point, the operator matching was 15% of the
25517723Sralph 				    total comile time; thus, the function
25617723Sralph 				    call that was here was removed...
25717723Sralph 				*/
25817723Sralph 
25917723Sralph 				if( q->op < OPSIMP ){
26017723Sralph 					if( q->op==i ) break;
26117723Sralph 					}
26217723Sralph 				else {
26317723Sralph 					register opmtemp;
26417723Sralph 					if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){
26517723Sralph 						if( i==NAME || i==ICON || i==OREG ) break;
26617723Sralph 						else if( shltype( i, NIL ) ) break;
26717723Sralph 						}
26817723Sralph 					else if( (dope[i]&(opmtemp|ASGFLG)) == opmtemp ) break;
26917723Sralph 					}
27017723Sralph 				}
27117723Sralph 			opptr[i] = q;
27217723Sralph 			}
27317723Sralph 		}
27417723Sralph 	}
27517723Sralph 
276*32809Sdonn #ifdef MATCHSTATS
277*32809Sdonn struct matchstats {
278*32809Sdonn 	unsigned ms_total;
279*32809Sdonn 	unsigned ms_opsimp;
280*32809Sdonn 	unsigned ms_opglob;
281*32809Sdonn 	unsigned ms_cookie;
282*32809Sdonn 	unsigned ms_shape;
283*32809Sdonn 	unsigned ms_type;
284*32809Sdonn 	unsigned ms_rewrite;
285*32809Sdonn 	unsigned ms_allo;
286*32809Sdonn 	unsigned ms_done;
287*32809Sdonn 	unsigned ms_nope;
288*32809Sdonn } ms;
289*32809Sdonn #define CMS(x) { ++x; continue; }
290*32809Sdonn #else
291*32809Sdonn #define CMS(x) continue;
292*32809Sdonn #endif
293*32809Sdonn 
match(p,cookie)29417723Sralph match( p, cookie ) NODE *p; {
29517723Sralph 	/* called by: order, gencall
29617723Sralph 	   look for match in table and generate code if found unless
29717723Sralph 	   entry specified REWRITE.
29817723Sralph 	   returns MDONE, MNOPE, or rewrite specification from table */
29917723Sralph 
30017723Sralph 	register struct optab *q;
30117723Sralph 	register NODE *r;
30217723Sralph 
30317723Sralph 	rcount();
30417723Sralph 	if( cookie == FORREW ) q = rwtable;
30517723Sralph 	else q = opptr[p->in.op];
30617723Sralph 
30717723Sralph 	for( ; q->op != FREE; ++q ){
30817723Sralph 
30917723Sralph 		/* at one point the call that was here was over 15% of the total time;
31017723Sralph 		    thus the function call was expanded inline */
311*32809Sdonn #ifdef MATCHSTATS
312*32809Sdonn 		++ms.ms_total;
313*32809Sdonn #endif
31417723Sralph 		if( q->op < OPSIMP ){
315*32809Sdonn 			if( q->op!=p->in.op ) CMS(ms.ms_opsimp)
31617723Sralph 			}
31717723Sralph 		else {
31817723Sralph 			register opmtemp;
31917723Sralph 			if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){
32017723Sralph 				if( p->in.op!=NAME && p->in.op!=ICON && p->in.op!= OREG &&
321*32809Sdonn 					! shltype( p->in.op, p ) ) CMS(ms.ms_opglob)
32217723Sralph 				}
323*32809Sdonn 			else if( (dope[p->in.op]&(opmtemp|ASGFLG)) != opmtemp ) CMS(ms.ms_opglob)
32417723Sralph 			}
32517723Sralph 
326*32809Sdonn 		if( !(q->visit & cookie ) ) CMS(ms.ms_cookie)
32717723Sralph 		r = getlr( p, 'L' );			/* see if left child matches */
328*32809Sdonn 		if( !tshape( r, q->lshape ) ) CMS(ms.ms_shape)
329*32809Sdonn 		if( !ttype( r->in.type, q->ltype ) ) CMS(ms.ms_type)
33017723Sralph 		r = getlr( p, 'R' );			/* see if right child matches */
331*32809Sdonn 		if( !tshape( r, q->rshape ) ) CMS(ms.ms_shape)
332*32809Sdonn 		if( !ttype( r->in.type, q->rtype ) ) CMS(ms.ms_type)
33317723Sralph 
33417723Sralph 			/* REWRITE means no code from this match but go ahead
33517723Sralph 			   and rewrite node to help future match */
336*32809Sdonn 		if( q->needs & REWRITE ) {
337*32809Sdonn #ifdef MATCHSTATS
338*32809Sdonn 			++ms.ms_rewrite;
339*32809Sdonn #endif
340*32809Sdonn 			return( q->rewrite );
341*32809Sdonn 			}
342*32809Sdonn 		if( !allo( p, q ) ) CMS(ms.ms_allo)			/* if can't generate code, skip entry */
34317723Sralph 
34417723Sralph 		/* resources are available */
34517723Sralph 
34617723Sralph 		expand( p, cookie, q->cstring );		/* generate code */
34717723Sralph 		reclaim( p, q->rewrite, cookie );
348*32809Sdonn #ifdef MATCHSTATS
349*32809Sdonn 		++ms.ms_done;
350*32809Sdonn #endif
35117723Sralph 
35217723Sralph 		return(MDONE);
35317723Sralph 
35417723Sralph 		}
35517723Sralph 
356*32809Sdonn #ifdef MATCHSTATS
357*32809Sdonn 	++ms.ms_nope;
358*32809Sdonn #endif
359*32809Sdonn 
36017723Sralph 	return(MNOPE);
36117723Sralph 	}
36217723Sralph 
36317723Sralph int rtyflg = 0;
36417723Sralph 
expand(p,cookie,cp)36517723Sralph expand( p, cookie, cp ) NODE *p;  register char *cp; {
36617723Sralph 	/* generate code by interpreting table entry */
36717723Sralph 
36817745Sralph # ifdef NEWZZZ
36917723Sralph 	register char c;
37017745Sralph # endif
37117723Sralph 	CONSZ val;
37217723Sralph 
37317723Sralph 	rtyflg = 0;
37417723Sralph 
37517723Sralph 	for( ; *cp; ++cp ){
37617723Sralph 		switch( *cp ){
37717723Sralph 
37817723Sralph 		default:
37917723Sralph 			PUTCHAR( *cp );
38017723Sralph 			continue;  /* this is the usual case... */
38117723Sralph 
38217723Sralph 		case 'T':
38317723Sralph 			/* rewrite register type is suppressed */
38417723Sralph 			rtyflg = 1;
38517723Sralph 			continue;
38617723Sralph 
38717723Sralph 		case 'Z':  /* special machine dependent operations */
38817723Sralph # ifdef NEWZZZ
38917723Sralph 			switch( c = *++cp ) {
39017723Sralph 
39117723Sralph 			case '1':
39217723Sralph 			case '2':
39317723Sralph 			case '3':
39417723Sralph 			case 'R':
39517723Sralph 			case 'L':	/* get down first */
39617723Sralph 				zzzcode( getlr( p, c ), *++cp );
39717723Sralph 				break;
39817723Sralph 			default:   /* normal zzzcode processing otherwise */
39917723Sralph 				zzzcode( p, c );
40017723Sralph 				break;
40117723Sralph 			}
40217723Sralph # else
40317723Sralph 			zzzcode( p, *++cp );
40417723Sralph # endif
40517723Sralph 			continue;
40617723Sralph 
40717723Sralph 		case 'F':  /* this line deleted if FOREFF is active */
40817723Sralph 			if( cookie & FOREFF ) while( *++cp != '\n' ) ; /* VOID */
40917723Sralph 			continue;
41017723Sralph 
41117723Sralph 		case 'S':  /* field size */
41217723Sralph 			printf( "%d", fldsz );
41317723Sralph 			continue;
41417723Sralph 
41517723Sralph 		case 'H':  /* field shift */
41617723Sralph 			printf( "%d", fldshf );
41717723Sralph 			continue;
41817723Sralph 
41917723Sralph 		case 'M':  /* field mask */
42017723Sralph 		case 'N':  /* complement of field mask */
42117723Sralph 			val = 1;
42217723Sralph 			val <<= fldsz;
42317723Sralph 			--val;
42417723Sralph 			val <<= fldshf;
42517723Sralph 			adrcon( *cp=='M' ? val : ~val );
42617723Sralph 			continue;
42717723Sralph 
42817723Sralph 		case 'L':  /* output special label field */
42917723Sralph 			printf( "%d", p->bn.label );
43017723Sralph 			continue;
43117723Sralph 
43217723Sralph 		case 'O':  /* opcode string */
43317723Sralph 			hopcode( *++cp, p->in.op );
43417723Sralph 			continue;
43517723Sralph 
43617723Sralph 		case 'B':  /* byte offset in word */
43717723Sralph 			val = getlr(p,*++cp)->tn.lval;
43817723Sralph 			val = BYTEOFF(val);
43917723Sralph 			printf( CONFMT, val );
44017723Sralph 			continue;
44117723Sralph 
44217723Sralph 		case 'C': /* for constant value only */
44317723Sralph 			conput( getlr( p, *++cp ) );
44417723Sralph 			continue;
44517723Sralph 
44617723Sralph 		case 'I': /* in instruction */
44717723Sralph 			insput( getlr( p, *++cp ) );
44817723Sralph 			continue;
44917723Sralph 
45017723Sralph 		case 'A': /* address of */
45117723Sralph 			adrput( getlr( p, *++cp ) );
45217723Sralph 			continue;
45317723Sralph 
45417723Sralph 		case 'U': /* for upper half of address, only */
45529885Ssam 			upput( getlr( p, *++cp ), SZLONG );
45617723Sralph 			continue;
45717723Sralph 
45817723Sralph 			}
45917723Sralph 
46017723Sralph 		}
46117723Sralph 
46217723Sralph 	}
46317723Sralph 
46417723Sralph NODE *
getlr(p,c)46517723Sralph getlr( p, c ) NODE *p; {
46617723Sralph 
46717723Sralph 	/* return the pointer to the left or right side of p, or p itself,
46817723Sralph 	   depending on the optype of p */
46917723Sralph 
47017723Sralph 	switch( c ) {
47117723Sralph 
47217723Sralph 	case '1':
47317723Sralph 	case '2':
47417723Sralph 	case '3':
47517723Sralph 		return( &resc[c-'1'] );
47617723Sralph 
47717723Sralph 	case 'L':
47817723Sralph 		return( optype( p->in.op ) == LTYPE ? p : p->in.left );
47917723Sralph 
48017723Sralph 	case 'R':
48117723Sralph 		return( optype( p->in.op ) != BITYPE ? p : p->in.right );
48217723Sralph 
48317723Sralph 		}
48417723Sralph 	cerror( "bad getlr: %c", c );
48517723Sralph 	/* NOTREACHED */
48617723Sralph 	}
48717723Sralph # ifdef MULTILEVEL
48817723Sralph 
48917723Sralph union mltemplate{
49017723Sralph 	struct ml_head{
49117723Sralph 		int tag; /* identifies class of tree */
49217723Sralph 		int subtag; /* subclass of tree */
49317723Sralph 		union mltemplate * nexthead; /* linked by mlinit() */
49417723Sralph 		} mlhead;
49517723Sralph 	struct ml_node{
49617723Sralph 		int op; /* either an operator or op description */
49717723Sralph 		int nshape; /* shape of node */
49817723Sralph 		/* both op and nshape must match the node.
49917723Sralph 		 * where the work is to be done entirely by
50017723Sralph 		 * op, nshape can be SANY, visa versa, op can
50117723Sralph 		 * be OPANY.
50217723Sralph 		 */
50317723Sralph 		int ntype; /* type descriptor from mfile2 */
50417723Sralph 		} mlnode;
50517723Sralph 	};
50617723Sralph 
50717723Sralph # define MLSZ 30
50817723Sralph 
50917723Sralph extern union mltemplate mltree[];
51017723Sralph int mlstack[MLSZ];
51117723Sralph int *mlsp; /* pointing into mlstack */
51217723Sralph NODE * ststack[MLSZ];
51317723Sralph NODE **stp; /* pointing into ststack */
51417723Sralph 
mlinit()51517723Sralph mlinit(){
51617723Sralph 	union mltemplate **lastlink;
51717723Sralph 	register union mltemplate *n;
51817723Sralph 	register mlop;
51917723Sralph 
52017723Sralph 	lastlink = &(mltree[0].nexthead);
52117723Sralph 	n = &mltree[0];
52217723Sralph 	for( ; (n++)->mlhead.tag != 0;
52317723Sralph 		*lastlink = ++n, lastlink = &(n->mlhead.nexthead) ){
52417723Sralph # ifndef BUG3
52517723Sralph 		if( vdebug )printf("mlinit: %d\n",(n-1)->mlhead.tag);
52617723Sralph # endif
52717723Sralph 	/* wander thru a tree with a stack finding
52817723Sralph 	 * its structure so the next header can be located.
52917723Sralph 	 */
53017723Sralph 		mlsp = mlstack;
53117723Sralph 
53217723Sralph 		for( ;; ++n ){
53317723Sralph 			if( (mlop = n->mlnode.op) < OPSIMP ){
53417723Sralph 				switch( optype(mlop) ){
53517723Sralph 
53617723Sralph 					default:
53717723Sralph 						cerror("(1)unknown opcode: %o",mlop);
53817723Sralph 					case BITYPE:
53917723Sralph 						goto binary;
54017723Sralph 					case UTYPE:
54117723Sralph 						break;
54217723Sralph 					case LTYPE:
54317723Sralph 						goto leaf;
54417723Sralph 					}
54517723Sralph 				}
54617723Sralph 			else{
54717723Sralph 				if( mamask[mlop-OPSIMP] &
54817723Sralph 					(SIMPFLG|COMMFLG|MULFLG|DIVFLG|LOGFLG|FLOFLG|SHFFLG) ){
54917723Sralph 				binary:
55017723Sralph 					*mlsp++ = BITYPE;
55117723Sralph 					}
55217723Sralph 				else if( ! (mamask[mlop-OPSIMP] & UTYPE) ){/* includes OPANY */
55317723Sralph 
55417723Sralph 				leaf:
55517723Sralph 					if( mlsp == mlstack )
55617723Sralph 						goto tree_end;
55717723Sralph 					else if ( *--mlsp != BITYPE )
55817723Sralph 						cerror("(1)bad multi-level tree descriptor around mltree[%d]",
55917723Sralph 						n-mltree);
56017723Sralph 					}
56117723Sralph 				}
56217723Sralph 			}
56317723Sralph 		tree_end: /* n points to final leaf */
56417723Sralph 		;
56517723Sralph 		}
56617723Sralph # ifndef BUG3
56717723Sralph 		if( vdebug > 3 ){
56817723Sralph 			printf("mltree={\n");
56917723Sralph 			for( n= &(mltree[0]); n->mlhead.tag != 0; ++n)
57017723Sralph 				printf("%o: %d, %d, %o,\n",n,
57117723Sralph 				n->mlhead.tag,n->mlhead.subtag,n->mlhead.nexthead);
57217723Sralph 			printf("	}\n");
57317723Sralph 			}
57417723Sralph # endif
57517723Sralph 	}
57617723Sralph 
mlmatch(subtree,target,subtarget)57717723Sralph mlmatch( subtree, target, subtarget ) NODE * subtree; int target,subtarget;{
57817723Sralph 	/*
57917723Sralph 	 * does subtree match a multi-level tree with
58017723Sralph 	 * tag "target"?  Return zero on failure,
58117723Sralph 	 * non-zero subtag on success (or MDONE if
58217723Sralph 	 * there is a zero subtag field).
58317723Sralph 	 */
58417723Sralph 	union mltemplate *head; /* current template header */
58517723Sralph 	register union mltemplate *n; /* node being matched */
58617723Sralph 	NODE * st; /* subtree being matched */
58717723Sralph 	register int mlop;
58817723Sralph 
58917723Sralph # ifndef BUG3
59017723Sralph 	if( vdebug ) printf("mlmatch(%o,%d)\n",subtree,target);
59117723Sralph # endif
59217723Sralph 	for( head = &(mltree[0]); head->mlhead.tag != 0;
59317723Sralph 		head=head->mlhead.nexthead){
59417723Sralph # ifndef BUG3
59517723Sralph 		if( vdebug > 1 )printf("mlmatch head(%o) tag(%d)\n",
59617723Sralph 			head->mlhead.tag);
59717723Sralph # endif
59817723Sralph 		if( head->mlhead.tag != target )continue;
59917723Sralph 		if( subtarget && head->mlhead.subtag != subtarget)continue;
60017723Sralph # ifndef BUG3
60117723Sralph 		if( vdebug ) printf("mlmatch for %d\n",target);
60217723Sralph # endif
60317723Sralph 
60417723Sralph 		/* potential for match */
60517723Sralph 
60617723Sralph 		n = head + 1;
60717723Sralph 		st = subtree;
60817723Sralph 		stp = ststack;
60917723Sralph 		mlsp = mlstack;
61017723Sralph 		/* compare n->op, ->nshape, ->ntype to
61117723Sralph 		 * the subtree node st
61217723Sralph 		 */
61317723Sralph 		for( ;; ++n ){ /* for each node in multi-level template */
61417723Sralph 			/* opmatch */
61517723Sralph 			if( n->op < OPSIMP ){
61617723Sralph 				if( st->op != n->op )break;
61717723Sralph 				}
61817723Sralph 			else {
61917723Sralph 				register opmtemp;
62017723Sralph 				if((opmtemp=mamask[n->op-OPSIMP])&SPFLG){
62117723Sralph 					if(st->op!=NAME && st->op!=ICON && st->op!=OREG &&
62217723Sralph 						! shltype(st->op,st)) break;
62317723Sralph 					}
62417723Sralph 				else if((dope[st->op]&(opmtemp|ASGFLG))!=opmtemp) break;
62517723Sralph 				}
62617723Sralph 			/* check shape and type */
62717723Sralph 
62817723Sralph 			if( ! tshape( st, n->mlnode.nshape ) ) break;
62917723Sralph 			if( ! ttype( st->type, n->mlnode.ntype ) ) break;
63017723Sralph 
63117723Sralph 			/* that node matched, let's try another */
63217723Sralph 			/* must advance both st and n and halt at right time */
63317723Sralph 
63417723Sralph 			if( (mlop = n->mlnode.op) < OPSIMP ){
63517723Sralph 				switch( optype(mlop) ){
63617723Sralph 
63717723Sralph 					default:
63817723Sralph 						cerror("(2)unknown opcode: %o",mlop);
63917723Sralph 					case BITYPE:
64017723Sralph 						goto binary;
64117723Sralph 					case UTYPE:
64217723Sralph 						st = st->left;
64317723Sralph 						break;
64417723Sralph 					case LTYPE:
64517723Sralph 						goto leaf;
64617723Sralph 					}
64717723Sralph 				}
64817723Sralph 			else{
64917723Sralph 				if( mamask[mlop - OPSIMP] &
65017723Sralph 					(SIMPFLG|COMMFLG|MULFLG|DIVFLG|LOGFLG|FLOFLG|SHFFLG) ){
65117723Sralph 				binary:
65217723Sralph 					*mlsp++ = BITYPE;
65317723Sralph 					*stp++ = st;
65417723Sralph 					st = st->left;
65517723Sralph 					}
65617723Sralph 				else if( ! (mamask[mlop-OPSIMP] & UTYPE) ){/* includes OPANY */
65717723Sralph 
65817723Sralph 				leaf:
65917723Sralph 					if( mlsp == mlstack )
66017723Sralph 						goto matched;
66117723Sralph 					else if ( *--mlsp != BITYPE )
66217723Sralph 						cerror("(2)bad multi-level tree descriptor around mltree[%d]",
66317723Sralph 						n-mltree);
66417723Sralph 					st = (*--stp)->right;
66517723Sralph 					}
66617723Sralph 				else /* UNARY */ st = st->left;
66717723Sralph 				}
66817723Sralph 			continue;
66917723Sralph 
67017723Sralph 			matched:
67117723Sralph 			/* complete multi-level match successful */
67217723Sralph # ifndef BUG3
67317723Sralph 			if( vdebug ) printf("mlmatch() success\n");
67417723Sralph # endif
67517723Sralph 			if( head->mlhead.subtag == 0 ) return( MDONE );
67617723Sralph 			else {
67717723Sralph # ifndef BUG3
67817723Sralph 				if( vdebug )printf("\treturns %d\n",
67917723Sralph 					head->mlhead.subtag );
68017723Sralph # endif
68117723Sralph 				return( head->mlhead.subtag );
68217723Sralph 				}
68317723Sralph 			}
68417723Sralph 		}
68517723Sralph 	return( 0 );
68617723Sralph 	}
68717723Sralph # endif
688