static char sccsid
[] = "@(#)order.c 1.8 (Berkeley) 8/26/88";
stoasg( p
, o
) 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) */
deltest( p
) register NODE
*p
; {
/* should we delay the INCR or DECR operation p */
return( p
->in
.op
== REG
|| p
->in
.op
== NAME
|| p
->in
.op
== OREG
);
mkadrs(p
) register NODE
*p
; {
if( p
->in
.left
->in
.su
>= p
->in
.right
->in
.su
){
if( p
->in
.left
->in
.op
== UNARY MUL
){
SETSTO( p
->in
.left
->in
.left
, INTEMP
);
else if( p
->in
.left
->in
.op
== FLD
&& p
->in
.left
->in
.left
->in
.op
== UNARY MUL
){
SETSTO( p
->in
.left
->in
.left
->in
.left
, INTEMP
);
else { /* should be only structure assignment */
SETSTO( p
->in
.left
, INTEMP
);
else SETSTO( p
->in
.right
, INTEMP
);
if( p
->in
.left
->in
.su
> p
->in
.right
->in
.su
){
SETSTO( p
->in
.left
, INTEMP
);
SETSTO( p
->in
.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))
sucomp( p
) register NODE
*p
; {
/* set the su field in the node to the sethi-ullman
number, or local equivalent */
register int o
, ty
, sul
, sur
, r
;
p
->in
.su
= szty( p
->in
.type
); /* 2 for double, else 1 */;
/* oreg cost is (worst case) 1 + number of temp registers used */
if( R2UPK1(r
)!=100 && istreg(R2UPK1(r
)) ) ++p
->in
.su
;
if( istreg(R2UPK2(r
)) ) ++p
->in
.su
;
if( istreg( r
) ) ++p
->in
.su
;
if( p
->in
.su
== szty(p
->in
.type
) &&
(p
->in
.op
!=REG
|| !istreg(p
->tn
.rval
)) &&
p
->in
.su
= fregs
; /* all regs needed */
p
->in
.su
= p
->in
.left
->in
.su
+
(szty(p
->in
.type
) >1 ? 2 : 0);
/* If rhs needs n, lhs needs m, regular su computation */
sur
= p
->in
.right
->in
.su
;
/* computed by doing right, then left (if not in mem), then doing it */
p
->in
.su
= max(sur
,sul
+1);
if( o
== CALL
|| o
== STCALL
){
/* in effect, takes all free registers */
p
->in
.su
= max( max( 1+sul
, sur
), fregs
);
/* computed by doing right, doing left address, doing left, op, and store */
if(optype(p
->in
.left
->in
.op
) != LTYPE
)
/* ediv uses more regs */
if(o
==ASG DIV
&& p
->in
.left
->in
.type
==UNSIGNED
|| o
==ASG MOD
){
p
->in
.su
= max(max(sul
,(sul
!=0)+2),sur
+1);
p
->in
.su
= max(sur
,sul
+1);
p
->in
.su
= max( max(sul
,sur
), 1);
/* commutative ops; put harder on left */
if( p
->in
.right
->in
.su
> p
->in
.left
->in
.su
&& !istnode(p
->in
.left
) ){
p
->in
.left
= p
->in
.right
;
/* ediv uses more regs */
if(p
->in
.left
->in
.type
!=UNSIGNED
)
p
->in
.su
= max(max(sul
,(sul
!=0)+2),sur
+1);
/* binary op, computed by left, then right, then do op */
p
->in
.su
= max(sul
,szty(p
->in
.right
->in
.type
)+sur
);
rallo( p
, down
) NODE
*p
; {
/* do register allocation */
register int o
, down1
, down2
, ty
;
if( radebug
) printf( "rallo( %o, %d )\n", p
, down
);
down1
= ( down
&= ~MUSTDO
);
ty
= optype( o
= p
->in
.op
);
if( ty
!= LTYPE
) rallo( p
->in
.left
, down1
);
if( ty
== BITYPE
) rallo( p
->in
.right
, down2
);
offstar( p
) register NODE
*p
; {
if( p
->in
.left
->in
.su
== fregs
) {
order( p
->in
.left
, INTAREG
|INAREG
);
} else if( p
->in
.right
->in
.su
== fregs
) {
order( p
->in
.right
, INTAREG
|INAREG
);
if( p
->in
.left
->in
.op
==LS
&&
(p
->in
.left
->in
.left
->in
.op
!=REG
|| tlen(p
->in
.left
->in
.left
)!=SZINT
/SZCHAR
) ) {
order( p
->in
.left
->in
.left
, INTAREG
|INAREG
);
if( p
->in
.right
->in
.op
==LS
&&
(p
->in
.right
->in
.left
->in
.op
!=REG
|| tlen(p
->in
.right
->in
.left
)!=SZINT
/SZCHAR
) ) {
order( p
->in
.right
->in
.left
, INTAREG
|INAREG
);
if( p
->in
.type
== (PTR
|CHAR
) || p
->in
.type
== (PTR
|UCHAR
) ) {
if( p
->in
.left
->in
.op
!=REG
|| tlen(p
->in
.left
)!=SZINT
/SZCHAR
) {
order( p
->in
.left
, INTAREG
|INAREG
);
else if( p
->in
.right
->in
.op
!=REG
|| tlen(p
->in
.right
)!=SZINT
/SZCHAR
) {
order(p
->in
.right
, INTAREG
|INAREG
);
if( p
->in
.op
== PLUS
|| p
->in
.op
== MINUS
){
if( p
->in
.right
->in
.op
== ICON
){
order( p
, INTAREG
|INAREG
);
if( p
->in
.op
== UNARY MUL
&& !canaddr(p
) ) {
order( p
, INTAREG
|INAREG
);
setincr( p
) register NODE
*p
; {
if( p
->in
.op
== UNARY MUL
){
setbin( p
) register NODE
*p
; {
rt
= p
->in
.right
->in
.type
;
if( canaddr( p
->in
.left
) && !canaddr( p
->in
.right
) ) { /* address rhs */
offstar( p
->in
.right
->in
.left
);
order( p
->in
.right
, INAREG
|INTAREG
|SOREG
);
if( !istnode( p
->in
.left
) ) { /* try putting LHS into a reg */
order( p
->in
.left
, INAREG
|INTAREG
|INBREG
|INTBREG
|SOREG
);
else if( ro
== UNARY MUL
&& rt
!= CHAR
&& rt
!= UCHAR
){
offstar( p
->in
.right
->in
.left
);
else if( rt
== CHAR
|| rt
== UCHAR
|| rt
== SHORT
|| rt
== USHORT
|| (ro
!= REG
&&
ro
!= NAME
&& ro
!= OREG
&& ro
!= ICON
) ){
order( p
->in
.right
, INAREG
|INBREG
);
setstr( p
) register NODE
*p
; { /* structure assignment */
if( p
->in
.right
->in
.op
!= REG
){
order( p
->in
.right
, INTAREG
);
if( p
->in
.op
!= NAME
&& p
->in
.op
!= OREG
){
if( p
->in
.op
!= UNARY MUL
) cerror( "bad setstr" );
order( p
->in
.left
, INTAREG
);
setasg( p
) register NODE
*p
; {
/* setup for assignment operator */
if( !canaddr(p
->in
.right
) ) {
if( p
->in
.right
->in
.op
== UNARY MUL
)
offstar(p
->in
.right
->in
.left
);
order( p
->in
.right
, INAREG
|INBREG
|SOREG
);
if( p
->in
.left
->in
.op
== UNARY MUL
) {
offstar( p
->in
.left
->in
.left
);
if( p
->in
.left
->in
.op
== FLD
&& p
->in
.left
->in
.left
->in
.op
== UNARY MUL
){
offstar( p
->in
.left
->in
.left
->in
.left
);
if( p
->in
.left
->in
.op
== FLD
&& !(p
->in
.right
->in
.type
==INT
|| p
->in
.right
->in
.type
==UNSIGNED
)) {
order( p
->in
.right
, INAREG
);
setasop( p
) register NODE
*p
; {
rt
= p
->in
.right
->in
.type
;
if( ro
== UNARY MUL
&& rt
!= CHAR
){
offstar( p
->in
.right
->in
.left
);
if( ( rt
== CHAR
|| rt
== SHORT
|| rt
== UCHAR
|| rt
== USHORT
||
( ro
!= REG
&& ro
!= ICON
&& ro
!= NAME
&& ro
!= OREG
) ) ){
order( p
->in
.right
, INAREG
|INBREG
);
if( p
->in
.op
== FLD
) p
= p
->in
.left
;
if( p
->in
.left
->in
.op
==OREG
)
cerror( "illegal setasop" );
int crslab
= 99999; /* Tahoe */
genargs( p
, ptemp
) register NODE
*p
, *ptemp
; {
/* generate code for the arguments */
/* first, do the arguments on the right */
genargs( p
->in
.right
, ptemp
);
if( p
->in
.op
== STARG
){ /* structure valued argument */
if( p
->in
.left
->in
.op
== ICON
){
/* make it look beautiful... */
canon( p
); /* turn it into an oreg */
for( count
= 0; p
->in
.op
!= OREG
&& count
< 10; ++count
){
if( p
->in
.op
!= OREG
) cerror( "stuck starg" );
ptemp
->tn
.lval
= 0; /* all moves to (sp) */
pasg
->stn
.stalign
= align
;
pasg
->in
.left
= tcopy( ptemp
);
/* the following line is done only with the knowledge
that it will be undone by the STASG node, with the
offset (lval) field retained */
if( p
->in
.op
== OREG
) p
->in
.op
= REG
; /* only for temporaries */
argsize( p
) register NODE
*p
; {
t
= argsize( p
->in
.left
);
if( p
->in
.type
== DOUBLE
|| p
->in
.type
== FLOAT
){
else if( p
->in
.op
== STARG
){
SETOFF( t
, 4 ); /* alignment */
return( t
+ ((p
->stn
.stsize
+3)/4)*4 ); /* size */