Annotation of researchv10no/cmd/lcc/gen2/gen.c, revision 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.