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