Annotation of researchv10no/cmd/lcc/gen2/gen.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.