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