int maxa
, mina
, maxb
, minb
;
allo0(){ /* free everything */
if( rstatus
[i
] & STAREG
){
if( rstatus
[i
] & STBREG
){
allo( p
, q
) NODE
*p
; struct optab
*q
; {
resc
[i
].rval
= freereg( p
, n
&NAMASK
);
resc
[i
].rval
= freereg( p
, n
&NBMASK
);
if( p
->op
== STCALL
|| p
->op
== STARG
|| p
->op
== UNARY STCALL
|| p
->op
== STASG
){
resc
[i
].lval
= freetemp( (SZCHAR
*p
->stsize
+ (SZINT
-1))/SZINT
);
resc
[i
].lval
= freetemp( (n
&NTMASK
)/NTEMP
);
resc
[i
].lval
= BITOOR(resc
[i
].lval
);
/* turn off "temporarily busy" bit */
for( j
=0; j
<i
; ++j
) if( resc
[j
].rval
< 0 ) return(0);
freetemp( k
){ /* allocate k integers worth of temp space */
/* we also make the convention that, if the number of words is more than 1,
/* it must be aligned for storing doubles... */
SETOFF( tmpoff
, ALDOUBLE
);
if( tmpoff
> maxoff
) maxoff
= tmpoff
;
if( tmpoff
-baseoff
> maxtemp
) maxtemp
= tmpoff
-baseoff
;
SETOFF( tmpoff
, ALDOUBLE
);
if( tmpoff
> maxoff
) maxoff
= tmpoff
;
if( tmpoff
-baseoff
> maxtemp
) maxtemp
= tmpoff
-baseoff
;
freereg( p
, n
) NODE
*p
; {
/* allocate a register of type n */
/* p gives the type, if floating */
/* not general; means that only one register (the result) OK for call */
if( usable( p
, n
, j
) ) return( j
);
/* have allocated callreg first */
if( j
!=NOPREF
&& usable(p
,n
,j
) ){ /* needed and not allocated */
for( j
=mina
; j
<=maxa
; ++j
) if( rstatus
[j
]&STAREG
){
for( j
=minb
; j
<=maxb
; ++j
) if( rstatus
[j
]&STBREG
){
usable( p
, n
, r
) NODE
*p
; {
/* decide if register r is usable in tree p to satisfy need n */
/* checks, for the moment */
if( !istreg(r
) ) cerror( "usable asked about nontemp register" );
if( busy
[r
] > 1 ) return(0);
if( n
&NAMASK
) return(0);
if( n
& NBMASK
) return(0);
if( (n
&NAMASK
) && (szty(p
->type
) == 2) ){ /* only do the pairing for real regs */
if( !istreg(r
+1) ) return( 0 );
if( busy
[r
+1] > 1 ) return( 0 );
if( busy
[r
] == 0 && busy
[r
+1] == 0 ||
busy
[r
+1] == 0 && shareit( p
, r
, n
) ||
busy
[r
] == 0 && shareit( p
, r
+1, n
) ||
shareit( p
, r
, n
) && shareit( p
, r
+1, n
) ){
/* busy[r] is 1: is there chance for sharing */
return( shareit( p
, r
, n
) );
shareit( p
, r
, n
) NODE
*p
; {
/* can we make register r available by sharing from p
given that the need is n */
if( (n
&(NASL
|NBSL
)) && ushare( p
, 'L', r
) ) return(1);
if( (n
&(NASR
|NBSR
)) && ushare( p
, 'R', r
) ) return(1);
ushare( p
, f
, r
) NODE
*p
; {
/* can we find a register r to share on the left or right
(as f=='L' or 'R', respectively) of p */
if( p
->op
== UNARY MUL
) p
= p
->left
;
return( r
==R2UPK1(p
->rval
) || r
==R2UPK2(p
->rval
) );
else return( r
== p
->rval
);
return( r
== p
->rval
|| ( szty(p
->type
) == 2 && r
==p
->rval
+1 ) );
recl2( p
) register NODE
*p
; {
if( p
->op
== REG
) rfree( r
, p
->type
);
else if( p
->op
== OREG
) {
if( R2UPK1( r
) != 100 ) rfree( R2UPK1( r
), PTR
+INT
);
rfree( R2UPK2( r
), INT
);
/* mark register r free, if it is legal to do so */
printf( "rfree( %s ), size %d\n", rnames
[r
], szty(t
) );
if( --busy
[r
] < 0 ) cerror( "register overfreed");
if( (istreg(r
)^istreg(r
+1)) ) cerror( "illegal free" );
if( --busy
[r
+1] < 0 ) cerror( "register overfreed" );
/* mark register r busy */
printf( "rbusy( %s ), size %d\n", rnames
[r
], szty(t
) );
if( istreg(r
) ) ++busy
[r
];
if( istreg(r
+1) ) ++busy
[r
+1];
if( (istreg(r
)^istreg(r
+1)) ) cerror( "illegal register pair freed" );
rwprint( rw
){ /* print rewriting rule */
static char * rwnames
[] = {
for( i
=0; rwnames
[i
]; ++i
){
if( flag
) printf( "|" );
reclaim( p
, rw
, cookie
) NODE
*p
; {
printf( "reclaim( %o, ", p
);
if( rw
== RNOP
|| ( p
->op
==FREE
&& rw
==RNULL
) ) return; /* do nothing */
/* check that all scratch regs are free */
callchk(p
); /* ordinarily, this is the same as allchk */
if( rw
== RNULL
|| (cookie
&FOREFF
) ){ /* totally clobber, leaving nothing */
/* handle condition codes specially */
if( (cookie
& FORCC
) && (rw
&RESCC
)) {
/* result is CC register */
if( rw
&RLEFT
) *qq
++ = p
->left
;
if( rw
&RRIGHT
) *qq
++ = p
->right
;
if( rw
&RESC1
) *qq
++ = &resc
[0];
if( rw
&RESC2
) *qq
++ = &resc
[1];
if( rw
&RESC3
) *qq
++ = &resc
[2];
cerror( "illegal reclaim");
/* now, select the best result, based on the cookie */
for( r
=respref
; r
->cform
; ++r
){
for( qq
=recres
; (q
= *qq
) != NIL
; ++qq
){
if( tshape( q
, r
->mform
) ) goto gotit
;
/* we can't do it; die */
cerror( "cannot reclaim");
if( p
->op
== STARG
) p
= p
->left
; /* STARGs are still STARGS */
/* q->type = p->type; /* to make multi-register allocations work */
q
->type
= p
->type
==FLOAT
&& q
->op
==REG
? DOUBLE
: p
->type
;
/* maybe there is a better way! */
for( i
=0; i
<NCHNAM
; ++i
)
/* if the thing is in a register, adjust the type */
if( p
->type
== CHAR
|| p
->type
== SHORT
) p
->type
= INT
;
else if( p
->type
== UCHAR
|| p
->type
== USHORT
) p
->type
= UNSIGNED
;
else if( p
->type
== FLOAT
) p
->type
= DOUBLE
;
if( ! (p
->rall
& MUSTDO
) ) return; /* unless necessary, ignore it */
if( busy
[i
] || ( szty(p
->type
)==2 && busy
[i
+1] ) ){
cerror( "faulty register move" );
rfree( p
->rval
, p
->type
);
rmove( i
, p
->rval
, p
->type
);
if( p
->op
== REG
|| !R2TEST(p
->rval
) ) {
if( busy
[p
->rval
]>1 && istreg(p
->rval
) ) cerror( "potential register overwrite");
if( (R2UPK1(p
->rval
) != 100 && busy
[R2UPK1(p
->rval
)]>1 && istreg(R2UPK1(p
->rval
)) )
|| (busy
[R2UPK2(p
->rval
)]>1 && istreg(R2UPK2(p
->rval
)) ) )
cerror( "potential register overwrite");
ncopy( q
, p
) NODE
*p
, *q
; {
/* copy the contents of p into q, without any feeling for
/* this code assume that copying rval and lval does the job;
in general, it might be necessary to special case the
for( i
=0; i
<NCHNAM
; ++i
) q
->name
[i
] = p
->name
[i
];
tcopy( p
) register NODE
*p
; {
/* make a fresh copy of p */
if( p
->op
== REG
) rbusy( r
, p
->type
);
else if( p
->op
== OREG
) {
if( R2UPK1(r
) != 100 ) rbusy( R2UPK1(r
), PTR
+INT
);
q
->right
= tcopy(p
->right
);
q
->left
= tcopy(p
->left
);
/* check to ensure that all register are free */
if( istreg(i
) && busy
[i
] ){
cerror( "register allocation error");