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
->name
[0] ) return(0);
if( p
->lval
== 0 && shape
== SZERO
) return(1);
else if( p
->lval
== 1 && shape
== SONE
) return(1);
else if( p
->lval
== -1 && shape
== SMONE
) return(1);
else if( p
->lval
> -257 && p
->lval
< 256 && shape
== SCCON
) return(1);
else if( p
->lval
> -32769 && p
->lval
< 32768 && shape
== SSCON
) return(1);
case SSOREG
: /* non-indexed OREG */
if( o
== OREG
&& !R2TEST(p
->rval
) ) return(1);
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
->lval
) ) return(0);
if( !flshape( p
->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
->rval
) ? SBREG
: SAREG
;
if( istreg( p
->rval
) && busy
[p
->rval
]<=1 ) mask
|= mask
==SAREG
? STAREG
: STBREG
;
/* return STARNM or STARREG or 0 */
return( shumul(p
->left
) & shape
);
ttype( t
, tword
) TWORD t
; {
/* does the type t match tword */
if( tword
& TANY
) return(1);
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
;
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
;
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
->op
) continue;
if((opmtemp
=mamask
[q
->op
- OPSIMP
])&SPFLG
){
if( p
->op
!=NAME
&& p
->op
!=ICON
&& p
->op
!= OREG
&&
! shltype( p
->op
, p
) ) continue;
else if( (dope
[p
->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
->type
, q
->ltype
) ) continue;
r
= getlr( p
, 'R' ); /* see if right child matches */
if( !tshape( r
, q
->rshape
) ) continue;
if( !ttype( r
->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... */
case 'Z': /* special machine dependent operations */
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
->label
);
case 'O': /* opcode string */
case 'B': /* byte offset in word */
val
= getlr(p
,*++cp
)->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
->op
) == LTYPE
? p
: p
->left
);
return( optype( p
->op
) != BITYPE
? p
: p
->right
);
cerror( "bad getlr: %c", c
);