|
|
1.1 ! root 1: /* ! 2: * C compiler. ! 3: * Pattern selection. ! 4: */ ! 5: #ifdef vax ! 6: #include "INC$LIB:cc1.h" ! 7: #else ! 8: #include "cc1.h" ! 9: #endif ! 10: ! 11: #if !TINY ! 12: #define consnap(x, p) if (sflag>x) snapf(p) ! 13: #define consnapv(x, p, v) if (sflag>x) snapf(p, v) ! 14: #else ! 15: #define consnap(x, p) /* consnap */ ! 16: #define consnapv(x, p, v) /* consnapv */ ! 17: #endif ! 18: extern TREE *ripout(); ! 19: ! 20: /* ! 21: * This table, indexed by a context name, ! 22: * returns the appropriate bit set used in the pattern match. ! 23: */ ! 24: static PATFLAG nflagtab[] = { ! 25: PEFFECT, ! 26: PLVALUE, ! 27: PRVALUE, ! 28: PFNARG, ! 29: 0, ! 30: 0, ! 31: 0, ! 32: 0, ! 33: 0, ! 34: 0, ! 35: 0, ! 36: 0, ! 37: 0, ! 38: PEQ, ! 39: PNE, ! 40: PGT, ! 41: PGE, ! 42: PLE, ! 43: PLT, ! 44: PUGT, ! 45: PUGE, ! 46: PULE, ! 47: PULT ! 48: }; ! 49: ! 50: /* ! 51: * This routine is the heart of the code selector. ! 52: * It looks for a pattern that covers the top level ! 53: * operation of tree 'tp' and is in conformance with ! 54: * (or can be pulled into conformance with) ! 55: * the pattern's shape requirements. ! 56: */ ! 57: seltree(tp, c, r) ! 58: TREE *tp; ! 59: { ! 60: register TREE *lp, *rp; ! 61: register PAT *patp; ! 62: PATX *patxp; ! 63: TREE *ap; ! 64: FLAG lflag, rflag, lpflag, rpflag; ! 65: TYPESET ltype, rtype, ntype; ! 66: PATFLAG pflag, nflag; ! 67: PREGSET savbusy, savxreg; ! 68: int ltemp, rtemp, ntemp, stemp, ptemp; ! 69: int sgoal; ! 70: int clash, h; ! 71: int rreg, op, npat, lindex, rindex; ! 72: int didstore; ! 73: ! 74: /* Confirm that the context is consistent ! 75: * with the register specified. */ ! 76: if (c == MLVALUE && isrealreg(r) ! 77: && (pertype[tp->t_type].p_kind®[r].r_lvalue)==0) ! 78: c = MRVALUE; ! 79: /* Jump here if the original match was accomplished by coercing a ! 80: * subtree into addressibility by a store into an auto temp. ! 81: * The tree has been rewritten and must ! 82: * be matched again for an earlier ADR|MMX pattern. */ ! 83: rematch: ! 84: #if !TINY ! 85: if (sflag > 1) { ! 86: snapf("seltree(%P, %C, ", tp, c); ! 87: snapf(c<MFLOW ? "%R" : c<MEQ ? "%d" : "L%d", r); ! 88: snapf(") %A curbusy=%M, curxreg=%M\n", ! 89: tp->t_op, curbusy, curxreg); ! 90: if (sflag > 2) ! 91: snapf("%W%E%W", "Seltree", tp, NULL); ! 92: } ! 93: #endif ! 94: nflag = nflagtab[c]; ! 95: ntype = pertype[tp->t_type].p_type; ! 96: if (tp->t_op < MIOBASE) ! 97: return (0); ! 98: /* Try for matches with widening conversions deleted. ! 99: * Shrink type conversions must remain as ! 100: * they may clear or sign extend the operand. */ ! 101: lp = tp->t_lp; ! 102: if (iswiden(lp)) { ! 103: ap = lp->t_lp; ! 104: if (ap->t_op >= MIOBASE) { ! 105: tp->t_lp = ap; ! 106: if (seltree(tp, c, r)) ! 107: return (1); ! 108: tp->t_lp = lp; ! 109: } ! 110: } ! 111: ltype = pertype[lp->t_type].p_type; ! 112: if (lp->t_op == FIELD) ! 113: lp = lp->t_lp; ! 114: lflag = lp->t_flag; ! 115: rtype = 0; ! 116: rflag = 0; ! 117: if ((op = tp->t_op) != FIELD) { ! 118: rp = tp->t_rp; ! 119: if (rp != NULL) { ! 120: if (iswiden(rp)) { ! 121: ap = rp->t_lp; ! 122: if (ap->t_op >= MIOBASE) { ! 123: tp->t_rp = ap; ! 124: if (seltree(tp, c, r)) ! 125: return (1); ! 126: tp->t_rp = rp; ! 127: } ! 128: } ! 129: rtype = pertype[rp->t_type].p_type; ! 130: rflag = rp->t_flag; ! 131: } ! 132: } ! 133: patxp = &patx[op - MIOBASE]; ! 134: patp = patxp->px_pp - 1; ! 135: npat = patxp->px_npat; ! 136: savbusy = curbusy; ! 137: savxreg = curxreg; ! 138: /* Main search. ! 139: * A flying jump to 'again' will try the next pattern. ! 140: * The 'patp' is predecremented. ! 141: * Yes, this is a bit ugly. */ ! 142: again: ! 143: curbusy = savbusy; ! 144: curxreg = savxreg; ! 145: tp->t_patp = NULL; ! 146: if (--npat < 0) ! 147: return (0); ! 148: ++patp; ! 149: consnapv(10, "%I: ", patp); ! 150: /* Pattern flag: specifies whether this pattern ! 151: * can satisfy the context specified for this tree ! 152: * we must have a hit to match. */ ! 153: pflag = 0; ! 154: if (patp->p_flag != 0) ! 155: pflag = patcache[patp->p_flag-1]; ! 156: if ((nflag&pflag) == 0) { ! 157: consnap(10, "pflag\n"); ! 158: goto again; ! 159: } ! 160: /* Node type: unless pattern specifies no type ! 161: * we must have a hit to match. */ ! 162: if (patp->p_ntype != 0 ! 163: && (typecache[patp->p_ntype-1]&ntype) == 0) { ! 164: consnap(10, "ntype\n"); ! 165: goto again; ! 166: } ! 167: /* Left tree type: unless pattern specifies no type ! 168: * we must have a hit to match. */ ! 169: if (patp->p_ltype != 0 ! 170: && (typecache[patp->p_ltype-1]<ype) == 0) { ! 171: consnap(10, "ltype\n"); ! 172: goto again; ! 173: } ! 174: /* Right tree type: unless pattern specifies no type ! 175: * we must have a hit to match. */ ! 176: if (patp->p_rtype != 0 ! 177: && (typecache[patp->p_rtype-1]&rtype) == 0) { ! 178: consnap(10, "rtype\n"); ! 179: goto again; ! 180: } ! 181: /* Left tree node type: a mismatch will be coerced ! 182: * unless the pattern specifies MMX. ! 183: * bytereg(tp) || ... is dgc's kludge to avoid ADR coercion ! 184: * of byte oriented operations which actually require a ! 185: * register, at least so I (rec) think (thinks). */ ! 186: lpflag = 0; ! 187: if (patp->p_lflag != 0) ! 188: lpflag = flagcache[patp->p_lflag-1]; ! 189: if (lpflag!=0 && (lpflag&lflag)==0 ! 190: && ((lpflag&T_MMX) != 0 ! 191: || (bytereg(tp) && lflag==0 && (lpflag&T_TREG)==0))) { ! 192: consnap(10, "lflag\n"); ! 193: goto again; ! 194: } ! 195: /* Right tree node type: a mismatch will be coerced ! 196: * unless the pattern rspecifies MMX. */ ! 197: rpflag = 0; ! 198: if (patp->p_rflag != 0) ! 199: rpflag = flagcache[patp->p_rflag-1]; ! 200: if (rpflag!=0 && (rpflag&rflag)==0 && (rpflag&T_MMX)!=0) { ! 201: consnap(10, "rflag\n"); ! 202: goto again; ! 203: } ! 204: /* This pattern is acceptable. ! 205: * The simplest case of a match requires ! 206: * only that the pattern pointer be identified. ! 207: * The rest of the code in this routine is activated ! 208: * by requests for registers, TREG loads, and node type coercion. */ ! 209: tp->t_patp = patp; ! 210: tp->t_used = 0; ! 211: /* The pattern may explicitly specify temp ! 212: * registers for a subtrees, or the ! 213: * subtree temp may have to be allocated ! 214: * before the other subtree is selected. */ ! 215: rtemp = NONE; ! 216: if ((rpflag&T_TREG) != 0) { ! 217: rtemp = patp->p_rtemp; ! 218: if (isrealreg(rtemp)) { ! 219: if (isbusy(rtemp)) { ! 220: consnap(10, "rtemp busy\n"); ! 221: goto again; ! 222: } ! 223: setused(tp, rtemp); ! 224: } else if ((lpflag&T_TREG)!=0 && (pflag&P_SRT)==0) { ! 225: rtemp = rallo(rp, tp->t_used, 0); ! 226: if (rtemp < 0) { ! 227: consnap(10, "rtemp allo\n"); ! 228: goto again; ! 229: } ! 230: consnapv(15, "rtemp = %R\n", rtemp); ! 231: setused(tp, rtemp); ! 232: } ! 233: } ! 234: ltemp = NONE; ! 235: if ((lpflag&T_TREG) != 0) { ! 236: ltemp = patp->p_ltemp; ! 237: if (isrealreg(ltemp)) { ! 238: if (isbusy(ltemp)) { ! 239: consnap(10, "ltemp busy\n"); ! 240: goto again; ! 241: } ! 242: setused(tp, ltemp); ! 243: } else if ((rpflag&T_TREG)!=0 && (pflag&P_SLT)==0) { ! 244: ltemp = rallo(lp, tp->t_used, 0); ! 245: if (ltemp < 0) { ! 246: consnap(10, "ltemp allo\n"); ! 247: goto again; ! 248: } ! 249: consnapv(15, "ltemp = %R\n", ltemp); ! 250: setused(tp, ltemp); ! 251: } ! 252: } ! 253: /* The pattern may require a node temp register. ! 254: * If the caller cares, use his preference. ! 255: * If PAIR, allocate a pair so that the right and left ! 256: * preferences (usually LOTEMP) will work out right. ! 257: * The ANY specifier stays around for a while. */ ! 258: ntemp = patp->p_ntemp; ! 259: if (isrealreg(ntemp)) { ! 260: if (isbusy(ntemp)) { ! 261: consnap(10, "ntemp busy\n"); ! 262: goto again; ! 263: } ! 264: } else if (ntemp != NONE) { ! 265: if ((c==MLVALUE || c==MRVALUE) && isrealreg(r)) { ! 266: ptemp = r; ! 267: clash = 0; ! 268: if (ntemp == PAIR) { ! 269: ptemp = enpair(ptemp); ! 270: if ((h=lohalf(ptemp))!=r && isbusy(h)) ! 271: ++clash; ! 272: if ((h=hihalf(ptemp))!=r && isbusy(h)) ! 273: ++clash; ! 274: } ! 275: if (!clash && isusable(tp, c, ptemp)) ! 276: ntemp = ptemp; ! 277: } ! 278: /* Bind only if we must. */ ! 279: if (!isrealreg(ntemp)) { ! 280: if (ntemp == PAIR ! 281: || (ltemp==LOTEMP || ltemp==HITEMP) ! 282: || (rtemp==LOTEMP || rtemp==HITEMP)) { ! 283: ntemp = regselect(tp, ntemp, 1); ! 284: if (ntemp < 0) { ! 285: consnap(10, "ntemp select\n"); ! 286: goto again; ! 287: } ! 288: } ! 289: } ! 290: } ! 291: if (isrealreg(ntemp) && rp!=NULL) { ! 292: consnapv(15, "ntemp = %R\n", ntemp); ! 293: setused(tp, ntemp); ! 294: } ! 295: /* If the pattern specifies addressible ! 296: * subtrees and the subtrees are not directly ! 297: * addressible, then index registers will be ! 298: * required to hold the offset expression. */ ! 299: lindex = rindex = -1; ! 300: if (ishlvadr(rpflag) && !isadr(rflag)) { ! 301: if (!isofs(rflag)) ! 302: cbotch("no rofs"); ! 303: ap = findoffs(rp); ! 304: if ((rindex = rallo(ap, tp->t_used, 2)) < 0) { ! 305: consnap(10, "rindex allo\n"); ! 306: goto again; ! 307: } ! 308: consnapv(15, "rindex = %R\n", rindex); ! 309: curxreg |= reg[rindex].r_phys; ! 310: } ! 311: if (ishlvadr(lpflag) && !isadr(lflag)) { ! 312: if (!isofs(lflag)) ! 313: cbotch("no lofs"); ! 314: ap = findoffs(lp); ! 315: if ((lindex = rallo(ap, tp->t_used, 2)) < 0) { ! 316: consnap(10, "lindex allo\n"); ! 317: goto again; ! 318: } ! 319: consnapv(15, "lindex = %R\n", lindex); ! 320: curxreg |= reg[lindex].r_phys; ! 321: } ! 322: consnap(10, "\n"); ! 323: /* If the pattern specifies T_TREG, then ! 324: * the subtree must be selected. */ ! 325: if ((rpflag&T_TREG) != 0) { ! 326: /* In case two TREG's are specified the ltemp ! 327: * must be identified and setbusy before the rtemp ! 328: * is loaded or ltemp may be clobbered. */ ! 329: ! 330: /* Select an rtemp register based on the share flag, ! 331: * the rtemp preference, and the node preference */ ! 332: if ((pflag&P_SRT) != 0 ! 333: && (rtemp==ANYL || rtemp==ANYR) ! 334: && isrealreg(r) ! 335: && isusable(tp, c, r)) ! 336: stemp = r; ! 337: else ! 338: stemp = reguse(rtemp, ntemp); ! 339: /* Select the subcontext depending on the register selected ! 340: * or the currently specified context */ ! 341: sgoal = subgoal(c, stemp); ! 342: /* Now load the specified register or preferred type */ ! 343: if (select(rp, sgoal, stemp) == 0) ! 344: goto again; ! 345: tp->t_used |= rp->t_used; ! 346: if ((pflag&P_SRT) != 0) { ! 347: if ((ntemp==ANYL || ntemp==ANYR) ! 348: && isusable(tp, c, rp->t_rreg)) ! 349: ntemp = rp->t_rreg; ! 350: else if (patp->p_ntemp == patp->p_rtemp ! 351: && ntemp != rp->t_rreg) { ! 352: consnap(10, "rtemp share\n"); ! 353: goto again; ! 354: } ! 355: } else ! 356: setbusy(rp->t_rreg); /* This is wrong */ ! 357: /* Should be set busy after the ltemp load */ ! 358: ! 359: /* If ltemp was setbusy above, it should now be freed */ ! 360: } ! 361: if ((lpflag&T_TREG) != 0) { ! 362: if ((pflag&P_SLT) != 0 ! 363: && (ltemp==ANYL || ltemp==ANYR) ! 364: && isrealreg(r) ! 365: && isusable(tp, c, r)) ! 366: stemp = r; ! 367: else ! 368: stemp = reguse(ltemp, ntemp); ! 369: sgoal = subgoal(c, stemp); ! 370: if (select(lp, sgoal, stemp) == 0) ! 371: goto again; ! 372: tp->t_used |= lp->t_used; ! 373: if ((pflag&P_SLT) != 0) { ! 374: if ((ntemp==ANYL || ntemp==ANYR) ! 375: && isusable(tp, c, lp->t_rreg)) ! 376: ntemp = lp->t_rreg; ! 377: else if (patp->p_ntemp == patp->p_ltemp ! 378: && ntemp != lp->t_rreg) { ! 379: consnap(10, "ltemp share\n"); ! 380: goto again; ! 381: } ! 382: } else ! 383: setbusy(lp->t_rreg); ! 384: } ! 385: /* Now bind the node temporary if it hasn't already happened. */ ! 386: if (!isrealreg(ntemp) && ntemp!=NONE) { ! 387: ntemp = regselect(tp, ntemp, 1); ! 388: if (ntemp < 0) { ! 389: consnap(10, "ntemp select\n"); ! 390: goto again; ! 391: } ! 392: } ! 393: tp->t_treg = ntemp; ! 394: /* Keep temps used in node coercion off target path */ ! 395: if (ntemp!=NONE && rp!=NULL) ! 396: setused(tp, ntemp); ! 397: /* Force ltemp and rtemp used */ ! 398: if ((lpflag&T_TREG)==0 && isrealreg(patp->p_ltemp)) ! 399: setused(tp, patp->p_ltemp); ! 400: if ((rpflag&T_TREG)==0 && isrealreg(patp->p_rtemp)) ! 401: setused(tp, patp->p_rtemp); ! 402: /* Now coerce the subtrees into rv or lv addressibility ! 403: * if they do not naturally conform. */ ! 404: didstore = 0; ! 405: if (selmiss(rpflag, rflag) && isrvadr(rpflag) && !isadr(rflag)) ! 406: selrv(tp, 1, &didstore); ! 407: if (selmiss(lpflag, lflag) && isrvadr(lpflag) && !isadr(lflag)) ! 408: selrv(tp, 0, &didstore); ! 409: if (selmiss(rpflag, rflag) && islvadr(rpflag) && !isadr(rflag)) ! 410: sellv(tp, rindex, 1, &didstore); ! 411: if (selmiss(lpflag, lflag) && islvadr(lpflag) && !isadr(lflag)) ! 412: sellv(tp, lindex, 0, &didstore); ! 413: /* If coercion generated a stack temp, ! 414: * then we must search the table again ! 415: * for a simpler pattern, after cleaning ! 416: * up any FIXUP's */ ! 417: if (didstore) { ! 418: tp = ripout(tp, 0); ! 419: curbusy = savbusy; ! 420: curxreg = savxreg; ! 421: consnap(1, "Goto rematch\n"); ! 422: goto rematch; ! 423: } ! 424: /* Make node temp used */ ! 425: if (ntemp != NONE) ! 426: setused(tp, ntemp); ! 427: /* Compute the result register */ ! 428: if ((rreg = patp->p_result) == TEMP) ! 429: rreg = ntemp; ! 430: else if (rreg == LOTEMP) ! 431: rreg = lohalf(ntemp); ! 432: else if (rreg == HITEMP) ! 433: rreg = hihalf(ntemp); ! 434: tp->t_rreg = rreg; ! 435: if (rreg != NONE) ! 436: setused(tp, rreg); ! 437: curbusy = savbusy; ! 438: curxreg = savxreg; ! 439: return (1); ! 440: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.