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