1 static char *sccsid ="@(#)order.c 1.1 (Berkeley) 12/15/82"; 2 # include "mfile2" 3 4 int maxargs = { -1 }; 5 6 stoasg( p, o ) register NODE *p; { 7 /* should the assignment op p be stored, 8 given that it lies as the right operand of o 9 (or the left, if o==UNARY MUL) */ 10 /* 11 if( p->in.op == INCR || p->in.op == DECR ) return; 12 if( o==UNARY MUL && p->in.left->in.op == REG && !isbreg(p->in.left->tn.rval) ) SETSTO(p,INAREG); 13 */ 14 } 15 16 deltest( p ) register NODE *p; { 17 /* should we delay the INCR or DECR operation p */ 18 p = p->in.left; 19 return( p->in.op == REG || p->in.op == NAME || p->in.op == OREG ); 20 } 21 22 autoincr( p ) NODE *p; { 23 register NODE *q = p->in.left, *r; 24 25 if( q->in.op == INCR && (r=q->in.left)->in.op == REG && 26 ISPTR(q->in.type) && p->in.type == DECREF(q->in.type) && 27 tlen(p) == q->in.right->tn.lval ) return(1); 28 29 return(0); 30 } 31 32 mkadrs(p) register NODE *p; { 33 register o; 34 35 o = p->in.op; 36 37 if( asgop(o) ){ 38 if( p->in.left->in.su >= p->in.right->in.su ){ 39 if( p->in.left->in.op == UNARY MUL ){ 40 SETSTO( p->in.left->in.left, INTEMP ); 41 } 42 else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 43 SETSTO( p->in.left->in.left->in.left, INTEMP ); 44 } 45 else { /* should be only structure assignment */ 46 SETSTO( p->in.left, INTEMP ); 47 } 48 } 49 else SETSTO( p->in.right, INTEMP ); 50 } 51 else { 52 if( p->in.left->in.su > p->in.right->in.su ){ 53 SETSTO( p->in.left, INTEMP ); 54 } 55 else { 56 SETSTO( p->in.right, INTEMP ); 57 } 58 } 59 } 60 61 notoff( t, r, off, cp) CONSZ off; char *cp; { 62 /* is it legal to make an OREG or NAME entry which has an 63 /* offset of off, (from a register of r), if the 64 /* resulting thing had type t */ 65 66 /* if( r == R0 ) return( 1 ); /* NO */ 67 return(0); /* YES */ 68 } 69 70 # define max(x,y) ((x)<(y)?(y):(x)) 71 72 sucomp( p ) register NODE *p; { 73 74 /* set the su field in the node to the sethi-ullman 75 number, or local equivalent */ 76 77 register o, ty, sul, sur, r; 78 79 o = p->in.op; 80 ty = optype( o ); 81 p->in.su = szty( p->in.type ); /* 2 for float or double, else 1 */; 82 83 if( ty == LTYPE ){ 84 if( o == OREG ){ 85 r = p->tn.rval; 86 /* oreg cost is (worst case) 1 + number of temp registers used */ 87 if( R2TEST(r) ){ 88 if( R2UPK1(r)!=100 && istreg(R2UPK1(r)) ) ++p->in.su; 89 if( istreg(R2UPK2(r)) ) ++p->in.su; 90 } 91 else { 92 if( istreg( r ) ) ++p->in.su; 93 } 94 } 95 if( p->in.su == szty(p->in.type) && 96 (p->in.op!=REG || !istreg(p->tn.rval)) && 97 (p->in.type==INT || p->in.type==UNSIGNED || p->in.type==DOUBLE) ) 98 p->in.su = 0; 99 return; 100 } 101 102 else if( ty == UTYPE ){ 103 switch( o ) { 104 case UNARY CALL: 105 case UNARY STCALL: 106 p->in.su = fregs; /* all regs needed */ 107 return; 108 109 default: 110 p->in.su = p->in.left->in.su + (szty( p->in.type ) > 1 ? 2 : 0) ; 111 return; 112 } 113 } 114 115 116 /* If rhs needs n, lhs needs m, regular su computation */ 117 118 sul = p->in.left->in.su; 119 sur = p->in.right->in.su; 120 121 if( o == ASSIGN ){ 122 /* computed by doing right, then left (if not in mem), then doing it */ 123 p->in.su = max(sur,sul+1); 124 return; 125 } 126 127 if( o == CALL || o == STCALL ){ 128 /* in effect, takes all free registers */ 129 p->in.su = fregs; 130 return; 131 } 132 133 if( o == STASG ){ 134 /* right, then left */ 135 p->in.su = max( max( 1+sul, sur), fregs ); 136 return; 137 } 138 139 if( asgop(o) ){ 140 /* computed by doing right, doing left address, doing left, op, and store */ 141 p->in.su = max(sur,sul+2); 142 /* 143 if( o==ASG MUL || o==ASG DIV || o==ASG MOD) p->in.su = max(p->in.su,fregs); 144 */ 145 return; 146 } 147 148 switch( o ){ 149 case ANDAND: 150 case OROR: 151 case QUEST: 152 case COLON: 153 case COMOP: 154 p->in.su = max( max(sul,sur), 1); 155 return; 156 157 case PLUS: 158 case OR: 159 case ER: 160 /* commutative ops; put harder on left */ 161 if( p->in.right->in.su > p->in.left->in.su && !istnode(p->in.left) ){ 162 register NODE *temp; 163 temp = p->in.left; 164 p->in.left = p->in.right; 165 p->in.right = temp; 166 } 167 break; 168 } 169 170 /* binary op, computed by left, then right, then do op */ 171 p->in.su = max(sul,szty(p->in.right->in.type)+sur); 172 /* 173 if( o==MUL||o==DIV||o==MOD) p->in.su = max(p->in.su,fregs); 174 */ 175 176 } 177 178 int radebug = 0; 179 180 rallo( p, down ) NODE *p; { 181 /* do register allocation */ 182 register o, type, down1, down2, ty; 183 184 if( radebug ) printf( "rallo( %o, %d )\n", p, down ); 185 186 down2 = NOPREF; 187 p->in.rall = down; 188 down1 = ( down &= ~MUSTDO ); 189 190 ty = optype( o = p->in.op ); 191 type = p->in.type; 192 193 194 if( type == DOUBLE || type == FLOAT ){ 195 if( o == FORCE ) down1 = R0|MUSTDO; 196 } 197 else switch( o ) { 198 case ASSIGN: 199 down1 = NOPREF; 200 down2 = down; 201 break; 202 203 /* 204 case MUL: 205 case DIV: 206 case MOD: 207 down1 = R3|MUSTDO; 208 down2 = R5|MUSTDO; 209 break; 210 211 case ASG MUL: 212 case ASG DIV: 213 case ASG MOD: 214 p->in.left->in.rall = down1 = R3|MUSTDO; 215 if( p->in.left->in.op == UNARY MUL ){ 216 rallo( p->in.left->in.left, R4|MUSTDO ); 217 } 218 else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 219 rallo( p->in.left->in.left->in.left, R4|MUSTDO ); 220 } 221 else rallo( p->in.left, R3|MUSTDO ); 222 rallo( p->in.right, R5|MUSTDO ); 223 return; 224 */ 225 226 case CALL: 227 case STASG: 228 case EQ: 229 case NE: 230 case GT: 231 case GE: 232 case LT: 233 case LE: 234 case NOT: 235 case ANDAND: 236 case OROR: 237 down1 = NOPREF; 238 break; 239 240 case FORCE: 241 down1 = R0|MUSTDO; 242 break; 243 244 } 245 246 if( ty != LTYPE ) rallo( p->in.left, down1 ); 247 if( ty == BITYPE ) rallo( p->in.right, down2 ); 248 249 } 250 251 offstar( p ) register NODE *p; { 252 if( p->in.op == PLUS ) { 253 if( p->in.left->in.su == fregs ) { 254 order( p->in.left, INTAREG|INAREG ); 255 return; 256 } else if( p->in.right->in.su == fregs ) { 257 order( p->in.right, INTAREG|INAREG ); 258 return; 259 } 260 if( p->in.left->in.op==LS && 261 (p->in.left->in.left->in.op!=REG || tlen(p->in.left->in.left)!=sizeof(int) ) ) { 262 order( p->in.left->in.left, INTAREG|INAREG ); 263 return; 264 } 265 if( p->in.right->in.op==LS && 266 (p->in.right->in.left->in.op!=REG || tlen(p->in.right->in.left)!=sizeof(int) ) ) { 267 order( p->in.right->in.left, INTAREG|INAREG ); 268 return; 269 } 270 if( p->in.type == (PTR|CHAR) || p->in.type == (PTR|UCHAR) ) { 271 if( p->in.left->in.op!=REG || tlen(p->in.left)!=sizeof(int) ) { 272 order( p->in.left, INTAREG|INAREG ); 273 return; 274 } 275 else if( p->in.right->in.op!=REG || tlen(p->in.right)!=sizeof(int) ) { 276 order(p->in.right, INTAREG|INAREG); 277 return; 278 } 279 } 280 } 281 if( p->in.op == PLUS || p->in.op == MINUS ){ 282 if( p->in.right->in.op == ICON ){ 283 p = p->in.left; 284 order( p , INTAREG|INAREG); 285 return; 286 } 287 } 288 289 if( p->in.op == UNARY MUL && !canaddr(p) ) { 290 offstar( p->in.left ); 291 return; 292 } 293 294 order( p, INTAREG|INAREG ); 295 } 296 297 setincr( p ) register NODE *p; { 298 p = p->in.left; 299 if( p->in.op == UNARY MUL ){ 300 offstar( p ); 301 return( 1 ); 302 } 303 return( 0 ); 304 } 305 306 setbin( p ) register NODE *p; { 307 register ro, rt; 308 309 rt = p->in.right->in.type; 310 ro = p->in.right->in.op; 311 312 if( canaddr( p->in.left ) && !canaddr( p->in.right ) ) { /* address rhs */ 313 if( ro == UNARY MUL ) { 314 offstar( p->in.right->in.left ); 315 return(1); 316 } else { 317 order( p->in.right, INAREG|INTAREG|SOREG ); 318 return(1); 319 } 320 } 321 if( !istnode( p->in.left) ) { /* try putting LHS into a reg */ 322 /* order( p->in.left, logop(p->in.op)?(INAREG|INBREG|INTAREG|INTBREG|SOREG):(INTAREG|INTBREG|SOREG) );*/ 323 order( p->in.left, INAREG|INTAREG|INBREG|INTBREG|SOREG ); 324 return(1); 325 } 326 else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){ 327 offstar( p->in.right->in.left ); 328 return(1); 329 } 330 else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || (ro != REG && 331 ro != NAME && ro != OREG && ro != ICON ) ){ 332 order( p->in.right, INAREG|INBREG ); 333 return(1); 334 } 335 /* 336 else if( logop(p->in.op) && rt==USHORT ){ /* must get rhs into register */ 337 /* 338 order( p->in.right, INAREG ); 339 return( 1 ); 340 } 341 */ 342 return(0); 343 } 344 345 setstr( p ) register NODE *p; { /* structure assignment */ 346 if( p->in.right->in.op != REG ){ 347 order( p->in.right, INTAREG ); 348 return(1); 349 } 350 p = p->in.left; 351 if( p->in.op != NAME && p->in.op != OREG ){ 352 if( p->in.op != UNARY MUL ) cerror( "bad setstr" ); 353 order( p->in.left, INTAREG ); 354 return( 1 ); 355 } 356 return( 0 ); 357 } 358 359 setasg( p ) register NODE *p; { 360 /* setup for assignment operator */ 361 362 if( !canaddr(p->in.right) ) { 363 if( p->in.right->in.op == UNARY MUL ) 364 offstar(p->in.right->in.left); 365 else 366 order( p->in.right, INAREG|INBREG|SOREG ); 367 return(1); 368 } 369 if( p->in.left->in.op == UNARY MUL ) { 370 offstar( p->in.left->in.left ); 371 return(1); 372 } 373 if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){ 374 offstar( p->in.left->in.left->in.left ); 375 return(1); 376 } 377 /* FLD patch */ 378 if( p->in.left->in.op == FLD && !(p->in.right->in.type==INT || p->in.right->in.type==UNSIGNED)) { 379 order( p->in.right, INAREG); 380 return(1); 381 } 382 /* end of FLD patch */ 383 return(0); 384 } 385 386 setasop( p ) register NODE *p; { 387 /* setup for =ops */ 388 register rt, ro; 389 390 rt = p->in.right->in.type; 391 ro = p->in.right->in.op; 392 393 if( ro == UNARY MUL && rt != CHAR ){ 394 offstar( p->in.right->in.left ); 395 return(1); 396 } 397 if( ( rt == CHAR || rt == SHORT || rt == UCHAR || rt == USHORT || 398 ( ro != REG && ro != ICON && ro != NAME && ro != OREG ) ) ){ 399 order( p->in.right, INAREG|INBREG ); 400 return(1); 401 } 402 /* 403 if( (p->in.op == ASG LS || p->in.op == ASG RS) && ro != ICON && ro != REG ){ 404 order( p->in.right, INAREG ); 405 return(1); 406 } 407 */ 408 409 410 p = p->in.left; 411 if( p->in.op == FLD ) p = p->in.left; 412 413 switch( p->in.op ){ 414 415 case REG: 416 case ICON: 417 case NAME: 418 case OREG: 419 return(0); 420 421 case UNARY MUL: 422 if( p->in.left->in.op==OREG ) 423 return(0); 424 else 425 offstar( p->in.left ); 426 return(1); 427 428 } 429 cerror( "illegal setasop" ); 430 } 431 432 int crslab = 9999; /* Honeywell */ 433 434 getlab(){ 435 return( crslab-- ); 436 } 437 438 deflab( l ){ 439 printf( "L%d:\n", l ); 440 } 441 442 genargs( p, ptemp ) register NODE *p, *ptemp; { 443 register NODE *pasg; 444 register align; 445 register size; 446 register TWORD type; 447 448 /* generate code for the arguments */ 449 450 /* first, do the arguments on the right */ 451 while( p->in.op == CM ){ 452 genargs( p->in.right, ptemp ); 453 p->in.op = FREE; 454 p = p->in.left; 455 } 456 457 if( p->in.op == STARG ){ /* structure valued argument */ 458 459 size = p->stn.stsize; 460 align = p->stn.stalign; 461 if( p->in.left->in.op == ICON ){ 462 p->in.op = FREE; 463 p= p->in.left; 464 } 465 else { 466 /* make it look beautiful... */ 467 p->in.op = UNARY MUL; 468 canon( p ); /* turn it into an oreg */ 469 if( p->in.op != OREG ){ 470 offstar( p->in.left ); 471 canon( p ); 472 if( p->in.op != OREG ){ 473 offstar( p->in.left ); 474 canon( p ); 475 if( p->in.op != OREG ) cerror( "stuck starg" ); 476 } 477 } 478 } 479 480 481 ptemp->tn.lval = 0; /* all moves to (sp) */ 482 483 pasg = talloc(); 484 pasg->in.op = STASG; 485 pasg->stn.stsize = size; 486 pasg->stn.stalign = align; 487 pasg->in.right = p; 488 pasg->in.left = tcopy( ptemp ); 489 490 /* the following line is done only with the knowledge 491 that it will be undone by the STASG node, with the 492 offset (lval) field retained */ 493 494 if( p->in.op == OREG ) p->in.op = REG; /* only for temporaries */ 495 496 order( pasg, FORARG ); 497 ptemp->tn.lval += size; 498 return; 499 } 500 501 /* ordinary case */ 502 503 order( p, FORARG ); 504 } 505 506 argsize( p ) register NODE *p; { 507 register t; 508 t = 0; 509 if( p->in.op == CM ){ 510 t = argsize( p->in.left ); 511 p = p->in.right; 512 } 513 if( p->in.type == DOUBLE || p->in.type == FLOAT ){ 514 SETOFF( t, 4 ); 515 return( t+8 ); 516 } 517 else if( p->in.op == STARG ){ 518 SETOFF( t, 4 ); /* alignment */ 519 return( t + ((p->stn.stsize+3)/4)*4 ); /* size */ 520 } 521 else { 522 SETOFF( t, 4 ); 523 return( t+4 ); 524 } 525 } 526 527 528