stoasg( p
, o
) register NODE
*p
; {
/* should the assignment op p be stored,
given that it lies as the right operand of o
(or the left, if o==UNARY MUL) */
return( shltype(p
->left
->op
, p
->left
) );
deltest( p
) register NODE
*p
; {
/* should we delay the INCR or DECR operation p */
if( p
->op
== INCR
&& p
->left
->op
== REG
&& spsz( p
->left
->type
, p
->right
->lval
) ){
if( p
->op
== UNARY MUL
) p
= p
->left
;
return( p
->op
== NAME
|| p
->op
== OREG
|| p
->op
== REG
);
mkadrs(p
) register NODE
*p
; {
if( p
->left
->su
>= p
->right
->su
){
if( p
->left
->op
== UNARY MUL
){
SETSTO( p
->left
->left
, INTEMP
);
if( p
->right
->su
> 0 ) SETSTO( p
->right
, INTEMP
);
else cerror( "store finds both sides trivial" );
else if( p
->left
->op
== FLD
&& p
->left
->left
->op
== UNARY MUL
){
SETSTO( p
->left
->left
->left
, INTEMP
);
else { /* should be only structure assignment */
SETSTO( p
->left
, INTEMP
);
else SETSTO( p
->right
, INTEMP
);
if( p
->left
->su
> p
->right
->su
){
SETSTO( p
->left
, INTEMP
);
SETSTO( p
->right
, INTEMP
);
notoff( t
, r
, off
, cp
) TWORD t
; CONSZ off
; char *cp
; {
/* is it legal to make an OREG or NAME entry which has an
/* offset of off, (from a register of r), if the
/* resulting thing had type t */
# define max(x,y) ((x)<(y)?(y):(x))
# define min(x,y) ((x)<(y)?(x):(y))
zum( p
, zap
) register NODE
*p
; {
/* zap Sethi-Ullman number for chars, longs, floats */
/* in the case of longs, only STARNM's are zapped */
/* ZCHAR, ZLONG, ZFLOAT are used to select the zapping */
if( !(zap
&ZCHAR
) ) break;
if( su
== 0 ) p
->su
= su
= 1;
if( !(zap
&ZLONG
) ) break;
if( p
->op
== UNARY MUL
&& su
== 0 ) p
->su
= su
= 2;
if( !(zap
&ZFLOAT
) ) break;
if( su
== 0 ) p
->su
= su
= 1;
sucomp( p
) register NODE
*p
; {
/* set the su field in the node to the sethi-ullman
number, or local equivalent */
register o
, ty
, sul
, sur
;
if( p
->type
==FLOAT
) p
->su
= 1;
p
->su
= fregs
; /* all regs needed */
if( shumul( p
->left
) ) return;
p
->su
= max( p
->left
->su
, nr
);
/* If rhs needs n, lhs needs m, regular su computation */
asop
: /* also used for +=, etc., to memory */
/* don't need to worry about the left side */
/* right, left address, op */
/* just get the lhs address into a register, and mov */
/* the `nr' covers the case where value is in reg afterwards */
/* right, left address, op */
p
->su
= max( sur
, nr
+sul
);
if( o
== CALL
|| o
== STCALL
){
/* in effect, takes all free registers */
p
->su
= max( max( sul
+nr
, sur
), fregs
);
/* do the harder side, then the easier side, into registers */
/* left then right, max(sul,sur+nr) */
/* right then left, max(sur,sul+nr) */
/* to hold both sides in regs: nr+nr */
nr
= szty( p
->left
->type
);
sul
= zum( p
->left
, ZLONG
|ZCHAR
|ZFLOAT
);
sur
= zum( p
->right
, ZLONG
|ZCHAR
|ZFLOAT
);
p
->su
= min( max(sul
,sur
+nr
), max(sur
,sul
+nr
) );
/* computed by doing right, doing left address, doing left, op, and store */
if( p
->type
!=FLOAT
&& p
->type
!=DOUBLE
) nr
= fregs
;
case ASG AND
: /* really bic */
if( p
->type
== INT
|| p
->type
== UNSIGNED
|| ISPTR(p
->type
) ) goto asop
;
sur
= zum( p
->right
, ZCHAR
|ZLONG
|ZFLOAT
);
if( sur
== 0 ){ /* easy case: if addressable,
do left value, op, store */
if( sul
== 0 ) p
->su
= nr
;
/* harder: left adr, val, op, store */
else p
->su
= max( sul
, nr
+1 );
else { /* do right, left adr, left value, op, store */
if( sul
== 0 ){ /* right, left value, op, store */
p
->su
= max( sur
, nr
+nr
);
p
->su
= max( sur
, max( sul
+nr
, 1+nr
+nr
) );
p
->su
= max( max(sul
,sur
), nr
);
if( ( o
==DIV
|| o
==MOD
|| o
==MUL
)
&& p
->type
!=FLOAT
&& p
->type
!=DOUBLE
) nr
= fregs
;
if( o
==PLUS
|| o
==MUL
|| o
==OR
|| o
==ER
){
/* AND is ruined by the hardware */
/* permute: get the harder on the left */
if( istnode( p
->left
) || sul
> sur
) goto noswap
; /* don't do it! */
/* look for a funny type on the left, one on the right */
if( rt
== FLOAT
&& lt
== DOUBLE
) goto swap
;
if( (rt
==CHAR
||rt
==UCHAR
) && (lt
==INT
||lt
==UNSIGNED
||ISPTR(lt
)) ) goto swap
;
if( lt
==LONG
|| lt
==ULONG
){
if( rt
==LONG
|| rt
==ULONG
){
/* if one is a STARNM, swap */
if( p
->left
->op
== UNARY MUL
&& sul
==0 ) goto noswap
;
if( p
->right
->op
== UNARY MUL
&& p
->left
->op
!= UNARY MUL
) goto swap
;
else if( p
->left
->op
== UNARY MUL
&& sul
== 0 ) goto noswap
;
else goto swap
; /* put long on right, unless STARNM */
/* we are finished with the type stuff now; if one is addressable,
if( sul
== 0 && sur
!= 0 ){
ssu
= sul
; sul
= sur
; sur
= ssu
;
s
= p
->left
; p
->left
= p
->right
; p
->right
= s
;
sur
= zum( p
->right
, ZCHAR
|ZLONG
|ZFLOAT
);
/* get left value into a register, do op */
/* do harder into a register, then easier */
p
->su
= max( nr
+nr
, min( max( sul
, nr
+sur
), max( sur
, nr
+sul
) ) );
mkrall( p
, r
) register NODE
*p
; {
/* insure that the use of p gets done with register r; in effect, */
if( p
->op
!= UNARY MUL
) return; /* no more to do */
if( p
->op
== UNARY MUL
){
if( p
->op
== PLUS
&& p
->right
->op
== ICON
){
rallo( p
, down
) register NODE
*p
; {
/* do register allocation */
register o
, type
, down1
, down2
, ty
;
if( radebug
) printf( "rallo( %o, %o )\n", p
, down
);
down1
= ( down
&= ~MUSTDO
);
ty
= optype( o
= p
->op
);
if( type
== DOUBLE
|| type
== FLOAT
){
if( o
== FORCE
) down1
= FR0
|MUSTDO
;
/* keep the addresses out of the hair of (r0,r1) */
/* lhs in (r0,r1), nothing else matters */
/* at least 3 regs free */
/* compute lhs in (r0,r1), address of left in r2 */
p
->left
->rall
= R1
|MUSTDO
;
mkrall( p
->left
, R2
|MUSTDO
);
/* now, deal with right */
if( fregs
== 3 ) rallo( p
->right
, NOPREF
);
/* put address of long or value here */
p
->right
->rall
= R3
|MUSTDO
;
mkrall( p
->right
, R3
|MUSTDO
);
rallo( p
->left
, R1
|MUSTDO
);
rallo( p
->right
, NOPREF
);
/* compute addresses, stay away from (r0,r1) */
p
->right
->rall
= (fregs
==3) ? R2
|MUSTDO
: R3
|MUSTDO
;
mkrall( p
->right
, R2
|MUSTDO
);
if( ty
!= LTYPE
) rallo( p
->left
, down1
);
if( ty
== BITYPE
) rallo( p
->right
, down2
);
offstar( p
) register NODE
*p
; {
/* handle indirections */
if( p
->op
== UNARY MUL
) p
= p
->left
;
if( p
->op
== PLUS
|| p
->op
== MINUS
){
if( p
->right
->op
== ICON
){
order( p
->left
, INTAREG
|INAREG
);
order( p
, INTAREG
|INAREG
);
return( 0 ); /* for the moment, don't bother */
niceuty( p
) register NODE
*p
; {
return( p
->op
== UNARY MUL
&& (t
=p
->type
)!=CHAR
&&
t
!= UCHAR
&& t
!= FLOAT
&&
shumul( p
->left
) != STARREG
);
setbin( p
) register NODE
*p
; {
if( p
->right
->su
== 0 ){ /* rhs is addressable */
if( l
->op
== UNARY MUL
&& l
->type
!= FLOAT
&& shumul( l
->left
) != STARREG
) offstar( l
->left
);
else order( l
, INAREG
|INTAREG
|INBREG
|INTBREG
|INTEMP
);
order( l
, INTAREG
|INTBREG
);
/* now, rhs is complicated: must do both sides into registers */
/* do the harder side first */
/* relational: do both sides into regs if need be */
else if( !istnode( r
) ){
order( r
, INTAREG
|INAREG
|INTBREG
|INBREG
|INTEMP
);
else if( !istnode( l
) ){
order( l
, INTAREG
|INAREG
|INTBREG
|INBREG
|INTEMP
);
order( r
, INTAREG
|INAREG
|INTBREG
|INBREG
|INTEMP
);
cerror( "setbin can't deal with %s", opst
[p
->op
] );
if( !istnode(r
) && r
->su
> l
->su
){
/* if there is a chance of making it addressable, try it... */
return( 1 ); /* hopefully, it is addressable by now */
order( r
, INTAREG
|INAREG
|INTBREG
|INBREG
|INTEMP
); /* anything goes on rhs */
order( l
, INTAREG
|INTBREG
);
setstr( p
) register NODE
*p
; { /* structure assignment */
if( p
->right
->op
!= REG
){
order( p
->right
, INTAREG
);
if( p
->op
!= NAME
&& p
->op
!= OREG
){
if( p
->op
!= UNARY MUL
) cerror( "bad setstr" );
order( p
->left
, INTAREG
);
setasg( p
) register NODE
*p
; {
/* setup for assignment operator */
if( p
->right
->su
!= 0 && p
->right
->op
!= REG
) {
if( p
->right
->op
== UNARY MUL
)
offstar( p
->right
->left
);
order( p
->right
, INAREG
|INBREG
|SOREG
|SNAME
|SCON
);
if( p
->right
->op
!= REG
&& ( p
->type
== FLOAT
|| p
->type
== DOUBLE
) ) {
order( p
->right
, INBREG
);
if( p
->left
->op
== UNARY MUL
&& !tshape( p
->left
, STARREG
|STARNM
) ){
offstar( p
->left
->left
);
if( p
->left
->op
== FLD
&& p
->left
->left
->op
== UNARY MUL
){
offstar( p
->left
->left
->left
);
/* if things are really strange, get rhs into a register */
if( p
->right
->op
!= REG
){
order( p
->right
, INAREG
|INBREG
);
setasop( p
) register NODE
*p
; {
if( p
->type
!= INT
&& p
->type
!= UNSIGNED
&& !ISPTR(p
->type
) ) break;
if( p
->right
->type
== CHAR
|| p
->right
->type
== UCHAR
){
order( p
->right
, INAREG
);
if( sul
== 0 || p
->left
->op
== REG
){
if( p
->left
->type
== CHAR
|| p
->left
->type
== UCHAR
) goto rew
; /* rewrite */
order( p
->right
, INAREG
|INBREG
);
/* easy case: if addressable, do left value, op, store */
if( sul
== 0 ) goto rew
; /* rewrite */
/* harder; make aleft address, val, op, and store */
if( p
->left
->op
== UNARY MUL
){
offstar( p
->left
->left
);
if( p
->left
->op
== FLD
&& p
->left
->left
->op
== UNARY MUL
){
offstar( p
->left
->left
->left
);
rew
: /* rewrite, accounting for autoincrement and autodecrement */
if( q
->op
== FLD
) q
= q
->left
;
if( q
->op
!= UNARY MUL
|| shumul(q
->left
) != STARREG
) return(0); /* let reader.c do it */
/* mimic code from reader.c */
reclaim( p
->right
, RNULL
, 0 );
/* now, zap INCR on right, ASG MINUS on left */
if( q
->left
->op
== INCR
){
if( q
->op
== FLD
) q
= q
->left
;
if( q
->left
->op
!= INCR
) cerror( "bad incr rewrite" );
else if( q
->left
->op
!= ASG MINUS
) cerror( " bad -= rewrite" );
q
->left
->right
->op
= FREE
;
/* now, resume reader.c rewriting code */
order( p2
->left
, INTBREG
|INTAREG
);
order( p2
, INTBREG
|INTAREG
);
/* harder case: do right, left address, left value, op, store */
if( p
->right
->op
== UNARY MUL
){
offstar( p
->right
->left
);
/* sur> 0, since otherwise, done above */
if( p
->right
->op
== REG
) goto leftadr
; /* make lhs addressable */
order( p
->right
, INAREG
|INBREG
);
genargs( p
) register NODE
*p
; {
/* generate code for the arguments */
/* first, do the arguments on the right (last->first) */
if( p
->op
== STARG
){ /* structure valued argument */
if( p
->left
->op
== ICON
){
/* make into a name node */
/* make it look beautiful... */
canon( p
); /* turn it into an oreg */
if( p
->op
!= OREG
) cerror( "stuck starg" );
p
->lval
+= size
; /* end of structure */
/* put on stack backwards */
for( ; size
>0; size
-= 2 ){
expand( p
, RNOP
, " mov AR,Z-\n" );
argsize( p
) register NODE
*p
; {
if( p
->type
== DOUBLE
|| p
->type
== FLOAT
){
else if( p
->type
== LONG
|| p
->type
== ULONG
) {
else if( p
->op
== STARG
){
SETOFF( t
, p
->stalign
); /* alignment */
return( t
+ p
->stsize
); /* size */