File:  [Research Unix] / researchv9 / cmd / sun / mip / match.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:59 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#ifndef lint
static	char sccsid[] = "@(#)match.c 1.1 86/02/03 SMI";
#endif

# include "cpass2.h"

# ifdef WCARD1
# ifdef WCARD2
# define NOINDIRECT
# endif
# endif

extern vdebug;

int fldsz, fldshf;

int mamask[] = { /* masks for matching dope with shapes */
	SIMPFLG,	/* OPSIMP */
	SIMPFLG|ASGFLG,	/* ASG OPSIMP */
	COMMFLG,	/* OPCOMM */
	COMMFLG|ASGFLG,	/* ASG OPCOMM */
	MULFLG,		/* OPMUL */
	MULFLG|ASGFLG,	/* ASG OPMUL */
	DIVFLG,		/* OPDIV */
	DIVFLG|ASGFLG,	/* ASG OPDIV */
	UTYPE,		/* OPUNARY */
	TYFLG,		/* ASG OPUNARY is senseless */
	LTYPE,		/* OPLEAF */
	TYFLG,		/* ASG OPLEAF is senseless */
	0,		/* OPANY */
	ASGOPFLG|ASGFLG,/* ASG OPANY */
	LOGFLG,		/* OPLOG */
	TYFLG,		/* ASG OPLOG is senseless */
	FLOFLG,		/* OPFLOAT */
	FLOFLG|ASGFLG,	/* ASG OPFLOAT */
	SHFFLG,		/* OPSHFT */
	SHFFLG|ASGFLG,	/* ASG OPSHIFT */
	SPFLG,		/* OPLTYPE */
	TYFLG,		/* ASG OPLTYPE is senseless */
	INTRFLG,	/* OPINTR */
	TYFLG,		/* ASG OPINTR is senseless */
};

int sdebug = 0;

tshape( p, shape ) 
	register NODE *p;
{
	/*
	 * return true if shape is appropriate for the node p
	 * side effect for SFLD is to set up fldsz,etc
	 */
	register o, mask;
	register lval;

	o = p->in.op;

# ifndef BUG3
	if ( sdebug ){
		printf( "tshape( %o, %o), op = %d\n", p, shape, o );
	}
# endif

	if ( shape & SPECIAL ){
		switch ( shape ){
		case SZERO:
			if ( o != ICON || p->in.name[0] ) return(0);
			return(p->tn.lval == 0);
		case SONE:
			if ( o != ICON || p->in.name[0] ) return(0);
			return(p->tn.lval == 1);
		case SMONE:
			if ( o != ICON || p->in.name[0] ) return(0);
			return(p->tn.lval == -1);
		case SSCON:
			if ( o != ICON || p->in.name[0] ) return(0);
			lval = p->tn.lval;
			return(lval >= -32768 && lval <= 32767);
		case SCCON:
			if ( o != ICON || p->in.name[0] ) return(0);
			lval = p->tn.lval;
			return(lval >= -128 && lval <= 127);
		case SSOREG:	/* non-indexed OREG */
			return(o == OREG && !R2TEST(p->tn.rval));

		default:
# ifdef MULTILEVEL
			if ( shape & MULTILEVEL )
				return( mlmatch(p,shape,0) );
			else
# endif
			return (special( p, shape ));
		}
	}
	if ( shape & SANY ) return(1);
	if ( (shape&INTEMP) && shtemp(p) ) return(1);
	if ( (shape&SWADD) && (o==NAME||o==OREG) ){
		if ( BYTEOFF(p->tn.lval) ) return(0);
	}

# ifdef WCARD1
	if ( shape & WCARD1 )
		return( wcard1(p) & shape );
# endif

# ifdef WCARD2
	if ( shape & WCARD2 )
		return( wcard2(p) & shape );
# endif
	switch( o ){
	case NAME:
		return( shape&SNAME );
	case FCON:
	case ICON:
		mask = SCON;
		return( shape & mask );
	case FLD:
		if ( shape & SFLD ){
			if ( !flshape( p->in.left ) ) return(0);
			/* it is a FIELD shape; make side-effects */
			o = p->tn.rval;
			fldsz = UPKFSZ(o);
# ifdef RTOLBYTES
			fldshf = UPKFOFF(o);
# else
			fldshf = SZINT - fldsz - UPKFOFF(o);
# endif
			return(1);
		}
		return(0);
	case FCCODES:
	case CCODES:
		return( shape&SCC );
	case REG:
		/* distinctions:
		 * SAREG	any scalar register
		 * STAREG	any temporary scalar register
		 * SBREG	any lvalue (index) register
		 * STBREG	any temporary lvalue register
		 * SCREG	any floating register
		 * STCREG	any temporary floating register
		 */
		if (isbreg( p->tn.rval ))
			mask = SBREG; 
		else if (iscreg( p->tn.rval ))
			mask = SCREG; 
		else 
			mask = SAREG; 
		if ( istreg( p->tn.rval ) && busy[p->tn.rval]<=1 ) {
			if (mask==SAREG)
				mask |= STAREG;
			else if (mask==SBREG)
				mask |= STBREG;
			else
				mask |= STCREG;
		}
		return( shape & mask );
	case OREG:
		return( shape & SOREG );

# ifndef NOINDIRECT
	case UNARY MUL:
		/* return STARNM or STARREG or 0 */
		return( shumul(p->in.left) & shape );
# endif

	}

	return(0);
}

