|
|
1.1 ! root 1: /* ! 2: * The routines in this file perform code output. ! 3: * That is, they walk down a selected tree, ! 4: * expanding the code patterns and filling in the blanks. ! 5: */ ! 6: ! 7: #ifdef vax ! 8: #include "INC$LIB:cc1.h" ! 9: #else ! 10: #include "cc1.h" ! 11: #endif ! 12: ! 13: /* ! 14: * Code output. ! 15: * All registers have been set up by selection. ! 16: * A pointer to the selected macro has been stashed in the tree. ! 17: * Walk down the tree, putting out the required code. ! 18: * It would be nice if select and this guy could be one routine. ! 19: */ ! 20: output(tp, c, s, n) ! 21: register TREE *tp; ! 22: { ! 23: register TREE *ap; ! 24: register op; ! 25: int lab0, lab1, rel; ! 26: ! 27: again: ! 28: #if !TINY ! 29: if (oflag > 1) ! 30: snapf("output(%P, %C, %d, L%d); %A\n", ! 31: tp, c, s, n, tp->t_op); ! 32: #endif ! 33: if ((op=tp->t_op) == COMMA) { ! 34: output(tp->t_lp, MEFFECT, 0, 0); ! 35: tp = tp->t_rp; ! 36: goto again; ! 37: } ! 38: if (op == QUEST) { ! 39: lab0 = newlab(); ! 40: lab1 = newlab(); ! 41: output(tp->t_lp, MFLOW, 0, lab0); ! 42: ap = tp->t_rp; ! 43: output(ap->t_lp, c, s, n); ! 44: genubr(lab1); ! 45: genlab(lab0); ! 46: output(ap->t_rp, c, s, n); ! 47: genlab(lab1); ! 48: return; ! 49: } ! 50: if (c == MFLOW) { ! 51: if (op == NOT) { ! 52: s = !s; ! 53: tp = tp->t_lp; ! 54: goto again; ! 55: } ! 56: if (op == LEAF) { ! 57: ap = tp->t_lp; ! 58: if (ap->t_op==ICON || ap->t_op==LCON) { ! 59: if ((grabnval(ap)!=0) == s) ! 60: genubr(n); ! 61: return; ! 62: } ! 63: } ! 64: if (op==ANDAND || op==OROR) { ! 65: if ((op==OROR) == s) { ! 66: output(tp->t_lp, MFLOW, s, n); ! 67: output(tp->t_rp, MFLOW, s, n); ! 68: return; ! 69: } ! 70: lab0 = newlab(); ! 71: output(tp->t_lp, MFLOW, !s, lab0); ! 72: output(tp->t_rp, MFLOW, s, n); ! 73: genlab(lab0); ! 74: return; ! 75: } ! 76: rel = NE; ! 77: if (isrelop(op)) { ! 78: rel = op; ! 79: if (isnval(tp->t_rp, 0) ! 80: && tp->t_lp->t_op != QUEST) { ! 81: if (rel == ULE) ! 82: rel = EQ; ! 83: else if (rel == UGT) ! 84: rel = NE; ! 85: tp = tp->t_lp; ! 86: ap = tp; ! 87: while ((op=ap->t_op) == COMMA) ! 88: ap = ap->t_rp; ! 89: if (isrelop(op) || isflow(op)) { ! 90: switch (rel) { ! 91: ! 92: case EQ: ! 93: case LE: ! 94: case ULE: ! 95: s = !s; ! 96: case NE: ! 97: case GT: ! 98: case UGT: ! 99: goto again; ! 100: } ! 101: } ! 102: } ! 103: } ! 104: if (s == 0) ! 105: rel = otherel[rel-EQ]; ! 106: while ((op=tp->t_op) == COMMA) { ! 107: output(tp->t_lp, MEFFECT, 0, 0); ! 108: tp = tp->t_rp; ! 109: } ! 110: c = MEQ + rel - EQ; ! 111: } ! 112: if (op == CALL) { ! 113: outcall(tp, c, n); ! 114: return; ! 115: } ! 116: if (op == FIXUP) { ! 117: output(tp->t_lp, MRVALUE, 0, 0); ! 118: tp->t_lp->t_op = REG; ! 119: tp->t_lp->t_reg = tp->t_lp->t_rreg; ! 120: walk(tp, amd); ! 121: } ! 122: outtree(tp, c, n); ! 123: } ! 124: ! 125: /* ! 126: * This routine does the general cases of code output. ! 127: * It generates code to output the subgoals, ! 128: * then expands the code macro for this node. ! 129: */ ! 130: outtree(tp, cxt, lab) ! 131: register TREE *tp; ! 132: { ! 133: register TREE *lp, *rp; ! 134: PAT *patp; ! 135: FLAG lflag, rflag, lpflag, rpflag; ! 136: TREE *ap; ! 137: int op; /* Tree operator */ ! 138: int lab0, lab1; /* Manufactured labels */ ! 139: unsigned char *mp; /* Macro pointer */ ! 140: int c; /* Current macro byte */ ! 141: int false; /* Conditional macro state */ ! 142: int opcode; /* Machine operation */ ! 143: int opv; /* Opcode size variant */ ! 144: int naddr; /* Number of addresses output */ ! 145: int nse; /* Side effect flag */ ! 146: int star; /* Indirection of computed address */ ! 147: int npfx; /* Number of prefix bytes */ ! 148: unsigned char pfx[8]; /* Prefix bytes */ ! 149: int label; /* jump label */ ! 150: MASK mask; /* Bit field mask */ ! 151: TREE node; /* Automatic node */ ! 152: ! 153: /* ! 154: * Gather flags and types from the tree node. ! 155: * If the left operand is a FIELD, ! 156: * pull off the field and make up the appropriate mask. ! 157: */ ! 158: #if !TINY ! 159: snapfix(&node); ! 160: if (oflag > 1) { ! 161: snapf("outtree(%P, %C, L%d);\n", tp, cxt, lab); ! 162: if (oflag > 2) ! 163: snapf("%W%E%W", "Outtree", tp, NULL); ! 164: } ! 165: #endif ! 166: if ((patp=tp->t_patp) == NULL) { ! 167: #if !TINY ! 168: printf("tp = "); ! 169: psnap((char *) tp); ! 170: printf("\n"); ! 171: #endif ! 172: cbotch("no patp"); ! 173: } ! 174: if ((lp=tp->t_lp)->t_op == FIELD) { ! 175: mask = ((MASK)01<<lp->t_width) - 1; ! 176: mask = mask << lp->t_base; ! 177: lp = lp->t_lp; ! 178: } ! 179: lflag = lp->t_flag; ! 180: lpflag = 0; ! 181: if (patp->p_lflag != 0) ! 182: lpflag = flagcache[patp->p_lflag-1]; ! 183: rflag = rpflag = 0; ! 184: if ((rp=tp->t_rp) != NULL) { ! 185: rflag = rp->t_flag; ! 186: if (patp->p_rflag != 0) ! 187: rpflag = flagcache[patp->p_rflag-1]; ! 188: } ! 189: /* ! 190: * Perform output for any subgoals. ! 191: * This code is similar to that in select, ! 192: * but works in exactly the reverse order. ! 193: */ ! 194: if (selmiss(lpflag, lflag) ! 195: && islvadr(lpflag) && !isadr(lflag) && !isind(lflag)) ! 196: outofs(lp); ! 197: if (selmiss(rpflag, rflag) ! 198: && islvadr(rpflag) && !isadr(rflag) && !isind(rflag)) ! 199: outofs(rp); ! 200: if (selmiss(lpflag, lflag) && isrvadr(lpflag) && !isadr(lflag)) { ! 201: ap = lp; ! 202: if (isofs(lflag)) ! 203: ap = findoffs(lp); ! 204: output(ap, MLVALUE, 0, 0); ! 205: ap->t_op = REG; ! 206: ap->t_reg = ap->t_rreg; ! 207: walk(lp, amd); ! 208: } ! 209: if (selmiss(rpflag, rflag) && isrvadr(rpflag) && !isadr(rflag)) { ! 210: ap = rp; ! 211: if (isofs(rflag)) ! 212: ap = findoffs(rp); ! 213: output(ap, MLVALUE, 0, 0); ! 214: ap->t_op = REG; ! 215: ap->t_reg = ap->t_rreg; ! 216: walk(rp, amd); ! 217: } ! 218: /* BUG - these are not reversed, but maybe another bug, too */ ! 219: if ((rpflag&T_TREG) != 0) { ! 220: output(rp, MRVALUE, 0, 0); ! 221: rp->t_op = REG; ! 222: rp->t_reg = rp->t_rreg; ! 223: amd(rp, NULL); ! 224: } ! 225: if ((lpflag&T_TREG) != 0) { ! 226: output(lp, MRVALUE, 0, 0); ! 227: lp->t_op = REG; ! 228: lp->t_reg = lp->t_rreg; ! 229: amd(lp, NULL); ! 230: } ! 231: if (isind(lflag)) ! 232: outofs(lp); ! 233: if (isind(rflag)) ! 234: outofs(rp); ! 235: /* ! 236: * Expand the code macro. ! 237: * Handle prefix bytes, ! 238: * the no side effect flag byte, ! 239: * the op variant prefix, ! 240: * jumps to other parts of the table, ! 241: * and conditional macros. ! 242: */ ! 243: #if !TINY ! 244: if (isvariant(VTPROF)) { ! 245: bput(DLABEL); ! 246: bput(DC_LINE); ! 247: iput(patp->p_fline); ! 248: sput(namecache[patp->p_fname]); ! 249: bput(DT_NONE); ! 250: iput(0); ! 251: } ! 252: #endif ! 253: op = tp->t_op; ! 254: lab0 = lab1 = -1; ! 255: false = naddr = opv = nse = npfx = star = 0; ! 256: mp = patp->p_macro; ! 257: while ((c = *mp++) != M_END) { ! 258: /* Unsatisfied conditions ignore everything but goto's */ ! 259: if (false) { ! 260: if (c == M_ENDIF) { ! 261: false = 0; ! 262: continue; ! 263: } ! 264: if (c != M_JMP1 && c != M_JMPB && c != M_JMP2) ! 265: continue; ! 266: } ! 267: switch (c) { ! 268: ! 269: case M_JMP1: ! 270: label = mp[0]; ! 271: jump: ! 272: mp = macros + label; ! 273: continue; ! 274: ! 275: case M_JMPB: ! 276: label = mp - macros - 1 - mp[0]; ! 277: goto jump; ! 278: ! 279: case M_JMP2: ! 280: label = mp[0] + (mp[1] << 8); ! 281: goto jump; ! 282: ! 283: case M_IFV: /* Value context conditional */ ! 284: false = (cxt!=MLVALUE && cxt!=MRVALUE); ! 285: continue; ! 286: ! 287: case M_IFE: /* Effect context conditional */ ! 288: false = (cxt != MEFFECT); ! 289: continue; ! 290: ! 291: case M_IFR: /* Relational context condtional */ ! 292: false = (cxt < MEQ); ! 293: continue; ! 294: ! 295: case M_ENDIF: /* End of conditional */ ! 296: continue; ! 297: ! 298: case M_TN: /* Adjust the opcode according */ ! 299: case M_TL: /* to the type of the base, left, */ ! 300: case M_TR: /* or right node via maptype(...) */ ! 301: opv = c; ! 302: continue; ! 303: ! 304: case M_OP0: /* Use the opcode table to select */ ! 305: case M_OP1: /* one of three variations of opcode */ ! 306: case M_OP2: ! 307: opcode = optab[op-MIOBASE][c-M_OP0]; ! 308: outop: ! 309: opcode = maptype(opv, opcode, tp); ! 310: bput(CODE); ! 311: bput(opcode); ! 312: naddr = opv = 0; ! 313: continue; ! 314: ! 315: case M_CALL: ! 316: outopcall(0); ! 317: continue; ! 318: ! 319: default: /* This should be a machine opcode */ ! 320: if (c < M_ORG) { ! 321: opcode = mapcode(c, tp); ! 322: goto outop; ! 323: } ! 324: cbotch("bad macro %d", c); ! 325: /* NOTREACHED */ ! 326: ! 327: case M_NSE: /* Set no side effect flag for genadr */ ! 328: nse++; ! 329: continue; ! 330: ! 331: case M_HI: /* Set part of address prefix for genadr */ ! 332: case M_LO: ! 333: pfx[npfx++] = c; ! 334: continue; ! 335: ! 336: case M_STAR: /* Indicate indirection of address */ ! 337: star += 1; ! 338: continue; ! 339: ! 340: case M_AN: /* Output address form of base node */ ! 341: ap = tp; ! 342: outadr: ! 343: if (star) ! 344: genstar(ap, nse, npfx, pfx); ! 345: else ! 346: genadr(ap, nse, npfx, pfx); ! 347: nse = npfx = star = 0; ! 348: naddr += 1; ! 349: continue; ! 350: ! 351: case M_AL: /* Output address form of left node */ ! 352: ap = lp; ! 353: goto outadr; ! 354: ! 355: case M_AR: /* Output address form of right node */ ! 356: ap = rp; ! 357: goto outadr; ! 358: ! 359: case M_R: /* Output node register */ ! 360: node.t_reg = tp->t_treg; ! 361: node.t_type = tp->t_type; ! 362: outreg: ! 363: node.t_op = REG; ! 364: ap = &node; ! 365: goto outadr; ! 366: ! 367: case M_RL: /* Output left temp register */ ! 368: node.t_reg = lp->t_rreg; ! 369: node.t_type = lp->t_type; ! 370: goto outreg; ! 371: ! 372: case M_RR: /* Output right temp register */ ! 373: node.t_reg = rp->t_rreg; ! 374: node.t_type = rp->t_type; ! 375: goto outreg; ! 376: ! 377: case M_REGNO: /* Literal register from tables */ ! 378: node.t_op = REG; ! 379: node.t_reg = *mp++; ! 380: ap = &node; ! 381: goto outadr; ! 382: ! 383: case M_ICON: /* Literal ival_t constant */ ! 384: c = *mp++; ! 385: node.t_ival = ivalcache[c-1]; ! 386: outival: ! 387: node.t_op = ICON; ! 388: node.t_type = IVAL_T; ! 389: ap = &node; ! 390: goto outadr; ! 391: ! 392: case M_SIZE: /* Size of block object */ ! 393: node.t_ival = tp->t_size; ! 394: goto outival; ! 395: ! 396: case M_SSIZE: /* Size of block object on stack */ ! 397: node.t_ival = mapssize(tp->t_size); ! 398: goto outival; ! 399: ! 400: case M_LCON: /* Literal lval_t constant */ ! 401: c = *mp++; ! 402: node.t_lval = lvalcache[c-1]; ! 403: outlval: ! 404: node.t_op = LCON; ! 405: node.t_type = LVAL_T; ! 406: ap = &node; ! 407: goto outadr; ! 408: ! 409: case M_EMASK: /* Field extraction mask */ ! 410: node.t_lval = (lval_t) mask; ! 411: goto outlval; ! 412: ! 413: case M_CMASK: /* Field clear mask */ ! 414: node.t_lval = (lval_t) ~mask; ! 415: goto outlval; ! 416: ! 417: case M_GID: /* Literal global identifier */ ! 418: c = *mp++; ! 419: node.t_op = GID; ! 420: node.t_sp = gidpool(gidcache[c-1]); ! 421: node.t_seg = SANY; ! 422: node.t_offs = 0; ! 423: ap = &node; ! 424: goto outadr; ! 425: ! 426: #if BITS ! 427: case M_BITL: /* Bit number of left node */ ! 428: node.t_ival = getbit(lp); ! 429: goto outival; ! 430: ! 431: case M_BITR: /* Bit number of right node */ ! 432: node.t_ival = getbit(rp); ! 433: goto outival; ! 434: #endif ! 435: ! 436: case M_TOS: /* Generate top of stack address */ ! 437: gentos(opcode, naddr++); ! 438: continue; ! 439: ! 440: case M_LAB0: /* Generated label #0 */ ! 441: if (lab0 < 0) ! 442: lab0 = newlab(); ! 443: node.t_label = lab0; ! 444: outlid: ! 445: node.t_op = LID; ! 446: node.t_seg = SANY; ! 447: node.t_offs = 0; ! 448: ap = &node; ! 449: goto outadr; ! 450: ! 451: case M_LAB1: /* Generated label #1 */ ! 452: if (lab1 < 0) ! 453: lab1 = newlab(); ! 454: node.t_label = lab1; ! 455: goto outlid; ! 456: ! 457: case M_DLAB0: /* Define label #0 */ ! 458: if (lab0 < 0) ! 459: lab0 = newlab(); ! 460: bput(LLABEL); ! 461: iput(lab0); ! 462: continue; ! 463: ! 464: case M_DLAB1: /* Define label #1 */ ! 465: if (lab1 < 0) ! 466: lab1 = newlab(); ! 467: bput(LLABEL); ! 468: iput(lab1); ! 469: continue; ! 470: ! 471: case M_LAB: /* The label associated with the tree */ ! 472: node.t_label = lab; ! 473: goto outlid; ! 474: ! 475: case M_REL0: ! 476: case M_REL1: ! 477: bput(CODE); ! 478: bput(optab[cxt-MEQ+EQ-MIOBASE][c-M_REL0]); ! 479: naddr = 0; ! 480: continue; ! 481: ! 482: #if LONGREL ! 483: case M_LREL0: ! 484: case M_LREL1: ! 485: case M_LREL2: ! 486: bput(CODE); ! 487: opcode = cxt-MEQ+EQ; ! 488: if (c == M_LREL2) { ! 489: if (opcode>=GT && opcode<=LT) ! 490: opcode += UGT-GT; ! 491: bput(optab[opcode-MIOBASE][0]); ! 492: naddr = 0; ! 493: continue; ! 494: } ! 495: if (c == M_LREL1) ! 496: opcode = fliprel[opcode-EQ]; ! 497: bput(optab[opcode-MIOBASE][2]); ! 498: naddr = 0; ! 499: continue; ! 500: #endif ! 501: ! 502: } ! 503: } ! 504: } ! 505: ! 506: /* ! 507: * Given a pointer to an offset type tree, ! 508: * dig up the subtree that gets loaded into the base register ! 509: * and make a recursive call to generate the code that does the load. ! 510: */ ! 511: outofs(tp) ! 512: TREE *tp; ! 513: { ! 514: register TREE *ap; ! 515: ! 516: ap = findoffs(tp); ! 517: output(ap, MLVALUE, 0, 0); ! 518: ap->t_op = REG; ! 519: ap->t_reg = ap->t_rreg; ! 520: walk(tp, amd); ! 521: } ! 522: ! 523: #if BITS ! 524: /* ! 525: * Figure out and output a bit number. ! 526: * The argument must be flagged as a bit thing. ! 527: */ ! 528: getbit(tp) ! 529: register TREE *tp; ! 530: { ! 531: register ival_t half; ! 532: ! 533: if ((tp->t_flag&(T_UOBS|T_LOBS|T_UOBC|T_LOBC)) == 0) ! 534: cbotch("bad bit"); ! 535: { ! 536: register op; ! 537: ! 538: while ((op=tp->t_op) == LEAF) ! 539: tp = tp->t_lp; ! 540: if (op == ICON) ! 541: half = tp->t_ival; ! 542: else if ((tp->t_flag&(T_UOBS|T_UOBC)) != 0) ! 543: half = upper(tp->t_lval); ! 544: else ! 545: half = lower(tp->t_lval); ! 546: } ! 547: if ((tp->t_flag&(T_UOBC|T_LOBC)) != 0) ! 548: half = ~half; ! 549: { ! 550: register bitnum; ! 551: ! 552: bitnum = 0; ! 553: while ((half&01) == 0) { ! 554: half >>= 1; ! 555: ++bitnum; ! 556: } ! 557: return (bitnum); ! 558: } ! 559: } ! 560: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.