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