int tdebug = 0;

ttype( t, tword ) 
	register TWORD t;
	register tword;
{
	/* does the type t match tword */

	if ( tword & TANY ) return(1);
	if ( t == UNDEF ) t=INT; /* void functions eased thru tables */
# ifndef BUG3
	if ( tdebug ){
		printf( "ttype( %o, %o )\n", t, tword );
	}
# endif
	if ( ISPTR(t) && (tword&TPTRTO) ) {
		do {
			t = DECREF(t);
		} while ( ISARY(t) );
		/* arrays that are left are usually only
		   in structure references... */
		return( ttype( t, tword&(~TPTRTO) ) );
	}
	if ( t != BTYPE(t) )
		return( tword & TPOINT );	/* TPOINT means not simple! */
	if ( tword & TPTRTO ) return(0);
	switch( t ){
	case CHAR:
		return( tword & TCHAR );
	case SHORT:
		return( tword & TSHORT );
	case STRTY:
	case UNIONTY:
		return( tword & TSTRUCT );
	case INT:
		return( tword & TINT );
	case UNSIGNED:
		return( tword & TUNSIGNED );
	case USHORT:
		return( tword & TUSHORT );
	case UCHAR:
		return( tword & TUCHAR );
	case ULONG:
		return( tword & TULONG );
	case LONG:
		return( tword & TLONG );
	case FLOAT:
		return( tword & TFLOAT );
	case DOUBLE:
		return( tword & TDOUBLE );
	}
	return(0);
}

#define MAXOPSET 2000

struct opvect {
	struct optab **first;
	struct optab **rewrite;
};

struct opvect opvect[DSIZE];
struct optab *opsets[MAXOPSET];

static struct optab **firstelement= opsets;
static struct optab **nextelement = opsets;

extern int opmatch(/* op, targetop */);	/* returns 1 if op matches targetop */

/*
 * setrew()
 *	Generates sets of templates to be examined by match(), one
 *	for each operator in 0..DSIZE.  The sets are represented as
 *	vectors of pointers into the code table.  The sets could be
 *	constructed by a separate program when the compiler is compiled,
 *	but doing it at startup enables us to deal more conveniently
 *	with user-selected processor options (e.g., -m68020 -m68881)
 */

