|
|
1.1 ! root 1: /* C compiler: machine-independent back-end support routines */ ! 2: ! 3: #include "c.h" ! 4: ! 5: unsigned freemask[3]; ! 6: int savebase[3]; ! 7: unsigned savemask[3]; ! 8: unsigned tempmask[3]; ! 9: unsigned usedmask[3]; ! 10: unsigned eemask[3]; ! 11: unsigned tmask[3]; ! 12: unsigned vmask[3]; ! 13: ! 14: char **asmstr[MAXINTS]; ! 15: int nregsets; ! 16: Node last; ! 17: int maxoffset; ! 18: int ncalls; ! 19: int offset; ! 20: int argoffset; ! 21: int argbuildsize; ! 22: int bflag, dflag, kflag, pflag, rflag; ! 23: char **opcodes; ! 24: Symbol regs; ! 25: Symbol regvars; ! 26: Symbol rmap[8]; ! 27: int dalign, salign; ! 28: int genx = 2; ! 29: ! 30: static int cseg; ! 31: static Node curhead; ! 32: ! 33: dclproto(static Node *findxnext,(Node)); ! 34: dclproto(static void freereg,(Symbol)); ! 35: dclproto(static void genreload,(Node*, Symbol, int, Symbol)); ! 36: dclproto(static void genreloads,(Node, Symbol, int, Symbol)); ! 37: dclproto(static Symbol genspill,(Symbol, int, Node *)); ! 38: dclproto(static Symbol getreg,(Symbol, Node, unsigned, int)); ! 39: dclproto(static void linearize,(Node, Node *, Node)); ! 40: dclproto(static Node *lin1,(Node, Node *)); ! 41: dclproto(static Symbol mkreg,(char *, int, int, int, int, Symbol)); ! 42: dclproto(static void mvregvar,(Symbol, unsigned)); ! 43: dclproto(static int ntob,(Symbol)); ! 44: dclproto(static int overlaps,(Symbol, Symbol)); ! 45: dclproto(static void ralloc,(Node)); ! 46: dclproto(static int rmember,(Regnode, Symbol)); ! 47: dclproto(static Symbol spillee,(Symbol, Node, unsigned)); ! 48: dclproto(static void spillr,(Symbol, Node)); ! 49: dclproto(static int uses,(Node, Symbol)); ! 50: ! 51: /* aset - record that p and any right ADD+P descendants are address calculations */ ! 52: int aset(p, n) Node p; { ! 53: p = p->kids[n]; ! 54: p->x.loadaddr = 1; ! 55: while (p->op == ADD+P) { ! 56: p = p->kids[1]; ! 57: p->x.loadaddr = 1; ! 58: } ! 59: return 1; ! 60: } ! 61: ! 62: /* bitcount - count number of 1 bits in mask */ ! 63: int bitcount(mask) unsigned mask; { ! 64: unsigned i, n = 0; ! 65: ! 66: for (i = 1; i; i <<= 1) ! 67: if (mask&i) ! 68: n++; ! 69: return n; ! 70: } ! 71: ! 72: /* blkcopy - emit code to copy size bytes from sreg+soff to dreg+doff using tmp regs */ ! 73: void blkcopy(dreg, doff, sreg, soff, size, tmp) int tmp[]; { ! 74: if (size <= 0) ! 75: return; ! 76: else if (size <= 1) { ! 77: blkunroll(1, dreg, doff, sreg, soff, size, tmp); ! 78: } else if (size <= 3) { ! 79: blkunroll(2, dreg, doff, sreg, soff, 2, tmp); ! 80: blkcopy(dreg, doff+(size&~(2-1)), sreg, soff+(size&~(2-1)), size&(2-1), tmp); ! 81: } else if (size <= 16) { ! 82: blkunroll(4, dreg, doff, sreg, soff, size&~(4-1), tmp); ! 83: blkcopy(dreg, doff+(size&~(4-1)), sreg, soff+(size&~(4-1)), size&(4-1), tmp); ! 84: } else ! 85: (*IR->x.blkloop)(dreg, doff, sreg, soff, size, tmp); ! 86: } ! 87: ! 88: /* blkunroll - blkcopy as an unrolled loop using k-byte chunks */ ! 89: void blkunroll(k, dreg, doff, sreg, soff, size, tmp) int tmp[]; { ! 90: int i; ! 91: ! 92: assert(IR->x.maxunalignedload); ! 93: if ((salign < k || dalign < k) && k > IR->x.maxunalignedload) ! 94: k = IR->x.maxunalignedload; ! 95: (*IR->x.blkfetch)(k, soff, sreg, tmp[0]); ! 96: for (i = k; i <= size - k; i += k) { ! 97: (*IR->x.blkfetch)(k, i+soff, sreg, tmp[(i&k)==k]); ! 98: (*IR->x.blkstore)(k, i+doff-k, dreg, tmp[(i&k)!=k]); ! 99: } ! 100: (*IR->x.blkstore)(k, i+doff-k, dreg, tmp[((i-k)&k)==k]); ! 101: } ! 102: ! 103: /* blockbeg - begin a compound statement */ ! 104: void blockbeg(e) Env *e; { ! 105: int i; ! 106: ! 107: e->off = offset; ! 108: for (i = 0; i < nregsets; i++) ! 109: e->freemask[i] = freemask[i]; ! 110: } ! 111: ! 112: /* blockend - end a compound statement */ ! 113: void blockend(e) Env *e; { ! 114: int i; ! 115: ! 116: if (offset > maxoffset) ! 117: maxoffset = offset; ! 118: offset = e->off; ! 119: for (i = 0; i < nregsets; i++) ! 120: freemask[i] = e->freemask[i]; ! 121: } ! 122: ! 123: /* docall - finalize a call */ ! 124: void docall(p) Node p; { ! 125: if (argoffset > argbuildsize) ! 126: argbuildsize = argoffset; ! 127: p->syms[0] = intconst(argoffset); ! 128: argoffset = 0; ! 129: } ! 130: ! 131: /* dumpregs - trace register allocation */ ! 132: void dumpregs(msg, a, b) char *a, *b, *msg; { ! 133: int i; ! 134: ! 135: fprint(2, msg, a, b); ! 136: for (i = 0; i < nregsets; i++) ! 137: fprint(2, "(free[%d]=%x)\n", i, freemask[i]); ! 138: } ! 139: ! 140: /* dumptree1 - emit debugging image of dag p, indented n, with kid# k */ ! 141: void dumptree1(p, op, k, n) Node p; { ! 142: int i; ! 143: char *s; ! 144: extern char **opcodes; ! 145: ! 146: if (dflag == 0 || p == 0) ! 147: return; ! 148: for (i = 0; i < n; i++) ! 149: fprint(2, " "); ! 150: if (k < 0) ! 151: fprint(2, "(root=%x ", p); ! 152: else ! 153: fprint(2, "(kid%d=%x ", k, p); ! 154: s = opname(op); ! 155: if (*s >= '0' && *s <= '9') ! 156: s = opcodes[op]; ! 157: fprint(2, "op=%s ", s); ! 158: for (i = 0; i < MAXINTS; i++) ! 159: if (p->x.ints[i]) ! 160: fprint(2, "I%d=%s ", i, asmstr[i][p->x.ints[i]]); ! 161: for (i = 0; i < MAXSYMS; i++) ! 162: if (p->syms[i]) ! 163: fprint(2, "S%d=%s ", i, p->syms[i]->x.name); ! 164: fprint(2, "count=%d)\n", p->count); ! 165: if (p->x.registered == 0) ! 166: for (i = 0; i < MAXKIDS; i++) ! 167: if (p->kids[i]) ! 168: dumptree1(p->kids[i], p->kids[i]->op, i, n+1); ! 169: if (k == -1) ! 170: fprint(2, "\n"); ! 171: } ! 172: ! 173: void export(p) Symbol p; { ! 174: if (!bflag) ! 175: print(IR->x.exportfmt, p->x.name); ! 176: } ! 177: ! 178: /* findxnext - return the address of the pointer to p in the linearized chain */ ! 179: static Node *findxnext(p) Node p; { ! 180: Node *q; ! 181: ! 182: for (q = &curhead; *q; q = &(*q)->x.next) ! 183: if (*q == p) ! 184: return q; ! 185: assert(0); ! 186: return 0; ! 187: } ! 188: ! 189: /* freereg - free register p */ ! 190: static void freereg(p) Symbol p; { ! 191: assert(p->x.regnode); ! 192: p->x.regnode->count = 0; ! 193: freemask[p->x.regnode->regset] |= p->x.regnode->mask; ! 194: debug(rflag, dumpregs("(freeing %s)\n", p->x.name, 0)); ! 195: } ! 196: ! 197: /* freeregvars - free register variables */ ! 198: void freeregvars() { ! 199: Symbol p; ! 200: ! 201: for (p = regvars; p; p = p->x.nextregvar) { ! 202: Regnode r = p->x.regvar->x.regnode; ! 203: usedmask[r->regset] |= r->mask; ! 204: freereg(p->x.regvar); ! 205: } ! 206: } ! 207: ! 208: /* gen - drive nodelist from front end through all back-end phases */ ! 209: Node gen(nodelist) Node nodelist; { ! 210: int i; ! 211: Node p, q = 0; ! 212: ! 213: curhead = nodelist; ! 214: last = 0; ! 215: for (p = nodelist; p; p = p->link) { ! 216: switch (generic(p->op)) { ! 217: case CALL: ! 218: p->x.sideeffect = 1; ! 219: p->x.iscall = 1; ! 220: p->x.args = q; ! 221: q = 0; ! 222: (*IR->x.docall)(p); ! 223: break; ! 224: case ARG: ! 225: p->x.isarg = 1; ! 226: p->x.args = q; ! 227: q = p; ! 228: (*IR->x.doarg)(p); ! 229: /* fall through */ ! 230: case ASGN: case JUMP: case LABEL: case RET: ! 231: case EQ: case GE: case GT: case LE: case LT: case NE: ! 232: assert(p->count == 0); ! 233: p->x.sideeffect = 1; ! 234: break; ! 235: case INDIR: ! 236: p->x.unavailable = 1; ! 237: assert(p->count); ! 238: break; ! 239: case DIV: case MOD: case MUL: ! 240: if (IR->mulops_are_calls && (optype(p->op) == I || optype(p->op) == U)) ! 241: break; ! 242: /* else fall through */ ! 243: default: ! 244: assert(0); ! 245: } ! 246: (*IR->x.rewrite)(p); ! 247: last = p; ! 248: debug(dflag, fprint(2, "(last=%x)\n", last)); ! 249: } ! 250: last = 0; ! 251: linearize(curhead, &curhead, 0); ! 252: for (p = curhead; p; p = p->x.next) { ! 253: assert(p->x.sideeffect || p->count); ! 254: if (p->x.registered == 0) { ! 255: if (p->x.iscall) ! 256: for (q = p->x.args; q; q = q->x.args) ! 257: if (q->syms[RX] && q->syms[RX]->x.regnode) ! 258: freereg(q->syms[RX]); ! 259: ralloc(p); ! 260: if (p->x.isarg && p->syms[RX] && p->syms[RX]->x.regnode) ! 261: p->syms[RX]->x.regnode->count = -1; ! 262: else if (p->x.listed && p->count == 0 && p->syms[RX] && p->syms[RX]->x.regnode && p->syms[RX]->x.regnode->count >= 0) ! 263: freereg(p->syms[RX]); ! 264: last = p; ! 265: } else ! 266: last = 0; ! 267: } ! 268: for (i = 0; i < nregsets; i++) { ! 269: freemask[i] |= tempmask[i]; ! 270: tempmask[i] = 0; ! 271: } ! 272: return curhead; ! 273: } ! 274: ! 275: /* genascii - emit ascii string str */ ! 276: void genascii(ascii, byte, len, str) char *ascii, *byte, *str; { ! 277: char *s = str; ! 278: int m, n; ! 279: ! 280: for (n = 5, m = 9; s < str + len; s++) { ! 281: if (*s == '"' || *s == '\\') ! 282: m += 2; ! 283: else ! 284: m += *s < ' ' || *s >= 0177 ? 4 : 1; ! 285: n += *s < 10 ? 2 : *s < 100 ? 3 : 4; ! 286: } ! 287: s = str; ! 288: if (ascii == 0 || n < m) { ! 289: print("%s %d", byte, (*s++)&0xff); ! 290: for (n = 0; s < str + len; n++) ! 291: if (n > 10) { ! 292: n = 0; ! 293: print("\n%s %d", byte, (*s++)&0xff); ! 294: } else ! 295: print(",%d", (*s++)&0xff); ! 296: outs("\n"); ! 297: } else { ! 298: n = 0; ! 299: print("%s \"", ascii); ! 300: for (s = str; s < str + len; s++) { ! 301: if (n >= 64) { ! 302: print("\"\n%s \"", ascii); ! 303: n = 0; ! 304: } ! 305: if (*s == '"' || *s == '\\') { ! 306: print("\\%c", *s); ! 307: n += 2; ! 308: } else if (*s >= ' ' && *s < 0177) { ! 309: *bp++ = *s; ! 310: n += 1; ! 311: } else { ! 312: print("\\%d%d%d", (*s>>6)&3, (*s>>3)&7, *s&7); ! 313: n += 4; ! 314: } ! 315: } ! 316: outs("\"\n"); ! 317: } ! 318: } ! 319: ! 320: /* genreload - make *pp use reloads instead of r */ ! 321: static void genreload(pp, temp, ty, r) Node *pp; Symbol r, temp; { ! 322: int i; ! 323: Node p = *pp; ! 324: ! 325: for (i = 0; i < MAXKIDS; i++) ! 326: if (p->kids[i] && p->kids[i]->syms[RX] == r && p->kids[i]->x.registered) { ! 327: Symbol target = p->kids[i]->x.rtarget; ! 328: p->kids[i] = newnode(INDIR + ty, newnode(ADDRL+P, 0, 0, temp), 0, 0); ! 329: p->kids[i]->count = 1; ! 330: (*IR->x.rewrite)(p->kids[i]); ! 331: if (target) ! 332: rtarget(p, i, target); ! 333: (*IR->x.rewrite)(p); ! 334: linearize(p->kids[i], pp, *pp); ! 335: if (p->kids[i]) ! 336: pp = &p->kids[i]->x.next; ! 337: } ! 338: } ! 339: ! 340: /* genreloads - make the nodes after dot use reloads instead of r */ ! 341: static void genreloads(dot, temp, ty, r) Node dot; Symbol r, temp; { ! 342: Node p, *pp; ! 343: ! 344: if (IR->x.twoop && dot->x.zap0) { ! 345: pp = findxnext(dot); ! 346: genreload(pp, temp, ty, r); ! 347: for (p = *pp; p != dot; p = p->x.next) ! 348: ralloc(*pp); ! 349: } ! 350: for (pp = &dot->x.next; dot = *pp; pp = &dot->x.next) ! 351: genreload(pp, temp, ty, r); ! 352: } ! 353: ! 354: /* genspill - generate code to spill r and return the temp used */ ! 355: static Symbol genspill(r, ty, last) Symbol r; Node *last; { ! 356: Node p, q; ! 357: Symbol s, tmp; ! 358: static struct symbol z; ! 359: unsigned i, savemask[(sizeof freemask)/(sizeof freemask[0])]; ! 360: ! 361: for (i = 0; i < nregsets; i++) { ! 362: savemask[i] = vmask[i]; ! 363: vmask[i] &= ~usedmask[i]; ! 364: } ! 365: tmp = newtemp(REGISTER, ty); ! 366: for (i = 0; i < nregsets; i++) ! 367: vmask[i] = savemask[i]; ! 368: debug(rflag, fprint(2, "(spilling %s to symbol %s=%s)\n", r->x.name, tmp->name, tmp->x.name)); ! 369: s = (Symbol) talloc(sizeof *s); ! 370: *s = z; ! 371: s->sclass = REGISTER; ! 372: s->x.name = r->x.name; ! 373: symeaddr(s) = symeaddr(r); ! 374: s->x.regvar = r; ! 375: q = newnode(ADDRL+P, 0, 0, s); ! 376: q = newnode(INDIR + ty, q, 0, 0); ! 377: p = newnode(ADDRL+P, 0, 0, tmp); ! 378: p = newnode(ASGN + ty, p, q, 0); ! 379: p->x.sideeffect = 1; ! 380: (*IR->x.rewrite)(p); ! 381: q = *last; ! 382: linearize(p, last, q); ! 383: for (p = *last; p != q; p = p->x.next) ! 384: ralloc(p); ! 385: return tmp; ! 386: } ! 387: ! 388: /* getint - return value of signed integer constant */ ! 389: int getint(p) Symbol p; { ! 390: switch (ttob(p->type)) { ! 391: case C: return p->u.c.v.sc; ! 392: case S: return p->u.c.v.ss; ! 393: default: return p->u.c.v.i; ! 394: } ! 395: } ! 396: ! 397: /* getreg - assign a register from set rs to node p */ ! 398: static Symbol getreg(rs, p, rmask, count) Symbol rs; Node p; unsigned rmask; { ! 399: Regnode rn; ! 400: Symbol r; ! 401: ! 402: if (rs->x.regnode->link == 0) ! 403: rmask = -1; ! 404: for (r = rs; r; r = rn->link) { ! 405: rn = r->x.regnode; ! 406: assert(rn); ! 407: if ((rn->mask&~(freemask[rn->regset]&rmask)) == 0) { ! 408: freemask[rn->regset] &= ~rn->mask; ! 409: r->x.regnode->node = p; ! 410: r->x.regnode->count = count; ! 411: return r; ! 412: } ! 413: } ! 414: if (p == 0) /* register variable */ ! 415: return 0; ! 416: r = spillee(rs, p, rmask); ! 417: spill(r->x.regnode->mask, r->x.regnode->regset, p); ! 418: r = getreg(rs, p, rmask, count); ! 419: assert(r); ! 420: return r; ! 421: } ! 422: ! 423: /* getregnode - return regnode for register variable or codegen temp */ ! 424: Regnode getregnode(p) Symbol p; { ! 425: assert(p); ! 426: if (p->x.regvar) { ! 427: assert(!p->x.regnode); ! 428: assert(p->x.regvar->x.regnode); ! 429: return p->x.regvar->x.regnode; ! 430: } else { ! 431: assert(p->x.regnode); ! 432: return p->x.regnode; ! 433: } ! 434: } ! 435: ! 436: /* getregset - return index of the register set to which p's been allocated */ ! 437: int getregset(p) Symbol p; { ! 438: if (p->sclass == REGISTER) { ! 439: assert(p->x.regvar); ! 440: return getregnode(p)->regset; ! 441: } else ! 442: return -1; ! 443: } ! 444: ! 445: /* getregvar - assign variable p to a register if possible */ ! 446: int getregvar(p, reglist) Symbol p, reglist; { ! 447: Symbol reg; ! 448: ! 449: assert(p && p->type); ! 450: if (reglist && isscalar(p->type) && isregvar(p) && (reg = getreg(reglist, 0, vmask[reglist->x.regnode->regset], -1))) { ! 451: p->x.regvar = reg; ! 452: p->x.name = reg->x.name; ! 453: symeaddr(p) = symeaddr(reg); ! 454: p->x.nextregvar = regvars; ! 455: regvars = p; ! 456: debug(rflag, dumpregs("(allocating %s to symbol %s)\n", p->x.name, p->name)); ! 457: if (p->temporary) ! 458: tempmask[reg->x.regnode->regset] |= reg->x.regnode->mask; ! 459: return 1; ! 460: } else { ! 461: p->sclass = AUTO; ! 462: return 0; ! 463: } ! 464: } ! 465: ! 466: /* getunsigned - return value of unsigned integer constant */ ! 467: unsigned getunsigned(p) Symbol p; { ! 468: switch (ttob(p->type)) { ! 469: case C: return p->u.c.v.uc; ! 470: case S: return p->u.c.v.us; ! 471: default: return p->u.c.v.u; ! 472: } ! 473: } ! 474: ! 475: /* initfunc - common function initialization */ ! 476: void initfunc(a, b, c) { ! 477: int i; ! 478: ! 479: offset = b; ! 480: maxoffset = 0; ! 481: argbuildsize = c; ! 482: ncalls = a; ! 483: regvars = 0; ! 484: for (i = 0; i < nregsets; i++) { ! 485: usedmask[i] = 0; ! 486: freemask[i] = -1; ! 487: } ! 488: } ! 489: ! 490: /* linearize - linearize nodelist p */ ! 491: static void linearize(p, last, next) Node *last, next, p; { ! 492: for (; p; p = p->link) ! 493: if (p->x.sideeffect || p->count > 0) { ! 494: last = lin1(p, last); ! 495: p->x.listed = 1; ! 496: } ! 497: *last = next; ! 498: } ! 499: ! 500: /* lin1 - linearize dag p */ ! 501: static Node *lin1(p, last) Node p, *last; { ! 502: int i; ! 503: ! 504: if (p->x.linearized) ! 505: return last; ! 506: for (i = 0; i < MAXKIDS; i++) ! 507: if (p->kids[i]) ! 508: last = lin1(p->kids[i], last); ! 509: p->x.linearized = 1; ! 510: *last = p; ! 511: debug(rflag, fprint(2, "(listing %x)\n", p)); ! 512: return &p->x.next; ! 513: } ! 514: ! 515: /* lop - p->syms[i] &= mask */ ! 516: int lop(p, i, size) Node p; { ! 517: unsigned before = getunsigned(p->syms[i]); ! 518: unsigned after = before&((1<<size) - 1); ! 519: ! 520: if (before == after) ! 521: return 0; ! 522: else { ! 523: Value v; ! 524: v.u = after; ! 525: p->syms[i] = constant(p->syms[i]->type, v); ! 526: return 1; ! 527: } ! 528: } ! 529: ! 530: /* mkactual - make next frame offset */ ! 531: int mkactual(prealign, size, postalign) { ! 532: int n = roundup(argoffset, prealign); ! 533: argoffset = roundup(n + size, postalign); ! 534: return n; ! 535: } ! 536: ! 537: /* mkauto - make next local */ ! 538: int mkauto(p, align) Symbol p; { ! 539: offset = roundup(offset + p->type->size, align); ! 540: p->x.offset = -offset; ! 541: return -offset; ! 542: } ! 543: ! 544: /* mkreg - create register s with given mask, regset, and link */ ! 545: static Symbol mkreg(s, n, mask, regset, regtype, link) char *s; Symbol link; { ! 546: static struct symbol zs; ! 547: static struct regnode zr; ! 548: Symbol q = (Symbol)alloc(sizeof *q); ! 549: ! 550: *q = zs; ! 551: q->x.name = string(s); ! 552: symeaddr(q) = atoi(s); ! 553: q->x.regnode = (Regnode)alloc(sizeof *q->x.regnode); ! 554: *q->x.regnode = zr; ! 555: q->x.regnode->regnum = n; ! 556: q->x.regnode->mask = mask; ! 557: q->x.regnode->link = link; ! 558: q->x.regnode->regset = regset; ! 559: q->x.regnode->regtype = regtype; ! 560: q->x.regnode->next = regs; ! 561: regs = q; ! 562: return q; ! 563: } ! 564: ! 565: /* mkregs - create registers lo to hi by inc with given mask and type */ ! 566: Symbol mkregs(fmt, lo, hi, inc, mask, regset, regtype, p) char *fmt; Symbol p; { ! 567: for (; lo*inc <= hi*inc; lo += inc) ! 568: p = mkreg(stringf(fmt, lo), lo, mask << lo, regset, regtype, p); ! 569: return p; ! 570: } ! 571: ! 572: /* mvregvar - move register variable */ ! 573: static void mvregvar(p, mask) Symbol p; unsigned mask; { ! 574: Symbol reg; ! 575: ! 576: if (reg = getreg(rmap[ttob(p->type)], 0, ~mask, -1)) { ! 577: freereg(p->x.regvar); ! 578: p->x.regvar = reg; ! 579: p->x.name = reg->x.name; ! 580: symeaddr(p) = symeaddr(reg); ! 581: debug(rflag, dumpregs("(moving register variable %s to %s)\n", p->name, p->x.name)); ! 582: } ! 583: } ! 584: ! 585: /* mvregvars - move register variables to reduce callee saves */ ! 586: void mvregvars() { ! 587: Symbol p; ! 588: ! 589: if (ncalls == 0) { ! 590: unsigned i, mask[(sizeof usedmask)/(sizeof usedmask[0])]; ! 591: for (i = 0; i < nregsets; i++) ! 592: mask[i] = usedmask[i] | eemask[i]; ! 593: for (p = regvars; p; p = p->x.nextregvar) { ! 594: Regnode r = p->x.regvar->x.regnode; ! 595: mask[r->regset] |= r->mask; ! 596: } ! 597: for (p = regvars; p; p = p->x.nextregvar) { ! 598: Regnode r = p->x.regvar->x.regnode; ! 599: if (r->mask&eemask[r->regset]) ! 600: mvregvar(p, mask[r->regset]); ! 601: } ! 602: } ! 603: freeregvars(); ! 604: } ! 605: ! 606: /* ntob - infer type suffix from register set for register p */ ! 607: static int ntob(p) Symbol p; { ! 608: Regnode r = getregnode(p); ! 609: assert(r->regtype); ! 610: return r->regtype; ! 611: } ! 612: ! 613: /* overlaps - do registers x and y overlap? */ ! 614: static int overlaps(x, y) Symbol x, y; { ! 615: Regnode rx = getregnode(x), ry = getregnode(y); ! 616: return rx->regset == ry->regset && rx->mask&ry->mask; ! 617: } ! 618: ! 619: /* parseflags - parse back end flags */ ! 620: void parseflags(argc, argv) char *argv[]; { ! 621: for (++argv; --argc > 0; ++argv) ! 622: if (strcmp(*argv, "-d") == 0) ! 623: dflag++; ! 624: else if (strcmp(*argv, "-p") == 0 || strcmp(*argv, "-pg") == 0) ! 625: pflag++; ! 626: else if (strcmp(*argv, "-r") == 0) ! 627: rflag++; ! 628: else if (strcmp(*argv, "-k") == 0) ! 629: kflag++; ! 630: } ! 631: ! 632: void progend() {} ! 633: ! 634: /* ralloc - assign registers for p */ ! 635: static void ralloc(p) Node p; { ! 636: Symbol s; ! 637: int i, n; ! 638: ! 639: assert(p && p->x.registered == 0); ! 640: n = IR->x.twoop && p->x.zap0 ? 1 : MAXKIDS; ! 641: for (i = 0; i < n; i++) ! 642: if (p->kids[i]) { ! 643: assert(p->kids[i]->x.registered); ! 644: s = p->kids[i]->syms[RX]; ! 645: if (s == 0) { ! 646: debug(rflag, fprint(2, "(%x->kids[%d]=%x has no register allocated)\n", p, i, p->kids[i])); ! 647: assert(s); ! 648: } ! 649: if (s->x.regnode && s->x.regnode->count >= 0 && --s->x.regnode->count == 0) ! 650: freereg(s); ! 651: } ! 652: s = p->syms[RX]; ! 653: if (s && s->x.regnode) { ! 654: p->syms[RX] = getreg(s, p, tmask[s->x.regnode->regset], p->count); ! 655: usedmask[p->syms[RX]->x.regnode->regset] |= p->syms[RX]->x.regnode->mask; ! 656: debug(rflag, dumpregs("(allocating %s to node %x)\n", p->syms[RX]->x.name, (char *) p)); ! 657: } ! 658: for (i = n; i < MAXKIDS; i++) ! 659: if (p->kids[i]) { ! 660: assert(p->kids[i]->x.registered); ! 661: s = p->kids[i]->syms[RX]; ! 662: assert(s); ! 663: if (s->x.regnode && s->x.regnode->count >= 0 && --s->x.regnode->count == 0) ! 664: freereg(s); ! 665: } ! 666: p->x.registered = 1; ! 667: (*IR->x.final)(p); ! 668: } ! 669: ! 670: /* range - does signed k fit in n bits? */ ! 671: int range(k, n) { ! 672: return k >= -(1<<(n - 1)) && k < (1<<(n - 1)); ! 673: } ! 674: ! 675: /* regchain - does this binary instruction overwrite its left operand? */ ! 676: regchain(a) Node a; { ! 677: return a->kids[0] == 0 || a->kids[0]->syms[RX] == a->syms[RX]; ! 678: } ! 679: ! 680: /* regloc - return "id" for p's register */ ! 681: unsigned regloc(p) Symbol p; { ! 682: assert(p && p->sclass == REGISTER && p->x.regvar && p->x.regvar->x.regnode); ! 683: return p->x.regvar->x.regnode->regset<<8 | p->x.regvar->x.regnode->regnum; ! 684: } ! 685: ! 686: /* rmcopy - remove the register-to-register copy in node a? */ ! 687: int rmcopy(a) Node a; { ! 688: return !isregvar(a->syms[RX]) && !a->x.unavailable; ! 689: } ! 690: ! 691: /* rmember - is regnode r in register class s? */ ! 692: static int rmember(r, s) Regnode r; Symbol s; { ! 693: assert(r && s->x.regnode); ! 694: for (; s; s = s->x.regnode->link) ! 695: if (r->regset == s->x.regnode->regset && r->mask == s->x.regnode->mask) ! 696: return 1; ! 697: return 0; ! 698: } ! 699: ! 700: /* rtarget - evaluate p->kids[n] into register r */ ! 701: void rtarget(p, n, r) Node p; Symbol r; { ! 702: Node q; ! 703: Regnode regnode; ! 704: Symbol s; ! 705: ! 706: assert(p && r); ! 707: q = p->kids[n]; ! 708: assert(q && r); ! 709: regnode = getregnode(r); ! 710: assert(r->x.regvar || regnode->link == 0); ! 711: s = q->syms[RX]; ! 712: assert(s); ! 713: if (!isregvar(s) && rmember(regnode, s)) { ! 714: debug(rflag, fprint(2, "(targeting %x to %s)\n", q, r->x.name)); ! 715: q->syms[RX] = q->x.rtarget = r; ! 716: } else { ! 717: debug(rflag, fprint(2, "(moving %x to %s)\n", q, r->x.name)); ! 718: q->count--; ! 719: p->kids[n] = q = newnode(LOAD + ntob(q->syms[RX]), q, 0, q->syms[0]?q->syms[0]:p->syms[0]); ! 720: q->count++; ! 721: q->syms[RX] = q->x.rtarget = r; ! 722: (*IR->x.rewrite)(q); ! 723: } ! 724: } ! 725: ! 726: /* setseg - switch to logical segment n (1..5) */ ! 727: void setseg(n) { ! 728: assert(n >= 0 && n < sizeof IR->x.segnames/sizeof IR->x.segnames[0]); ! 729: cseg = n; ! 730: if (IR->x.segnames[n-1]) ! 731: print("%s\n", IR->x.segnames[n-1]); ! 732: } ! 733: ! 734: /* spacen - allocate n bytes of space in the current segment */ ! 735: void spacen(n, prefix) char *prefix; { ! 736: if (cseg != BSS) ! 737: print("%s ", prefix); ! 738: print("%d\n", n); ! 739: } ! 740: ! 741: /* spill - spill all busy registers in regset n that overlap mask */ ! 742: void spill(mask, n, dot) unsigned mask; Node dot; { ! 743: Symbol r; ! 744: ! 745: if (mask&~freemask[n]) ! 746: for (r = regs; r; r = r->x.regnode->next) ! 747: if (n == r->x.regnode->regset && mask&r->x.regnode->mask && r->x.regnode->count) ! 748: spillr(r, dot); ! 749: usedmask[n] |= mask; ! 750: } ! 751: ! 752: /* spillee - identify most-distantly-used register in register class r */ ! 753: static Symbol spillee(r, dot, rmask) Node dot; Symbol r; unsigned rmask; { ! 754: int bestdist = -1; ! 755: Symbol bestreg = 0; ! 756: ! 757: for (; r; r = r->x.regnode->link) ! 758: if ((r->x.regnode->mask&~rmask) == 0 && r->x.regnode->count >= 0) { ! 759: Node q; ! 760: int dist = 0; ! 761: for (q = dot; q && !uses(q, r); q = q->x.next) ! 762: dist++; ! 763: if (q && dist > bestdist) { /* no local use => reg vbl */ ! 764: bestdist = dist; ! 765: bestreg = r; ! 766: } ! 767: } ! 768: assert(bestreg); ! 769: return bestreg; ! 770: } ! 771: ! 772: /* spillr - spill register r */ ! 773: static void spillr(r, dot) Symbol r; Node dot; { ! 774: int ty = ntob(r); ! 775: if (r->x.regnode->count < 0) { ! 776: Node p = newnode(LOAD+ty, ! 777: newnode(INDIR+ty, ! 778: newnode(ADDRL+P, 0, 0, ! 779: genspill(r, ty, findxnext(dot))), 0, 0), 0, 0); ! 780: p->syms[RX] = r; ! 781: p->x.sideeffect = 1; ! 782: (*IR->x.rewrite)(p); ! 783: linearize(p, &dot->x.next, dot->x.next); ! 784: p->x.registered = 1; ! 785: } else if (dot->x.registered && r == dot->syms[RX]) { ! 786: /* dot can't have set it yet, so no spill is needed */ ! 787: } else { ! 788: genreloads(dot, genspill(r, ty, &r->x.regnode->node->x.next), ty, r); ! 789: freereg(r); ! 790: } ! 791: } ! 792: ! 793: /* uses - does node p read register r? */ ! 794: static int uses(p, r) Node p; Symbol r; { ! 795: int i; ! 796: ! 797: for (i = 0; i < MAXKIDS; i++) ! 798: if ( ! 799: p->kids[i] && ! 800: p->kids[i]->x.registered && ! 801: overlaps(r, p->kids[i]->syms[RX]) ! 802: ) ! 803: return 1; ! 804: return 0; ! 805: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.