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