setrew()
{
	register struct optab *q;
	register int op;
	register struct optab **nextel = nextelement;
	register struct optab **firstel = firstelement;

	for( op = 0; op < DSIZE; ++op ) {
		if (dope[op]) {
			/*
			 * operator exists;
			 * scan table for matching templates
			 */
			register struct optab **firstrew;
			firstrew = (struct optab**)NULL;
			for (q = table; q->op != FREE; q++) {
				if (opmatch(op, q->op)) {
					if (q->needs == REWRITE) {
						if (!firstrew) {
							firstrew = nextel;
						}
					}
					*nextel++ = q;
				}
			}
			if (nextel-opsets >= MAXOPSET) {
				cerror("too many opsets (%d)",
					nextel-opsets);
			}
			opvect[op].first = firstel;
			opvect[op].rewrite = firstrew;
			*nextel++ = (struct optab*)NULL;
			firstel = nextel;
		} else {
			/* no operator */
			opvect[op].first = (struct optab**)NULL;
			opvect[op].rewrite = (struct optab**)NULL;
		} /* else */
	} /* for each op */
	nextelement = nextel;
	firstelement = firstel;
} /* setrew */

match( p, cookie ) 
	NODE *p; 
{
	/*
	 * called by: order, gencall
	 * look for match in table and generate code if found unless
	 * entry specified REWRITE.
	 * returns MDONE, MNOPE, or rewrite specification from table 
	 */

	register struct optab **opset;
	register struct optab *q;
	register op;
	register NODE *r;

	rcount();
	op = p->in.op;
	if (cookie == FORREW) {
		opset = opvect[op].rewrite;
	} else {
		opset = opvect[op].first;
		/*
		 * finish the special-case test for autoincrement trees
		 */
		if (op == UNARY MUL && !shumul(p->in.left)) {
			return(MNOPE);
		}
	}
	if (opset == (struct optab**)NULL) {
		cerror("no template for op '%s'", opst[op]);
	}
	for (q = *opset++; q != (struct optab *)NULL; q = *opset++) {

		/* see if goal matches */
		if ( !(q->visit & cookie ) ) continue;

		/* see if left child matches */
		r = ( optype( op ) == LTYPE ? p : p->in.left );
		if ( !tshape( r, q->lshape ) )
			continue;
		if ( !ttype( r->in.type, q->ltype ) ) 
			continue;

		/* see if right child matches */
		r = ( optype( op ) != BITYPE ? p : p->in.right );
		if ( !tshape( r, q->rshape ) )
			continue;
		if ( !ttype( r->in.type, q->rtype ) )
			continue;

		/*
		 * REWRITE means no code from this match but go ahead
		 * and rewrite node to help future match.
		 */
		if ( q->needs & REWRITE )
			return( q->rewrite );
		if ( !allo( p, q ) )
			continue;	/* if can't generate code, skip entry */

		/* resources are available */

		/* generate code */
		expand( p, cookie, q->cstring );
		reclaim( p, q->rewrite, cookie );

		return(MDONE);

	}

	return(MNOPE);
}

int rtyflg = 0;

expand( p, cookie, cp )
	NODE *p; 
	register char *cp;
{
	/* generate code by interpreting table entry */

	register char c;
	CONSZ val;

	rtyflg = 0;

	for( ; *cp; ++cp ){
		switch( *cp ){

		case '\\':
			cp++;
			/* FALL THROUGH */
		default:
			PUTCHAR( *cp );
			continue;  /* this is the usual case... */
		case 'T':
			/* rewrite register type is suppressed */
			rtyflg = 1;
			continue;

		case 'Z':  /* special machine dependent operations */
# ifdef NEWZZZ
			switch( c = *++cp ) {

			case '1':
			case '2':
			case '3':
			case 'R':
			case 'L':	/* get down first */
				zzzcode( getlr( p, c ), *++cp );
				break;
			default:   /* normal zzzcode processing otherwise */
				zzzcode( p, c );
				break;
			}
# else
			zzzcode( p, *++cp, cookie );
# endif
			continue;

		case 'F':  /* this line deleted if FOREFF is active */
			if ( cookie & FOREFF )
				while( *++cp != '\n' )
					; /* VOID */
			continue;

#ifdef undef
		case 'R': /* this line deleted if descendent is already in a temp register */
			{
			NODE * t;

			t = getlr(p, *++cp );
			if ( istnode(t) )
				while( *++cp != '\n' )
					; /* VOID */
			continue;
			}
#endif sun
		case 'S':  /* field size */
			print_d(fldsz );
			continue;

		case 'H':  /* field shift */
			print_d( fldshf );
			continue;

		case 'M':  /* field mask */
		case 'N':  /* complement of field mask */
			val = 1;
			val <<= fldsz;
			--val;
			val <<= fldshf;
			adrcon( *cp=='M' ? val : ~val );
			continue;

		case 'L':  /* output special label field */
			print_d( p->bn.label );
			continue;

		case 'O':  /* opcode string */
			hopcode( *++cp, p->in.op );
			continue;

		case 'B':  /* byte offset in word */
			val = getlr(p,*++cp)->tn.lval;
			val = BYTEOFF(val);
			printf( CONFMT, val );
			continue;

		case 'C': /* for constant value only */
			conput( getlr( p, *++cp ) );
			continue;

		case 'I': /* in instruction */
			insput( getlr( p, *++cp ) );
			continue;

		case 'A': /* address of */
			adrput( getlr( p, *++cp ) );
			continue;

		case 'U': /* for upper half of address, only */
			upput( getlr( p, *++cp ) );
			continue;

		}

	}

}

