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