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