NODE *
getlr( p, c )
	NODE *p;
{

	/*
	 * return the pointer to the left or right side of p, or p itself,
	 * depending on the optype of p
	 */

	switch ( c ) {

	case '1':
	case '2':
	case '3':
		return ( &resc[c-'1'] );

	case 'L':
		return ( optype( p->in.op ) == LTYPE ? p : p->in.left );

	case 'R':
		return ( optype( p->in.op ) != BITYPE ? p : p->in.right );

	case '.':
		return ( p );

	}
	cerror( "bad getlr: %c", c );
	/* NOTREACHED */
}

# ifdef MULTILEVEL

union mltemplate{
	struct ml_head{
		int tag; /* identifies class of tree */
		int subtag; /* subclass of tree */
		union mltemplate * nexthead; /* linked by mlinit() */
		} mlhead;
	struct ml_node{
		int op; /* either an operator or op description */
		int nshape; /* shape of node */
		/* both op and nshape must match the node.
		 * where the work is to be done entirely by
		 * op, nshape can be SANY, visa versa, op can
		 * be OPANY.
		 */
		int ntype; /* type descriptor from mfile2 */
		} mlnode;
	};

# define MLSZ 30

extern union mltemplate mltree[];
int mlstack[MLSZ];
int *mlsp; /* pointing into mlstack */
NODE * ststack[MLSZ];
NODE **stp; /* pointing into ststack */

mlinit(){
	union mltemplate **lastlink;
	register union mltemplate *n;
	register mlop;

	lastlink = &(mltree[0].nexthead);
	n = &mltree[0];
	for( ; (n++)->mlhead.tag != 0;
		*lastlink = ++n, lastlink = &(n->mlhead.nexthead) ){
# ifndef BUG3
		if ( vdebug )print_str_d_nl("mlinit: ",(n-1)->mlhead.tag);
# endif
	/* wander thru a tree with a stack finding
	 * its structure so the next header can be located.
	 */
		mlsp = mlstack;

		for( ;; ++n ){
			if ( (mlop = n->mlnode.op) < OPSIMP ){
				switch( optype(mlop) ){

					default:
						cerror("(1)unknown opcode: %o",mlop);
					case BITYPE:
						goto binary;
					case UTYPE:
						break;
					case LTYPE:
						goto leaf;
					}
				}
			else{
				if ( mamask[mlop-OPSIMP] &
					(SIMPFLG|COMMFLG|MULFLG|DIVFLG|LOGFLG|FLOFLG|SHFFLG) ){
				binary:
					*mlsp++ = BITYPE;
					}
				else if ( ! (mamask[mlop-OPSIMP] & UTYPE) ){/* includes OPANY */

				leaf:
					if ( mlsp == mlstack )
						goto tree_end;
					else if ( *--mlsp != BITYPE )
						cerror("(1)bad multi-level tree descriptor around mltree[%d]",
						n-mltree);
					}
				}
			}
		tree_end: /* n points to final leaf */
		;
		}
# ifndef BUG3
		if ( vdebug > 3 ){
			print_str("mltree={\n");
			for( n= &(mltree[0]); n->mlhead.tag != 0; ++n)
				printf("%o: %d, %d, %o,\n",n,
				n->mlhead.tag,n->mlhead.subtag,n->mlhead.nexthead);
			print_str("	}\n");
			}
# endif
	}

