1File: SMATCH.C Page 1 1 /* 2 Copyright 1982 3 Alcyon Corporation 4 8716 Production Ave. 5 San Diego, Ca. 92121 6 */ 7 8 /* Code Skeleton expansion and matching */ 9 10 #include "cgen.h" 11 #include "cskel.h" 12 #define SK_TYPE(x) (x&017) 13 14 /* expand - code skeleton expansion*/ 15 /* Handles the expansion of code skeleton macros.*/ 16 expand(tp,cookie,freg,skp) /* returns register result is in*/ 17 struct tnode *tp; /* pointer to expression tree*/ 18 int cookie; /* goal of expression tree*/ 19 int freg; /* register to leave results in*/ 20 struct skeleton *skp; /* pointer to code skeleton*/ 21 { 22 register int op, nreg, reg; 23 register int c; 24 register int extf, i2f; 25 register struct tnode *ltp, *rtp; 26 register char *p; 27 register int i, inaddreg, sreg, flag, subtrees, scookie; 28 register char *macro; 29 30 #ifndef NODEBUG 31 if( eflag ) 32 printf("expand op=%d left=%x right=%x skp=%o\n",tp->t_op, 33 skp->sk_left,skp->sk_right,skp); 34 #endif 35 if( ((op=tp->t_op) >= MULT && op <= XOR) || tp->t_type == CHAR ) 36 freg = dreg(freg); 37 macro = skp->sk_def; 38 extf = 0; 39 i2f = 0; 40 rtp = ltp = tp->t_left; 41 subtrees = 1; 42 if( binop(op) ) { 43 subtrees++; 44 rtp = tp->t_right; 45 if( (longorptr(tp->t_type)) && (op == DIV || op == MOD || 46 (op != MULT && (isdreg(freg)) && 47 !(longorptr(ltp->t_type)) && !(longorptr(rtp->t_type)))) ) 48 extf++; 49 switch( op ) { 50 51 case RSH: 52 case LSH: 53 case EQLSH: 54 case EQRSH: 55 if( unsign(ltp->t_type) ) 56 i2f++; 57 break; 58 59 case MULT: 1File: SMATCH.C Page 2 60 case EQMULT: 61 case DIV: 62 case MOD: 63 case EQDIV: 64 case EQMOD: 65 if( unsign(ltp->t_type) || unsign(rtp->t_type) ) 66 i2f++; 67 break; 68 } 69 } 70 nreg = freg + 1; 71 while( c = *macro++ ) { 72 c =& 0xff; 73 switch( c ) { 74 75 default: 76 putchar(c); 77 break; 78 79 case POP: 80 stacksize--; 81 printf("(sp)+"); 82 break; 83 84 case POP4: 85 stacksize--; 86 popstack(4); 87 break; 88 89 case POP8: 90 stacksize =- 2; 91 popstack(8); 92 break; 93 94 case PSH: 95 if( cookie == FORSP ) /*don't affect sp*/ 96 printf("(sp)"); 97 else 98 printf("-(sp)"); 99 stacksize++; 100 break; 101 102 case MOV: 103 case MOVL: 104 case JSR: 105 case CLR: 106 case CLRL: 107 case EXTW: 108 case EXTL: 109 case LEA: 110 case STK: 111 printf("%s",strtab[c-128]); 112 break; 113 114 case OPCALL: 115 if( isfloat(tp->t_type) || isfloat(ltp->t_type) ) { 116 switch( op ) { 117 118 case ADD: 1File: SMATCH.C Page 3 119 case EQADD: 120 printf("_fpadd"); 121 break; 122 123 case SUB: 124 case EQSUB: 125 printf("_fpsub"); 126 break; 127 128 case MULT: 129 case EQMULT: 130 printf("_fpmult"); 131 break; 132 133 case DIV: 134 case EQDIV: 135 printf("_fpdiv"); 136 break; 137 138 case UMINUS: 139 case EQNEG: 140 printf("_fpneg"); 141 break; 142 143 case FLOAT2L: 144 case FLOAT2I: 145 printf("_fpftol"); 146 break; 147 148 case LONG2F: 149 case INT2F: 150 printf("_fpltof"); 151 break; 152 153 case EQUALS: 154 case NEQUALS: 155 case GREAT: 156 case GREATEQ: 157 case LESS: 158 case LESSEQ: 159 printf("_fpcmp"); 160 break; 161 162 default: 163 error("invalid floating op %d\n",op); 164 break; 165 } 166 } 167 else { 168 switch( op ) { 169 170 case MULT: 171 case LMULT: 172 printf("lmul"); 173 break; 174 175 case DIV: 176 case LDIV: 177 printf("ldiv"); 1File: SMATCH.C Page 4 178 break; 179 180 case MOD: 181 case LMOD: 182 printf("lrem"); 183 break; 184 185 default: 186 error("opcall bad op %d",op); 187 break; 188 } 189 } 190 break; 191 192 case TLEFT: 193 outtype( leafop(op) ? tp->t_type : ltp->t_type ); 194 break; 195 196 case TLEFTL: 197 outatype( leafop(op) ? tp->t_type : ltp->t_type ); 198 break; 199 200 case TEITHER: 201 if( longorptr(rtp->t_type) || longorptr(ltp->t_type) ) 202 outtype(LONG); 203 break; 204 205 case TRIGHT: 206 outtype(rtp->t_type); 207 break; 208 209 case OP: 210 case AOP: 211 if( c == AOP || i2f ) 212 i = optab[op][1]; 213 else 214 i = optab[op][0]; 215 printf(mnemonics[i]); 216 break; 217 218 case LADDR: 219 case RADDR: 220 p = (c==RADDR?rtp:ltp); 221 outaexpr(p,IMMED); 222 break; 223 224 case CR: 225 outcreg(freg); 226 break; 227 228 case NR: 229 outcreg(nreg); 230 break; 231 232 case CAR: 233 outcreg(areg(freg)); 234 break; 235 236 case NAR: 1File: SMATCH.C Page 5 237 outcreg(areg(nreg)); 238 break; 239 240 case EXL: 241 outextend(ltp,LONG,freg); 242 break; 243 244 case EXRL: 245 case EXRLN: 246 outextend(rtp,ltp->t_type,c==EXRL?freg:nreg); 247 break; 248 249 case EXLR: 250 case EXLRN: 251 outextend(ltp,rtp->t_type,c==EXLR?freg:nreg); 252 break; 253 254 case LEFT: 255 case RIGHT: 256 subtrees--; 257 case TREE: 258 p = (c==LEFT?ltp:c==RIGHT?rtp:tp); 259 flag = *macro++; 260 scookie = FORREG; 261 if( flag & S_STACK ) { 262 if( cookie == FORSP ) 263 scookie = FORSP; 264 else 265 scookie = FORSTACK; 266 } 267 else if( flag & S_FORCC ) 268 scookie = FORCC; 269 if( flag & S_NEXT ) 270 reg = nreg; 271 else 272 reg = freg; 273 if( flag & S_INDR ) { 274 if( p->t_op != INDR ) 275 error("code skeleton error: %d\n",op); 276 p = p->t_left; /*skip INDR*/ 277 if( coffset(p) ) { 278 p = p->t_left; 279 if( longorptr(p->t_type) == 0 && (flag&S_STACK) != 0 ) 280 p = tnalloc(INT2L,LONG,0,0,p); 281 } 282 reg = areg(reg); 283 } 284 sreg = codegen(p,scookie,reg); /*code for subtree*/ 285 if( scookie == FORREG ) { 286 if( flag & S_INDR ) { 287 if( isdreg(sreg) ) 288 outmovr(sreg,areg(reg),p); 289 } 290 else if( flag & S_NEXT ) 291 nreg = sreg; 292 else if( sreg != reg ) { 293 /* 294 * result was not in expected register, if remaining sub-tree can be 295 * compiled using the remaining registers, update current and next 1File: SMATCH.C Page 6 296 * registers, saving us the trouble of moving the register. 297 */ 298 if( c == TREE || ((isdreg(sreg)) && subtrees > 0 && 299 ((c == LEFT && 300 sucomp(rtp,sreg,0) <= skp->sk_right && 301 sucomp(rtp,sreg,1) <= SU_ANY) || 302 ( c == RIGHT && 303 sucomp(ltp,sreg,0) <= skp->sk_left && 304 sucomp(ltp,sreg,1) <= SU_ANY))) ) { 305 freg = dreg(sreg); 306 nreg = freg + 1; 307 } 308 else 309 outmovr(sreg,dreg(freg),p); 310 } 311 } 312 break; 313 314 case LOFFSET: 315 case ROFFSET: 316 p = (c==LOFFSET) ? ltp->t_left : rtp->t_left; 317 if((p=coffset(p)) != 0 && (p->t_op != CINT || p->t_value != 0)) 318 outaexpr(p,NOTIMMED); 319 break; 320 321 case MODSWAP: 322 switch( op ) { 323 324 case MOD: 325 case EQMOD: 326 case LMOD: 327 case LEQMOD: 328 outswap(freg); 329 } 330 break; 331 332 } 333 } 334 if( extf && cookie == FORREG && (isdreg(freg)) ) { 335 if( unsign(ltp->t_type) || unsign(rtp->t_type) ) 336 outuext(freg); 337 else 338 outext(freg); 339 } 340 #ifndef NODEBUG 341 if( eflag ) 342 printf("ending expand skp=%o\n",skp); 343 #endif 344 return(freg); 345 } 346 347 /* 348 * match - try to match expression tree with code skeleton 349 * Given the expression tree, tries to match the given tree with 350 * the appropriate code skeleton. The code skeleton list is 351 * gotten from the root operator and the cookie value. The code 352 * skeleton list is then searched, checking the Sethy-Ullman numbers 353 * of the sub-trees against the Sethy-Ullman numbers in the code 354 * skeleton list. If the Sethy-Ullman numbers are OK, then the 1File: SMATCH.C Page 7 355 * left and right sub-trees are checked for compatability, e.g. 356 * integer pointers, etc. If a match is found, the code skeleton 357 * list pointer is returned. 358 */ 359 char *match(tp,cookie,reg) /* returns ptr to code skeleton*/ 360 /* or 0 if no skeleton*/ 361 struct tnode *tp; /* pointer to tree*/ 362 int cookie; /* goal for code expansion*/ 363 int reg; /* register to use*/ 364 { 365 register struct skeleton *skp; 366 register int op, bop, opndx; 367 int i; 368 register struct tnode *ltp, *rtp; 369 370 #ifndef NODEBUG 371 if( mflag ) 372 printf("match op=%d cookie=%d reg=%d\n",tp->t_op,cookie,reg); 373 #endif 374 if( (op=tp->t_op) >= LCGENOP ) 375 return(0); 376 if( leafop(op) ) 377 ltp = tp; 378 else 379 ltp = tp->t_left; 380 if( (bop=binop(op)) ) { 381 rtp = tp->t_right; 382 if( convop(ltp->t_op) ) { 383 if( op != LSH && notconvop(rtp->t_op) ) { 384 if( !(unsign(ltp->t_left->t_type)) || op == ASSIGN ) { 385 tp->t_left = ltp->t_left; 386 if( (skp=match(tp,cookie,reg)) != 0 ) 387 return(skp); 388 tp->t_left = ltp; 389 } 390 } 391 } 392 else if( convop(rtp->t_op) ) { 393 if( !(unsign(rtp->t_left->t_type)) || op == ASSIGN ) { 394 tp->t_right = rtp->t_left; 395 if( (skp=match(tp,cookie,reg)) != 0 ) 396 return(skp); 397 tp->t_right = rtp; 398 } 399 } 400 } 401 switch( cookie ) { 402 403 case FORCC: 404 i = 3; 405 break; 406 407 case FOREFF: 408 i = 2; 409 break; 410 411 case FORSTACK: 412 case FORSP: 413 i = 4; 1File: SMATCH.C Page 8 414 break; 415 416 case FORREG: 417 i = 5; 418 break; 419 420 default: 421 error("match cookie=%d\n",cookie); 422 return(0); 423 } 424 #ifndef NODEBUG 425 if( mflag ) 426 printf("match op=%d i=%d ",op,i); 427 #endif 428 if( !(i=optab[op][i]) ) 429 return(0); 430 skp = codeskels[i]; 431 #ifndef NODEBUG 432 if( mflag ) 433 printf("codeskels[%d]=%o\n",i,skp); 434 #endif 435 #ifndef NODEBUG 436 if(mflag) { 437 printf("match LEFT "); 438 puttsu(ltp); 439 if(bop) { 440 printf(" RIGHT "); 441 puttsu(rtp); 442 } 443 putchar('\n'); 444 } 445 #endif 446 for( ; skp->sk_left != 0; skp++ ) { 447 #ifndef NODEBUG 448 if( mflag > 1 ) 449 printf("sk_left=%x sk_right=%x\n",skp->sk_left,skp->sk_right); 450 #endif 451 if( !(skelmatch(ltp,skp->sk_left)) ) 452 continue; 453 if( bop && !(skelmatch(rtp,skp->sk_right)) ) 454 continue; 455 #ifndef NODEBUG 456 if( mflag ) 457 printf("match found skp=%o left=%x right=%x\n",skp, 458 skp->sk_left,skp->sk_right); 459 #endif 460 return(skp); 461 } 462 return(0); 463 } 464 465 /* skelmatch - sub-tree type matching for match*/ 466 /* This checks a subtree for type compatability in match.*/ 467 skelmatch(tp,skinfo) /* returns 1 if matched, else 0*/ 468 struct tnode *tp; /* pointer to expression tree*/ 469 int skinfo; 470 { 471 register int type, unsignf, const, stype; 472 1File: SMATCH.C Page 9 473 if( tp->t_su > skinfo || ((skinfo&T_INDR) && tp->t_op != INDR) ) 474 return(0); 475 stype = SK_TYPE(skinfo); 476 type = tp->t_type; 477 if( function(type) ) 478 type = btype(type); 479 if( unsignf = unsign(type) ) 480 type = basetype(type); 481 const = 0; 482 switch( tp->t_op ) { 483 484 case CFLOAT: /* [vlh] 3.4 */ 485 case CLONG: 486 if( tp->t_su > SU_CONST ) 487 break; 488 case CINT: 489 const++; 490 break; 491 } 492 switch( stype ) { 493 494 case T_CHAR: 495 return( type == CHAR ); 496 497 case T_ANY: /*either int or char*/ 498 if( type == CHAR ) 499 return(1); 500 case T_INT: 501 return( type == INT || const ); 502 503 case T_UNSN: 504 return( unsignf ); 505 506 case T_LONG: 507 return( longorptr(type) ); 508 509 case T_FLOAT: 510 return( isfloat(type) ); 511 512 default: 513 error("skelmatch type: %x",stype); 514 return(0); 515 } 516 } 517