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