static char *sccsid
="@(#)order.c 1.1 (Berkeley) 12/15/82";
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) */
if( p->in.op == INCR || p->in.op == DECR ) return;
if( o==UNARY MUL && p->in.left->in.op == REG && !isbreg(p->in.left->tn.rval) ) SETSTO(p,INAREG);
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
);
register NODE
*q
= p
->in
.left
, *r
;
if( q
->in
.op
== INCR
&& (r
=q
->in
.left
)->in
.op
== REG
&&
ISPTR(q
->in
.type
) && p
->in
.type
== DECREF(q
->in
.type
) &&
tlen(p
) == q
->in
.right
->tn
.lval
) return(1);
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
) 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 */
/* if( r == R0 ) return( 1 ); /* NO */
# 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 o
, ty
, sul
, sur
, r
;
p
->in
.su
= szty( p
->in
.type
); /* 2 for float or 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
.type
==INT
|| p
->in
.type
==UNSIGNED
|| p
->in
.type
==DOUBLE
) )
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 */
p
->in
.su
= max(sur
,sul
+2);
if( o==ASG MUL || o==ASG DIV || o==ASG MOD) p->in.su = max(p->in.su,fregs);
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
;
/* binary op, computed by left, then right, then do op */
p
->in
.su
= max(sul
,szty(p
->in
.right
->in
.type
)+sur
);
if( o==MUL||o==DIV||o==MOD) p->in.su = max(p->in.su,fregs);
rallo( p
, down
) NODE
*p
; {
/* do register allocation */
register o
, type
, down1
, down2
, ty
;
if( radebug
) printf( "rallo( %o, %d )\n", p
, down
);
down1
= ( down
&= ~MUSTDO
);
ty
= optype( o
= p
->in
.op
);
if( type
== DOUBLE
|| type
== FLOAT
){
if( o
== FORCE
) down1
= R0
|MUSTDO
;
p->in.left->in.rall = down1 = R3|MUSTDO;
if( p->in.left->in.op == UNARY MUL ){
rallo( p->in.left->in.left, R4|MUSTDO );
else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){
rallo( p->in.left->in.left->in.left, R4|MUSTDO );
else rallo( p->in.left, R3|MUSTDO );
rallo( p->in.right, R5|MUSTDO );
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
)!=sizeof(int) ) ) {
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
)!=sizeof(int) ) ) {
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
)!=sizeof(int) ) {
order( p
->in
.left
, INTAREG
|INAREG
);
else if( p
->in
.right
->in
.op
!=REG
|| tlen(p
->in
.right
)!=sizeof(int) ) {
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, logop(p->in.op)?(INAREG|INBREG|INTAREG|INTBREG|SOREG):(INTAREG|INTBREG|SOREG) );*/
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
);
else if( logop(p->in.op) && rt==USHORT ){ /* must get rhs into register */
order( p->in.right, INAREG );
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 == ASG LS || p->in.op == ASG RS) && ro != ICON && ro != REG ){
order( p->in.right, INAREG );
if( p
->in
.op
== FLD
) p
= p
->in
.left
;
if( p
->in
.left
->in
.op
==OREG
)
cerror( "illegal setasop" );
int crslab
= 9999; /* Honeywell */
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 */
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 */