mlmatch( subtree, target, subtarget ) NODE * subtree; int target,subtarget;{
	/*
	 * does subtree match a multi-level tree with
	 * tag "target"?  Return zero on failure,
	 * non-zero subtag on success (or MDONE if
	 * there is a zero subtag field).
	 */
	union mltemplate *head; /* current template header */
	register union mltemplate *n; /* node being matched */
	NODE * st; /* subtree being matched */
	register int mlop;

# ifndef BUG3
	if ( vdebug ) printf("mlmatch(%o,%d)\n",subtree,target);
# endif
	for( head = &(mltree[0]); head->mlhead.tag != 0;
		head=head->mlhead.nexthead){
# ifndef BUG3
		if ( vdebug > 1 )printf("mlmatch head(%o) tag(%d)\n",
			head->mlhead.tag);
# endif
		if ( head->mlhead.tag != target )continue;
		if ( subtarget && head->mlhead.subtag != subtarget)continue;
# ifndef BUG3
		if ( vdebug ) print_str_d_nl("mlmatch for ",target);
# endif

		/* potential for match */

		n = head + 1;
		st = subtree;
		stp = ststack;
		mlsp = mlstack;
		/* compare n->op, ->nshape, ->ntype to
		 * the subtree node st
		 */
		for( ;; ++n ){ /* for each node in multi-level template */
			/* opmatch */
			if ( n->op < OPSIMP ){
				if ( st->op != n->op )break;
				}
			else {
				register opmtemp;
				if ((opmtemp=mamask[n->op-OPSIMP])&SPFLG){
					if (st->op!=NAME && st->op!=ICON && st->op!=OREG && 
						! shltype(st->op,st)) break;
					}
				else if ((dope[st->op]&(opmtemp|ASGFLG))!=opmtemp) break;
				}
			/* check shape and type */

			if ( ! tshape( st, n->mlnode.nshape ) ) break;
			if ( ! ttype( st->type, n->mlnode.ntype ) ) break;

			/* that node matched, let's try another */
			/* must advance both st and n and halt at right time */

			if ( (mlop = n->mlnode.op) < OPSIMP ){
				switch( optype(mlop) ){

					default:
						cerror("(2)unknown opcode: %o",mlop);
					case BITYPE:
						goto binary;
					case UTYPE:
						st = st->left;
						break;
					case LTYPE:
						goto leaf;
					}
				}
			else{
				if ( mamask[mlop - OPSIMP] &
					(SIMPFLG|COMMFLG|MULFLG|DIVFLG|LOGFLG|FLOFLG|SHFFLG) ){
				binary:
					*mlsp++ = BITYPE;
					*stp++ = st;
					st = st->left;
					}
				else if ( ! (mamask[mlop-OPSIMP] & UTYPE) ){/* includes OPANY */

				leaf:
					if ( mlsp == mlstack )
						goto matched;
					else if ( *--mlsp != BITYPE )
						cerror("(2)bad multi-level tree descriptor around mltree[%d]",
						n-mltree);
					st = (*--stp)->right;
					}
				else /* UNARY */ st = st->left;
				}
			continue;

			matched:
			/* complete multi-level match successful */
# ifndef BUG3
			if ( vdebug ) print_str("mlmatch() success\n");
# endif
			if ( head->mlhead.subtag == 0 ) return( MDONE );
			else {
# ifndef BUG3
				if ( vdebug )print_str_d_nl("\treturns ",
					head->mlhead.subtag );
# endif
				return( head->mlhead.subtag );
				}
			}
		}
	return( 0 );
	}
# endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.