static char *sccsid
="%W% (Berkeley) %G%";
static int mamask
[] = { /* masks for matching dope with shapes */
SIMPFLG
|ASGFLG
, /* ASG OPSIMP */
COMMFLG
|ASGFLG
, /* ASG OPCOMM */
MULFLG
|ASGFLG
, /* ASG OPMUL */
DIVFLG
|ASGFLG
, /* ASG OPDIV */
TYFLG
, /* ASG OPUNARY is senseless */
TYFLG
, /* ASG OPLEAF is senseless */
ASGOPFLG
|ASGFLG
, /* ASG OPANY */
TYFLG
, /* ASG OPLOG is senseless */
FLOFLG
|ASGFLG
, /* ASG OPFLOAT */
SHFFLG
|ASGFLG
, /* ASG OPSHIFT */
TYFLG
, /* ASG OPLTYPE is senseless */
tshape( p
, shape
) NODE
*p
; {
/* return true if shape is appropriate for the node p
side effect for SFLD is to set up fldsz,etc */
printf( "tshape( %o, %o), op = %d\n", p
, shape
, o
);
if( o
!= ICON
|| p
->in
.name
[0] ) return(0);
if( p
->tn
.lval
== 0 && shape
== SZERO
) return(1);
else if( p
->tn
.lval
== 1 && shape
== SONE
) return(1);
else if( p
->tn
.lval
== -1 && shape
== SMONE
) return(1);
else if( p
->tn
.lval
> -257 && p
->tn
.lval
< 256 && shape
== SCCON
) return(1);
else if( p
->tn
.lval
> -32769 && p
->tn
.lval
< 32768 && shape
== SSCON
) return(1);
case SSOREG
: /* non-indexed OREG */
if( o
== OREG
&& !R2TEST(p
->tn
.rval
) ) return(1);
return( mlmatch(p
,shape
,0) );
return( special( p
, shape
) );
if( shape
& SANY
) return(1);
if( (shape
&INTEMP
) && shtemp(p
) ) return(1);
if( (shape
&SWADD
) && (o
==NAME
||o
==OREG
) ){
if( BYTEOFF(p
->tn
.lval
) ) return(0);
return( wcard1(p
) & shape
);
return( wcard2(p
) & shape
);
if( !flshape( p
->in
.left
) ) return(0);
/* it is a FIELD shape; make side-effects */
fldshf
= SZINT
- fldsz
- UPKFOFF(o
);
SAREG any scalar register
STAREG any temporary scalar register
SBREG any lvalue (index) register
STBREG any temporary lvalue register
mask
= isbreg( p
->tn
.rval
) ? SBREG
: SAREG
;
if( istreg( p
->tn
.rval
) && busy
[p
->tn
.rval
]<=1 ) mask
|= mask
==SAREG
? STAREG
: STBREG
;
/* return STARNM or STARREG or 0 */
return( shumul(p
->in
.left
) & shape
);
ttype( t
, tword
) TWORD t
; {
/* does the type t match tword */
if( tword
& TANY
) return(1);
if( t
== UNDEF
) t
=INT
; /* void functions eased thru tables */
printf( "ttype( %o, %o )\n", t
, tword
);
if( ISPTR(t
) && (tword
&TPTRTO
) ) {
/* arrays that are left are usually only
in structure references... */
return( ttype( t
, tword
&(~TPTRTO
) ) );
if( t
!= BTYPE(t
) ) return( tword
& TPOINT
); /* TPOINT means not simple! */
if( tword
& TPTRTO
) return(0);
return( tword
& TSHORT
);
return( tword
& TSTRUCT
);
return( tword
& TUNSIGNED
);
return( tword
& TUSHORT
);
return( tword
& TUCHAR
);
return( tword
& TULONG
);
return( tword
& TFLOAT
);
return( tword
& TDOUBLE
);
struct optab
*opptr
[DSIZE
];
/* set rwtable to first value which allows rewrite */
register struct optab
*q
;
/* also initialize multi-level tree links */
for( q
= table
; q
->op
!= FREE
; ++q
){
if( q
->needs
== REWRITE
){
for( i
=0; i
<DSIZE
; ++i
){
if( dope
[i
] ){ /* there is an op... */
for( q
=table
; q
->op
!= FREE
; ++q
){
/* beware; things like LTYPE that match
multiple things in the tree must
not try to look at the NIL at this
stage of things! Put something else
/* at one point, the operator matching was 15% of the
total comile time; thus, the function
call that was here was removed...
if((opmtemp
=mamask
[q
->op
- OPSIMP
])&SPFLG
){
if( i
==NAME
|| i
==ICON
|| i
==OREG
) break;
else if( shltype( i
, NIL
) ) break;
else if( (dope
[i
]&(opmtemp
|ASGFLG
)) == opmtemp
) break;
match( p
, cookie
) NODE
*p
; {
/* called by: order, gencall
look for match in table and generate code if found unless
returns MDONE, MNOPE, or rewrite specification from table */
register struct optab
*q
;
if( cookie
== FORREW
) q
= rwtable
;
else q
= opptr
[p
->in
.op
];
for( ; q
->op
!= FREE
; ++q
){
/* at one point the call that was here was over 15% of the total time;
thus the function call was expanded inline */
if( q
->op
!=p
->in
.op
) continue;
if((opmtemp
=mamask
[q
->op
- OPSIMP
])&SPFLG
){
if( p
->in
.op
!=NAME
&& p
->in
.op
!=ICON
&& p
->in
.op
!= OREG
&&
! shltype( p
->in
.op
, p
) ) continue;
else if( (dope
[p
->in
.op
]&(opmtemp
|ASGFLG
)) != opmtemp
) continue;
if( !(q
->visit
& cookie
) ) continue;
r
= getlr( p
, 'L' ); /* see if left child matches */
if( !tshape( r
, q
->lshape
) ) continue;
if( !ttype( r
->in
.type
, q
->ltype
) ) continue;
r
= getlr( p
, 'R' ); /* see if right child matches */
if( !tshape( r
, q
->rshape
) ) continue;
if( !ttype( r
->in
.type
, q
->rtype
) ) continue;
/* REWRITE means no code from this match but go ahead
and rewrite node to help future match */
if( q
->needs
& REWRITE
) return( q
->rewrite
);
if( !allo( p
, q
) ) continue; /* if can't generate code, skip entry */
/* resources are available */
expand( p
, cookie
, q
->cstring
); /* generate code */
reclaim( p
, q
->rewrite
, cookie
);
expand( p
, cookie
, cp
) NODE
*p
; register char *cp
; {
/* generate code by interpreting table entry */
continue; /* this is the usual case... */
/* rewrite register type is suppressed */
case 'Z': /* special machine dependent operations */
case 'L': /* get down first */
zzzcode( getlr( p
, c
), *++cp
);
default: /* normal zzzcode processing otherwise */
case 'F': /* this line deleted if FOREFF is active */
if( cookie
& FOREFF
) while( *++cp
!= '\n' ) ; /* VOID */
case 'S': /* field size */
case 'H': /* field shift */
case 'M': /* field mask */
case 'N': /* complement of field mask */
adrcon( *cp
=='M' ? val
: ~val
);
case 'L': /* output special label field */
printf( "%d", p
->bn
.label
);
case 'O': /* opcode string */
hopcode( *++cp
, p
->in
.op
);
case 'B': /* byte offset in word */
val
= getlr(p
,*++cp
)->tn
.lval
;
case 'C': /* for constant value only */
conput( getlr( p
, *++cp
) );
case 'I': /* in instruction */
insput( getlr( p
, *++cp
) );
case 'A': /* address of */
adrput( getlr( p
, *++cp
) );
case 'U': /* for upper half of address, only */
upput( getlr( p
, *++cp
) );
/* return the pointer to the left or right side of p, or p itself,
depending on the optype of p */
return( optype( p
->in
.op
) == LTYPE
? p
: p
->in
.left
);
return( optype( p
->in
.op
) != BITYPE
? p
: p
->in
.right
);
cerror( "bad getlr: %c", c
);
int tag
; /* identifies class of tree */
int subtag
; /* subclass of tree */
union mltemplate
* nexthead
; /* linked by mlinit() */
int op
; /* either an operator or op description */
int nshape
; /* shape of node */
/* both op and nshape must match the node.
* where the work is to be done entirely by
* op, nshape can be SANY, visa versa, op can
int ntype
; /* type descriptor from mfile2 */
extern union mltemplate mltree
[];
int *mlsp
; /* pointing into mlstack */
NODE
**stp
; /* pointing into ststack */
union mltemplate
**lastlink
;
register union mltemplate
*n
;
lastlink
= &(mltree
[0].nexthead
);
for( ; (n
++)->mlhead
.tag
!= 0;
*lastlink
= ++n
, lastlink
= &(n
->mlhead
.nexthead
) ){
if( vdebug
)printf("mlinit: %d\n",(n
-1)->mlhead
.tag
);
/* wander thru a tree with a stack finding
* its structure so the next header can be located.
if( (mlop
= n
->mlnode
.op
) < OPSIMP
){
cerror("(1)unknown opcode: %o",mlop
);
if( mamask
[mlop
-OPSIMP
] &
(SIMPFLG
|COMMFLG
|MULFLG
|DIVFLG
|LOGFLG
|FLOFLG
|SHFFLG
) ){
else if( ! (mamask
[mlop
-OPSIMP
] & UTYPE
) ){/* includes OPANY */
else if ( *--mlsp
!= BITYPE
)
cerror("(1)bad multi-level tree descriptor around mltree[%d]",
tree_end
: /* n points to final leaf */
for( n
= &(mltree
[0]); n
->mlhead
.tag
!= 0; ++n
)
printf("%o: %d, %d, %o,\n",n
,
n
->mlhead
.tag
,n
->mlhead
.subtag
,n
->mlhead
.nexthead
);
mlmatch( subtree
, target
, subtarget
) NODE
* subtree
; int target
,subtarget
;{
* does subtree match a multi-level tree with
* tag "target"? Return zero on failure,
* non-zero subtag on success (or MDONE if
* there is a zero subtag field).
union mltemplate
*head
; /* current template header */
register union mltemplate
*n
; /* node being matched */
NODE
* st
; /* subtree being matched */
if( vdebug
) printf("mlmatch(%o,%d)\n",subtree
,target
);
for( head
= &(mltree
[0]); head
->mlhead
.tag
!= 0;
head
=head
->mlhead
.nexthead
){
if( vdebug
> 1 )printf("mlmatch head(%o) tag(%d)\n",
if( head
->mlhead
.tag
!= target
)continue;
if( subtarget
&& head
->mlhead
.subtag
!= subtarget
)continue;
if( vdebug
) printf("mlmatch for %d\n",target
);
/* potential for match */
/* compare n->op, ->nshape, ->ntype to
for( ;; ++n
){ /* for each node in multi-level template */
if( st
->op
!= n
->op
)break;
if((opmtemp
=mamask
[n
->op
-OPSIMP
])&SPFLG
){
if(st
->op
!=NAME
&& st
->op
!=ICON
&& st
->op
!=OREG
&&
! shltype(st
->op
,st
)) break;
else if((dope
[st
->op
]&(opmtemp
|ASGFLG
))!=opmtemp
) break;
/* check shape and type */
if( ! tshape( st
, n
->mlnode
.nshape
) ) break;
if( ! ttype( st
->type
, n
->mlnode
.ntype
) ) break;
/* that node matched, let's try another */
/* must advance both st and n and halt at right time */
if( (mlop
= n
->mlnode
.op
) < OPSIMP
){
cerror("(2)unknown opcode: %o",mlop
);
if( mamask
[mlop
- OPSIMP
] &
(SIMPFLG
|COMMFLG
|MULFLG
|DIVFLG
|LOGFLG
|FLOFLG
|SHFFLG
) ){
else if( ! (mamask
[mlop
-OPSIMP
] & UTYPE
) ){/* includes OPANY */
else if ( *--mlsp
!= BITYPE
)
cerror("(2)bad multi-level tree descriptor around mltree[%d]",
else /* UNARY */ st
= st
->left
;
/* complete multi-level match successful */
if( vdebug
) printf("mlmatch() success\n");
if( head
->mlhead
.subtag
== 0 ) return( MDONE
);
if( vdebug
)printf("\treturns %d\n",
return( head
->mlhead
.subtag
);