|
|
1.1 root 1: /* @(#) match.c: 1.1 12/22/83 */
2:
3: # include "mfile2.h"
4:
5: int fldsz, fldshf;
6:
7: extern int zflag; /* non-zero to output stin line and cost for
8: ** each assembly instruction
9: */
10: # define VALUE (RESC1|RESC2|RESC3|RLEFT|RRIGHT)
11:
12: OPTAB *
13: match( p, q )
14: register NODE *p;
15: register OPTAB *q;
16: {
17: /* look for match in table */
18: /* given a tree, p, and a template q, returns the next template that
19: /* matches p */
20: /* q == NULL starts the process off */
21: /* match is not called recursively, so much of the setup can be done
22: /* into static variables */
23:
24: static NODE *r, *l;
25: static tl, tr, goal, tyop;
26: static pop, lflg;
27: int rr;
28:
29: if( !q ) {
30: /* startup code */
31:
32: q = ophead[pop=p->tn.op];
33: l = getlo( p, pop ); /* left child */
34: r = getro( p, pop ); /* right child */
35: tl = l->in.type;
36: tr = r->in.type;
37: lflg = asgop(pop); /* forces a match on lvalues */
38: if( p->tn.goal == CCC ) goal = (VALUE|RESCC);
39: else if( p->tn.goal == NRGS ) goal = VALUE;
40: else goal = ~0;
41: tyop = p->in.type;
42: }
43:
44: else {
45: if( fast ) return( (OPTAB *)0 ); /* only first match */
46: else q = q->nextop;
47: }
48: if( !q ) return( (OPTAB *)0 );
49:
50: # ifndef NODBG
51: if( sdebug ) {
52: printf( "match tree %d, op %s\n", p-node, opst[pop] );
53: }
54: # endif
55: for( ; q ; q = q->nextop ){
56:
57: /* some templates are no good for computing values */
58:
59: if( !( tl & q->ltype ) ) continue;
60: if( !( tr & q->rtype ) ) continue;
61:
62: if( !( goal & q->rewrite ) ) continue;
63:
64: # ifndef NODBG
65: if( sdebug ) {
66: printf( " try table entry, line %d, op %s\n",
67: q->stinline, opst[q->op] );
68: }
69: # endif
70: if( !( tyop & q->tyop ) ) {
71: # ifndef NODBG
72: if( sdebug ) {
73: printf(
74: "\tentry line %d fails tyop, %o vs %o\n",
75: q->stinline, tyop, q->tyop );
76: }
77: # endif
78: continue;
79: }
80:
81: if( q->rshape ){
82: if( rr=mspine( q->rshape, (q->lshape)?r:p, 0, sha[1] )){
83: sha[1][rr] = 0;
84: if( !q->lshape ) ustrip(pop);
85: }
86: else continue;
87: }
88: else {
89: sha[1][1] = sha[1][0] = (SHAPE *)0;
90: }
91:
92: if( q->lshape ){
93: if( !lflg && asgop(q->op) ){
94: /* q->op is an assignment op, pop isn't */
95: /* thus, the lhs => a register or temp */
96: rr = rtspine( q->lshape, p );
97: }
98: else rr = mspine( q->lshape, l, lflg, sha[0] );
99: if( rr ) sha[0][rr] = 0;
100: else continue;
101: }
102: else {
103: sha[0][1] = sha[0][0] = (SHAPE *)0;
104: }
105:
106: /* at this point, we have a match */
107:
108: # ifndef NODBG
109: if( sdebug ) {
110: printf( "table line %d matches tree %d\n",
111: q->stinline, p-node );
112: }
113: # endif
114:
115: return( q ); /* found match */
116: }
117: return( (OPTAB *)0 );
118: }
119:
120: ustrip( o )
121: {
122: /* strip out of sha[1] all shapes with op != o */
123: /* sty should do this someday, but for now, it's done here */
124: register i, j;
125:
126: for( j=i=0; sha[1][j]; ++j ) {
127: if( sha[1][j]->op == o ) sha[1][i++] = sha[1][j];
128: }
129: sha[1][i] = (SHAPE *)0;
130: }
131:
132: rtspine( ps, p )
133: SHAPE **ps;
134: NODE *p; {
135: /* special routine to put the lhs into a reg or a temp */
136: /* looks for reg and/or temp in s */
137: /* makes a list in sha[0] */
138: register rr;
139: register SHAPE *s;
140:
141: for( rr = 0; s = *ps; ++ps ) {
142: /* works because FREE, CCODES, REG, and TEMP are first */
143: switch( s->op ) {
144:
145: case FREE:
146: case CCODES:
147: continue;
148:
149: case REG:
150: case TEMP:
151: if( s->sh ) if( !spshape( s->sh, p ) ) continue;
152: if( rr >= NSHP-1 ) cerror( "too many shapes" );
153: sha[0][rr] = s;
154: ++rr;
155: continue;
156:
157: default:
158: break;
159: }
160:
161: break;
162: }
163:
164: return( rr );
165: }
166:
167: restrip( pls )
168: register SHAPE **pls;
169: {
170: /* throw away those shapes that can't be results */
171: register SHAPE **p;
172:
173: for( p=pls; *p = *pls; ++p, ++pls )
174: {
175: if( noresult( *p ) ) --p; /* overwrite if result is illegal */
176: }
177: }
178:
179: noresult( s )
180: register SHAPE *s;
181: {
182: if( !s ) return( 0 );
183: if( s->op == INCR || s->op == DECR ) return( 1 );
184: return( (s->sr && noresult(s->sr)) ||
185: (s->sl && noresult( s->sl )) );
186: }
187:
188: smspine( s, p, flag )
189: register NODE *p;
190: register SHAPE *s;
191: {
192: /* match the spine of s, including special shapes */
193: /* this is a submatch, called only by mspine */
194: /* flag is nonzero if STAR's must be skipped */
195:
196: register sop, pop;
197:
198: again:
199:
200: sop = s->op;
201: pop = p->tn.op;
202:
203: # ifndef NODBG
204: if( sdebug>1 )
205: {
206: printf( " smspine(%d[%s], %d[%s])\n",
207: s-shapes, opst[sop], p-node, opst[pop] );
208: }
209: # endif
210:
211: if( ( s->sh ) && !spshape( s->sh,p) ) return( 0 );
212: if( sop != pop )
213: {
214: if( sop == CCODES || sop == FREE ) return(1);
215: return( !flag && (sop==REG || sop==TEMP) );
216: }
217: if( sop == STAR )
218: {
219: flag = 0;
220: goto recurse;
221: }
222: switch( optype( sop ) )
223: {
224:
225: case BITYPE:
226: if( !smspine( s->sr, p->in.right, 0 ) ) return(0);
227: flag = asgop(sop);
228: /* FALLTHRU */
229:
230: case UTYPE:
231: recurse:
232: s = s->sl;
233: p = p->in.left;
234: goto again;
235:
236: default:
237: return( 1 );
238: }
239: }
240:
241: mspine( ps, p, flag, ppls )
242: register NODE *p;
243: register SHAPE **ps;
244: register SHAPE **ppls;
245: {
246: /* match the spine of s, including special shapes */
247: /* s points to a list of shapes */
248: /* those shapes that match are copied into **ppls, with a null at end */
249: /* flag = 1 forces regs and temps to match exactly */
250: /* rr, the number of matches, is returned */
251:
252: register SHAPE *s;
253: int pop, rr;
254:
255: # ifndef NODBG
256: if( sdebug )
257: {
258: printf( "\tmspine( %d, %d, %d )\n", ps-pshape, p-node, flag );
259: }
260: # endif
261: pop = p->tn.op;
262:
263: /* copy the wild-cards, and those where the op matches */
264: for( rr=0; s = *ps; ++ps )
265: {
266: switch( s->op )
267: {
268:
269: case REG:
270: case TEMP:
271: if( flag ) break;
272: if( s->sh ) if( !spshape(s->sh,p) ) continue;
273: /* FALLTHRU */
274:
275: case FREE:
276: case CCODES:
277: if( rr >= NSHP-1 ) cerror( "too many shapes" );
278:
279: # ifndef NODBG
280: if( sdebug )
281: {
282: printf(
283: "\t\tmspine( %d[%s], %d[%s] ), becomes %d\n",
284: s-shapes, opst[s->op], p-node,
285: opst[pop], rr );
286: }
287: # endif
288:
289: ppls[rr++] = s;
290: continue;
291:
292: default:
293: break;
294: }
295: break;
296: }
297:
298: /* now, either s is 0 or s has a "real" op */
299: /* the first condition survives the next two loops */
300:
301: /* we have matched the wild cards: find others where the op matches */
302:
303: for( ; (s= *ps) && s->op != pop; ++ps )
304: {
305: ;
306: }
307:
308: /* now, s is null or matches the op of p */
309: for( ; (s = *ps) && s->op == pop; ++ps )
310: {
311:
312: if( pop == STAR )
313: {
314: if( !smspine( s->sl, p->in.left, 0 ) ) continue;
315: }
316:
317: /* general case: check the subtrees also */
318: else if( s->sl )
319: {
320: if( s->sr )
321: {
322: if( !smspine( s->sr, p->in.right, 0 ) )
323: continue;
324: if( !smspine( s->sl, p->in.left, asgop(s->op)) )
325: continue;
326: }
327: else
328: {
329: if( !smspine( s->sl, p->in.left, flag ))
330: continue;
331: }
332: }
333: else if( s->sr && !smspine( s->sr, p->in.right, 0 ) )
334: continue;
335:
336: /* if we get this far, we are in good shape */
337:
338: if( s->sh ) if( !spshape( s->sh, p ) ) continue;
339: if( rr >= NSHP-1 ) cerror( "too many shapes" );
340:
341: # ifndef NODBG
342: if( sdebug )
343: {
344: printf( "\t\tmspine( %d[%s], %d[%s] ), becomes %d\n",
345: s-shapes, opst[s->op], p-node,
346: opst[pop], rr );
347: }
348: # endif
349:
350: ppls[rr++] = s;
351: }
352:
353: /* fall out and we are done */
354: return( rr );
355: }
356:
357:
358: tempok( p )
359: NODE *p;
360:
361: {
362: /* decide if the result of p is OK as a temp */
363: int o;
364: if( (o = p->tn.op) == TEMP ) return( 1 );
365: if( asgop(o) && o!=INCR && o!=DECR )
366: {
367: return( p->in.left->tn.op == TEMP );
368: }
369: return( 0 );
370: }
371:
372: int sideff;
373:
374: rmside( p )
375: NODE *p;
376:
377: {
378: /* p is a tree with side effects: remove them */
379: /* this is done in place */
380: int o;
381: NODE *q;
382:
383: o = p->tn.op;
384: switch( o )
385: {
386:
387: case INCR:
388: case DECR:
389: case ASG PLUS:
390: case ASG MINUS:
391: if( p->in.right->tn.op == ICON ) p->in.right->tn.op = FREE;
392: else
393: {
394: regrcl( p->in.right );
395: tfree( p->in.right );
396: }
397: q = p->in.left;
398: *p = *q;
399: q->tn.op = FREE;
400: rmside( p );
401: return;
402: }
403:
404: switch( optype( o ) )
405: {
406:
407: case BITYPE:
408: rmside( p->in.right );
409: case UTYPE:
410: rmside( p->in.left );
411: }
412: }
413:
414: expand( p, goal, cp, q )
415: NODE *p;
416: char *cp;
417: OPTAB *q;
418: {
419: /* generate code by interpreting table entry */
420:
421: CONSZ val;
422: NODE *q1, *q2;
423: int c;
424: TWORD t;
425:
426: #ifdef GDEBUG
427: if ((c = p->stn.op) == CALL || c == UNARY CALL)
428: dbnargs(p->stn.argsize);
429: #endif
430: for( ; *cp; ++cp )
431: {
432: switch( *cp )
433: {
434:
435: case '\\':
436: ++cp;
437: /* FALLTHRU */
438: default:
439: PUTCHAR( *cp );
440: continue; /* this is the usual case... */
441:
442: case '\n':
443: if( zflag )
444: { /* add stin line number of production as a comment */
445: printf( "\t\t%s %d", COMMENTSTR, q->stinline );
446: if( p->in.cst[CEFF] < INFINITY )
447: printf( " = %d", p->in.cst[CEFF] );
448: }
449: PUTCHAR( *cp );
450: continue;
451:
452: case 'Y':
453: /* don't check this string: deleted by match */
454: continue;
455:
456: case 'Z': /* special machine dependent operations */
457: zzzcode( p, &cp, q );
458: continue;
459:
460: case 'E': /* exit */
461: if( zflag )
462: { /* add stin line number of production as a comment */
463: printf( "\t%s\t%d = %d",
464: COMMENTSTR, q->stinline, p->in.cst[CEFF] );
465: }
466: PUTCHAR( '\n' );
467: return;
468:
469: # ifndef STACK
470: case 'D': /* test for dependency */
471: q1 = getadr( p, &cp );
472: if( cp[1] == '!' )
473: {
474: c=0;
475: ++cp;
476: }
477: else c=1;
478: q2 = getadr( p, &cp );
479: if( q1->tn.op != REG ) cerror( "bad D" );
480: if( ushare( q2, q1->tn.rval ) == c ) continue;
481: goto cream;
482: # endif
483:
484: case 'R': /* put an operand into a particular register */
485: /* if the operand is in the register, delete the line */
486: q1 = getadr( p, &cp );
487: c = (*++cp == '=');
488: q2 = getadr( p, &cp );
489: if( q1->tn.op != REG )
490: {
491: if( c ) goto cream;
492: continue;
493: }
494: if( q2->tn.op != REG )
495: {
496: if( c ) goto cream;
497: continue;
498: }
499: if( q1->tn.rval != q2->tn.rval )
500: {
501: if( c ) goto cream;
502: continue;
503: }
504: if( c ) continue;
505: cream:
506: /* clobber a line to newline, or up to an E */
507: while( *++cp != '\n' && *cp != 'E' )
508: {
509: if( *cp == '\\' ) ++cp; /* hide next char */
510: if( !*cp ) return;
511: }
512: continue;
513:
514: case 'F': /* this line deleted if FOREFF is active */
515: if( goal & FOREFF ) goto cream;
516: continue;
517:
518: case 'S': /* field size */
519: case 'H': /* field shift */
520: case 'M': /* field mask, in place */
521: case 'N': /* field mask, right shifted */
522: c = *cp;
523: if( cp[1] == '~' )
524: {
525: if( c == 'M' ) c = 'm';
526: else if( c == 'N' ) c = 'n';
527: else cerror( "bad ~ after S or H" );
528: ++cp;
529: }
530: else if( cp[1] == '?' )
531: {
532: if( c == 'H' ) c = 'h';
533: else cerror( "bad ? after S, M, or N" );
534: ++cp;
535: }
536: q1 = getadr(p,&cp);
537: if( q1->tn.op != FLD ) cerror( "bad FLD for %c", c );
538: fldsz = UPKFSZ(q1->tn.rval);
539: # ifdef RTOLBYTES
540: fldshf = UPKFOFF(q1->tn.rval);
541: # else
542: t = q1->tn.type;
543: if( t & (TLONG|TULONG) )
544: {
545: fldshf = SZLONG - fldsz - UPKFOFF(q1->tn.rval);
546: }
547: else if( t & (TSHORT|TUSHORT) )
548: {
549: fldshf = SZSHORT - fldsz - UPKFOFF(q1->tn.rval);
550: }
551: else if( t & (TCHAR|TUCHAR) )
552: {
553: fldshf = SZCHAR - fldsz - UPKFOFF(q1->tn.rval);
554: }
555: else fldshf = SZINT - fldsz - UPKFOFF(q1->tn.rval);
556: # endif
557: if( c == 'h' )
558: {
559: if( fldshf == 0 ) goto cream;
560: continue;
561: }
562: if( c=='S' || c=='H' )
563: {
564: printf( "%d", c=='S' ? fldsz : fldshf );
565: continue;
566: }
567: val = 1;
568: val <<= fldsz;
569: --val;
570: if( c=='M' || c == 'm' ) val <<= fldshf;
571: if( c=='m' || c == 'n' ) val = ~val;
572: # ifdef MYMASK
573: MYMASK(val);
574: # else
575: printf( "%ld" , val );
576: # endif
577: continue;
578:
579: case 'L': /* output special label field */
580: printf( "%d", p->bn.label );
581: continue;
582:
583: case 'C': /* for constant value only */
584: conput( q1 = getadr( p, &cp ) );
585: if( !sideff ) cerror( "constant with side effects?" );
586: continue;
587:
588: case 'I': /* in instruction */
589: insput( q1 = getadr( p, &cp ) );
590: if( sideff ) rmside( q1 );
591: continue;
592:
593: case 'A': /* address of */
594: adrput( q1 = getadr( p, &cp ) );
595: if( sideff ) rmside( q1 );
596: continue;
597:
598: case 'U': /* for upper half of address, only */
599: upput( q1 = getadr( p, &cp ) );
600: if( sideff ) rmside( q1 );
601: continue;
602: #ifdef TMPSRET
603: case 'T': /* grab a temp for structure return and give it */
604: /* to adrput */
605: q1 = talloc();
606: q1->tn.op = TEMP;
607: q1->tn.type = TSTRUCT;
608: q1->tn.lval = freetemp(p->stn.stsize / SZINT);
609: q1->tn.lval = BITOOR(q1->tn.lval);
610: adrput(q1);
611: tfree(q1);
612: continue;
613: #endif
614:
615: }
616: }
617: }
618:
619: NODE *
620: getlr( p, c )
621: NODE *p;
622:
623: {
624:
625: /* return the pointer to the left or right side of p, or p itself,
626: ** depending on the optype of p
627: */
628:
629: switch( c )
630: {
631:
632: case '1':
633: case '2':
634: case '3':
635: return( &resc[c-'1'] );
636:
637: case 'L':
638: return( optype( p->in.op ) == LTYPE ? p : p->in.left );
639:
640: case 'R':
641: return( optype( p->in.op ) != BITYPE ? p : p->in.right );
642:
643: }
644: cerror( "bad getlr: %c", c );
645: /* NOTREACHED */
646: }
647:
648: NODE *
649: getadr( p, pc )
650: NODE *p;
651: char **pc;
652:
653: {
654: /* like getlr, but allows (LL), (LR), etc. */
655: int c;
656: sideff = 1;
657: c = *++(*pc);
658: if( c == '-' )
659: {
660: c = *++(*pc);
661: sideff = 0;
662: }
663: if( c == '.' ) return( p );
664: else if( c != '(' ) return( getlr( p, c ) );
665:
666: for(;;)
667: {
668: switch( c = *++(*pc) )
669: {
670:
671: case ')':
672: return( p );
673:
674: case 'L':
675: p = getl( p );
676: continue;
677:
678: case 'R':
679: p = getr( p );
680: continue;
681:
682: default:
683: cerror( "bad table char in (): %c", c );
684: }
685: }
686: /* NOTREACHED */
687: }
688:
689: long pow2[] =
690: {
691: 01L, 02L, 04L,
692: 010L, 020L, 040L,
693: 0100L, 0200L, 0400L,
694: 01000L, 02000L, 04000L,
695: 010000L, 020000L, 040000L,
696: 0100000L, 0200000L, 0400000L,
697: 01000000L, 02000000L, 04000000L,
698: 010000000L, 020000000L, 040000000L,
699: 0100000000L, 0200000000L, 0400000000L,
700: 01000000000L, 02000000000L, 04000000000L,
701: 010000000000L, 020000000000L, 040000000000L,
702: };
703:
704: spshape( sh, p )
705: NODE *p;
706:
707: {
708: long val;
709: int t, i;
710:
711: if( !(sh&SPECIAL) ) cerror( "spshape" );
712: if( sh&SPTYPE )
713: {
714: # ifndef NODBG
715: if( sdebug )
716: printf( "SPTYPE(%d, %o), ttype=%o\n", p-node,
717: sh, p->tn.type );
718: # endif
719:
720: if( sh & p->tn.type ) return( 1 );
721: else return( 0 );
722: }
723: t = (sh&STMASK);
724: i = (sh&SVMASK);
725:
726: switch( t )
727: {
728:
729: case SRANGE0:
730: case SSRANGE:
731: if( i<0 || i>31 ) cerror( "bad shape range" );
732: case SVAL:
733: case SNVAL:
734: case NACON:
735:
736: if( p->tn.op != ICON || p->tn.name != (char *) 0 ) return( 0 );
737: if( t == NACON ) return(1);
738: val = p->tn.lval;
739: if( t==SVAL && val == i ) return( 1 );
740: else if( t==SNVAL && val == -i ) return( 1 );
741: else if( t==SRANGE0 && val>=0 && val<pow2[i] ) return( 1 );
742: else if( t==SSRANGE && val>= -pow2[i] && val<pow2[i] )return(1);
743: return( 0 );
744:
745: case SUSER:
746: return( special( sh, p ) );
747:
748: default:
749: cerror( "bad special call" );
750: /* NOTREACHED */
751: }
752: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.