xref: /original-bsd/old/pcc/mip/match.c (revision 4e9331e4)
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
688