Annotation of researchv10no/cmd/lcc/c/dag.c, revision 1.1.1.1

1.1       root        1: /* C compiler: dag processing */
                      2: 
                      3: #include "c.h"
                      4: #define NBUCKETS 020
                      5: 
                      6: struct code codehead = { Start };
                      7: Code codelist = &codehead;     /* list of code nodes for current function */
                      8: int nodecount;                 /* # of available nodes in hash table */
                      9: 
                     10: static struct dag {            /* dags: */
                     11:        struct node node;               /* the node itself */
                     12:        struct dag *hlink;              /* next dag on hash chain */
                     13: } *buckets[NBUCKETS];          /* hash table */
                     14: static Node nodelist;          /* node list */
                     15: dclproto(static struct dag *dagnode,(int, Node, Node, Symbol));
                     16: dclproto(static void fixup,(Node));
                     17: dclproto(static int haskid,(Node, Node));
                     18: dclproto(static Node labelnode,(int));
                     19: dclproto(static Node list,(Node));
                     20: dclproto(static void reset,(void));
                     21: dclproto(static void remove,(Node));
                     22: dclproto(static void trash,(Node));
                     23: dclproto(static void typestab,(Symbol, Generic));
                     24: dclproto(static Node undag,(Node));
                     25: dclproto(static Node undag1,(Node, Node));
                     26: 
                     27: /* addlocal - add local p to list of locals for the current block */
                     28: void addlocal(p) Symbol p; {
                     29:        if (!p->defined) {
                     30:                code(Local)->u.var = p;
                     31:                p->defined = 1;
                     32:                p->scope = level;
                     33:        }
                     34: }
                     35: 
                     36: /* btot - map operator op or suffix op into a representative type */
                     37: Type btot(op) int op; {
                     38:        switch (optype(op)) {
                     39:        case F: return floattype;
                     40:        case D: return doubletype;
                     41:        case C: return chartype;
                     42:        case S: return shorttype;
                     43:        case I: return inttype;
                     44:        case U: return unsignedtype;
                     45:        case P: return voidptype;
                     46:        default: assert(0);
                     47:        }
                     48:        return 0;
                     49: }
                     50: 
                     51: /* code - allocate a code node of kind and append to the code list */
                     52: Code code(kind) {
                     53:        Code cp;
                     54: 
                     55:        if (kind > Label) {
                     56:                for (cp = codelist; cp->kind < Label; )
                     57:                        cp = cp->prev;
                     58:                if (cp->kind == Jump)
                     59:                        warning("unreachable code\n");
                     60:        }
                     61:        cp = (Code)talloc(sizeof *cp);
                     62:        cp->kind = kind;
                     63:        cp->prev = codelist;
                     64:        cp->next = 0;
                     65:        codelist->next = cp;
                     66:        return codelist = cp;
                     67: }
                     68: 
                     69: /* dagnode - allocate a dag with the given fields */
                     70: static struct dag *dagnode(op, l, r, sym) Node l, r; Symbol sym; {
                     71:        register struct dag *p = (struct dag *) talloc(sizeof *p);
                     72: 
                     73:        BZERO(p, struct dag);
                     74:        p->node.op = op;
                     75:        if (p->node.kids[0] = l)
                     76:                ++l->count;
                     77:        if (p->node.kids[1] = r)
                     78:                ++r->count;
                     79:        p->node.syms[0] = sym;
                     80:        return p;
                     81: }
                     82: 
                     83: /* emitcode - emit code for the current function */
                     84: void emitcode() {
                     85:        Code bp, cp;
                     86:        Coordinate save;
                     87: 
                     88:        save = src;
                     89:        for (bp = 0, cp = &codehead; errcnt <= 0 && cp; cp = cp->next)
                     90:                switch (cp->kind) {
                     91:                case Blockbeg:
                     92:                        cp->u.block.prev = bp;
                     93:                        bp = cp;
                     94:                        if (glevel && IR->stabblock) {
                     95:                                (*IR->stabblock)('{',  bp->u.block.level - LOCAL, bp->u.block.locals);
                     96:                                swtoseg(CODE);
                     97:                        }
                     98:                        break;
                     99:                case Blockend:
                    100:                        if (glevel && IR->stabblock) {
                    101:                                foreach(bp->u.block.identifiers, bp->u.block.level, typestab, (Generic)0);
                    102:                                foreach(bp->u.block.types,       bp->u.block.level, typestab, (Generic)0);
                    103:                                (*IR->stabblock)('}', bp->u.block.level - LOCAL, bp->u.block.locals);
                    104:                                swtoseg(CODE);
                    105:                        }
                    106:                        bp = bp->u.block.prev;
                    107:                        break;
                    108:                case Local:
                    109:                        if (glevel && IR->stabsym) {
                    110:                                (*IR->stabsym)(cp->u.var);
                    111:                                swtoseg(CODE);
                    112:                        }
                    113:                        break;
                    114:                case Defpoint:
                    115:                        src = cp->u.point.src;
                    116:                        if (glevel && IR->stabline) {
                    117:                                (*IR->stabline)(&cp->u.point.src);
                    118:                                swtoseg(CODE);
                    119:                        }
                    120:                        break;
                    121:                case Jump:
                    122:                        if (cp->u.node == 0)
                    123:                                break;
                    124:                        /* else fall thru */
                    125:                case Gen: case Label:
                    126:                        (*IR->emit)(cp->u.node);
                    127:                        break;
                    128:                case Switch: {
                    129:                        int i, k = cp->u.swtch.values[0];
                    130:                        for (i = 0; i < cp->u.swtch.size; i++) {
                    131:                                while (k++ < cp->u.swtch.values[i])
                    132:                                        (*IR->defaddress)(cp->u.swtch.deflab->u.l.equatedto);
                    133:                                (*IR->defaddress)(cp->u.swtch.labels[i]->u.l.equatedto);
                    134:                        }
                    135:                        break;
                    136:                        }
                    137:                }
                    138:        src = save;
                    139: }
                    140: 
                    141: /* fixup - re-aim equated labels to the true label */
                    142: static void fixup(p) Node p; {
                    143:        for ( ; p; p = p->link)
                    144:                switch (generic(p->op)) {
                    145:                case JUMP:
                    146:                        if (p->kids[0]->op == ADDRG+P)
                    147:                                p->kids[0]->syms[0] = p->kids[0]->syms[0]->u.l.equatedto;
                    148:                        break;
                    149:                case LABEL:
                    150:                case EQ: case GE: case GT: case LE: case LT: case NE:
                    151:                        assert(p->syms[0]);
                    152:                        p->syms[0] = p->syms[0]->u.l.equatedto;
                    153:                }
                    154: }
                    155: 
                    156: /* gencode - generate code for the current function */
                    157: void gencode(caller, callee) Symbol caller[], callee[]; {
                    158:        int i;
                    159:        Code bp, cp;
                    160:        Symbol p, q;
                    161:        Coordinate save;
                    162: 
                    163:        save = src;
                    164:        cp = codehead.next->next;
                    165:        codelist = codehead.next;
                    166:        for (i = 0; (p = callee[i]) && (q = caller[i]); i++)
                    167:                if (p->sclass != q->sclass || p->type != q->type) {
                    168:                        walk(asgn(p, idnode(q)), 0, 0);
                    169:                        if (glevel && IR->stabsym) {
                    170:                                (*IR->stabsym)(p);
                    171:                                (*IR->stabsym)(q);
                    172:                                swtoseg(CODE);
                    173:                        }
                    174:                } else if (glevel && IR->stabsym) {
                    175:                        (*IR->stabsym)(p);
                    176:                        swtoseg(CODE);
                    177:                }
                    178:        codelist->next = cp;
                    179:        cp->prev = codelist;
                    180:        for (bp = 0, cp = &codehead; errcnt <= 0 && cp; cp = cp->next)
                    181:                switch (cp->kind) {
                    182:                case Start: case Switch:
                    183:                        break;
                    184:                case Defpoint: 
                    185:                        src = cp->u.point.src;
                    186:                        break;
                    187:                case Blockbeg: {
                    188:                        Symbol *p = cp->u.block.locals;
                    189:                        cp->u.block.prev = bp;
                    190:                        bp = cp;
                    191:                        (*IR->blockbeg)(&bp->u.block.x);
                    192:                        for ( ; *p; p++)
                    193:                                if ((*p)->ref || glevel)
                    194:                                        (*IR->local)(*p);
                    195:                        break;
                    196:                        }
                    197:                case Blockend:
                    198:                        (*IR->blockend)(&bp->u.block.x);
                    199:                        bp = bp->u.block.prev;
                    200:                        break;
                    201:                case Local:
                    202:                        assert(cp->u.var->scope == bp->u.block.level);
                    203:                        (*IR->local)(cp->u.var);
                    204:                        break;
                    205:                case Address:
                    206:                        (*IR->address)(cp->u.addr.sym, cp->u.addr.base, cp->u.addr.offset);
                    207:                        break;
                    208:                case Jump:
                    209:                        if (cp->u.node == 0)
                    210:                                break;
                    211:                        /* else fall thru */
                    212:                case Gen: case Label:
                    213:                        fixup(cp->u.node);
                    214:                        if (IR->no_dag)
                    215:                                cp->u.node = undag(cp->u.node);
                    216:                        cp->u.node = (*IR->gen)(cp->u.node);
                    217:                        break;
                    218:                default:assert(0);
                    219:                }
                    220:        src = save;
                    221: }
                    222: 
                    223: /* haskid - does p appear as an operand in t? */
                    224: static int haskid(p, t) Node p, t; {
                    225:        if (t == 0)
                    226:                return 0;
                    227:        else if (p == t)
                    228:                return 1;
                    229:        else
                    230:                return haskid(p, t->kids[0]) || haskid(p, t->kids[1]); 
                    231: }
                    232: 
                    233: /* labelnode - list and return a LABEL node for label lab */
                    234: static Node labelnode(lab) {
                    235:        assert(lab);
                    236:        if (islabel(nodelist)) {
                    237:                equatelab(findlabel(lab), nodelist->syms[0]);
                    238:                return nodelist;
                    239:        }
                    240:        return list(newnode(LABEL+V, 0, 0, findlabel(lab)));
                    241: }
                    242: 
                    243: /* list - list node p unless it's already listed; return p */
                    244: static Node list(p) Node p; {
                    245:        if (p && p->link == 0) {
                    246:                if (nodelist) {
                    247:                        p->link = nodelist->link;
                    248:                        nodelist->link = p;
                    249:                } else
                    250:                        p->link = p;
                    251:                nodelist = p;
                    252: #ifdef DAGCHECK
                    253:                { extern void type_checker(Node); type_checker(p); }
                    254: #endif
                    255:        }
                    256:        return p;
                    257: }
                    258: 
                    259: /* listnodes - walk tree tp, building and listing dag nodes in execution order */
                    260: Node listnodes(tp, tlab, flab) Tree tp; {
                    261:        Opcode op;
                    262:        Node p, l, r;
                    263: 
                    264:        if (tp == 0)
                    265:                return 0;
                    266:        if (tp->node)
                    267:                return tp->node;
                    268:        op = generic(tp->op);
                    269:        switch (op) {
                    270:        case AND:
                    271:                if (flab) {
                    272:                        listnodes(tp->kids[0], 0, flab);
                    273:                        r = listnodes(tp->kids[1], 0, flab);
                    274:                } else {
                    275:                        listnodes(tp->kids[0], 0, flab = genlabel(1));
                    276:                        listnodes(tp->kids[1], tlab, 0);
                    277:                        r = labelnode(flab);
                    278:                }
                    279:                trash(0);
                    280:                return r;
                    281:        case NOT:
                    282:                return listnodes(tp->kids[0], flab, tlab);
                    283:        case OR:
                    284:                if (tlab) {
                    285:                        listnodes(tp->kids[0], tlab, 0);
                    286:                        r = listnodes(tp->kids[1], tlab, 0);
                    287:                } else {
                    288:                        listnodes(tp->kids[0], tlab = genlabel(1), 0);
                    289:                        listnodes(tp->kids[1], 0, flab);
                    290:                        r = labelnode(tlab);
                    291:                }
                    292:                trash(0);
                    293:                return r;
                    294:        case COND: {
                    295:                Tree q;
                    296:                assert(tlab == 0 && flab == 0);
                    297:                if (tp->u.sym)
                    298:                        addlocal(tp->u.sym);
                    299:                trash(0);
                    300:                listnodes(tp->kids[0], 0, flab = genlabel(2));
                    301:                trash(0);
                    302:                if (q = tp->kids[1]) {
                    303:                        assert(q->op == RIGHT);
                    304:                        listnodes(q->kids[0], 0, 0);
                    305:                        if (islabel(nodelist)) {
                    306:                                equatelab(nodelist->syms[0], findlabel(flab + 1));
                    307:                                remove(nodelist);
                    308:                        }
                    309:                        trash(0);
                    310:                }
                    311:                if (q && q->kids[1]) {
                    312:                        list(jump(flab + 1));
                    313:                        labelnode(flab);
                    314:                        listnodes(q->kids[1], 0, 0);
                    315:                        if (islabel(nodelist)) {
                    316:                                equatelab(nodelist->syms[0], findlabel(flab + 1));
                    317:                                remove(nodelist);
                    318:                        }
                    319:                } else
                    320:                        labelnode(flab);
                    321:                p = labelnode(flab + 1);
                    322:                trash(0);
                    323:                if (tp->u.sym) {
                    324:                        Tree t = idnode(tp->u.sym);
                    325:                        tp->u.sym->ref = 0;     /* undo idnode's setting ref */
                    326:                        p = listnodes(t, 0, 0);
                    327:                }
                    328:                break;
                    329:                }
                    330:        case CNST: {
                    331:                Type ty = unqual(tp->type);
                    332:                assert(op == CNST+S || ty->u.sym);
                    333:                if (op == CNST+S || ty->u.sym->addressed)
                    334:                        p = listnodes(cvtconst(tp), tlab, flab);
                    335:                else if (tlab == 0 && flab == 0)
                    336:                        p = node(tp->op, 0, 0, constant(ty, tp->u.v));
                    337:                else {
                    338:                        assert(ty == inttype);
                    339:                        if (tlab && tp->u.v.i != 0)
                    340:                                p = list(jump(tlab));
                    341:                        else if (flab && tp->u.v.i == 0)
                    342:                                p = list(jump(flab));
                    343:                        else
                    344:                                p = 0;
                    345:                }
                    346:                break;
                    347:                }
                    348:        case RIGHT:
                    349:                if (tp->kids[0] && generic(tp->kids[0]->op) == INDIR
                    350:                &&  tp->kids[1] && generic(tp->kids[1]->op) == ASGN
                    351:                &&  tp->kids[0]->kids[0] == tp->kids[1]->kids[0]) {     /* e++ */
                    352:                        p = listnodes(tp->kids[0], 0, 0);
                    353:                        if (nodelist) {
                    354:                                Node t;
                    355:                                for (t = nodelist; ; t = t->link)
                    356:                                        if (haskid(p, t->link)) {
                    357:                                                p->link = t->link;
                    358:                                                t->link = p;
                    359:                                                break;
                    360:                                        } else if (t->link == nodelist) {
                    361:                                                list(p);
                    362:                                                break;
                    363:                                        }
                    364:                        } else
                    365:                                list(p);
                    366:                        listnodes(tp->kids[1], 0, 0);
                    367:                } else if (tp->kids[1]) {
                    368:                        if (tp->kids[0] && generic(tp->kids[0]->op) == CNST)
                    369:                                tp->kids[0] = 0;
                    370:                        listnodes(tp->kids[0], 0, 0);
                    371:                        p = listnodes(tp->kids[1], tlab, flab);
                    372:                } else
                    373:                        p = listnodes(tp->kids[0], tlab, flab);
                    374:                break;
                    375:        case JUMP:
                    376:                assert(tlab == 0 && flab == 0);
                    377:                assert(tp->u.sym == 0);
                    378:                assert(tp->kids[0]);
                    379:                l = listnodes(tp->kids[0], 0, 0);
                    380:                p = newnode(JUMP+V, l, 0, 0);
                    381:                trash(0);
                    382:                list(p);
                    383:                break;
                    384:        case CALL:
                    385:                assert(tlab == 0 && flab == 0);
                    386:                l = listnodes(tp->kids[0], 0, 0);       /* arguments, function name */
                    387:                r = listnodes(tp->kids[1], 0, 0);
                    388:                p = newnode(tp->op, l, r, 0);
                    389:                p->syms[0] = (Symbol)talloc(sizeof *p->syms[0]);
                    390:                BZERO(p->syms[0], struct symbol);
                    391:                if (isptr(tp->kids[0]->type) && isfunc(tp->kids[0]->type->type))
                    392:                        p->syms[0]->type = tp->kids[0]->type->type;
                    393:                else
                    394:                        p->syms[0]->type = func(voidtype, 0, 1);
                    395:                trash(0);
                    396:                list(p);
                    397:                cfunc->u.f.ncalls++;
                    398:                break;
                    399:        case ARG:
                    400:                assert(tlab == 0 && flab == 0);
                    401:                if (IR->left_to_right)
                    402:                        listnodes(tp->kids[1], 0, 0);
                    403:                l = listnodes(tp->kids[0], 0, 0);
                    404:                p = newnode(tp->op, l, 0, 0);
                    405:                p->syms[0] = intconst(tp->type->size);
                    406:                p->syms[1] = intconst(tp->type->align);
                    407:                list(p);
                    408:                if (!IR->left_to_right)
                    409:                        listnodes(tp->kids[1], 0, 0);
                    410:                return 0;
                    411:        case EQ: case NE: case GT: case GE: case LE: case LT: {
                    412:                int lab;
                    413:                assert(tp->u.sym == 0);
                    414:                assert(errcnt || tlab || flab);
                    415:                if (lab = flab) {
                    416:                        assert(tlab == 0);
                    417:                        switch (op) {
                    418:                        case EQ: op = NE + optype(tp->op); break;
                    419:                        case NE: op = EQ + optype(tp->op); break;
                    420:                        case GT: op = LE + optype(tp->op); break;
                    421:                        case LT: op = GE + optype(tp->op); break;
                    422:                        case GE: op = LT + optype(tp->op); break;
                    423:                        case LE: op = GT + optype(tp->op); break;
                    424:                        }
                    425:                } else if (lab = tlab)
                    426:                        op = tp->op;
                    427:                l = listnodes(tp->kids[0], 0, 0);
                    428:                r = listnodes(tp->kids[1], 0, 0);
                    429:                p = newnode(op, l, r, findlabel(lab));
                    430:                p->syms[0]->ref++;
                    431:                list(p);
                    432:                break;
                    433:                }
                    434:        case ASGN:
                    435:                assert(tlab == 0 && flab == 0);
                    436:                if (tp->kids[0]->op == FIELD) {
                    437:                        Tree x = tp->kids[0]->kids[0];
                    438:                        Field p = tp->kids[0]->u.field;
                    439:                        assert(generic(x->op) == INDIR);
                    440:                        trash(0);
                    441:                        l = listnodes(lvalue(x), 0, 0);
                    442:                        if (fieldsize(p) < 8*p->type->size) {
                    443:                                unsigned int fmask = fieldmask(p);
                    444:                                unsigned int mask = fmask<<fieldright(p);
                    445:                                Tree q = tp->kids[1];
                    446:                                if (q->op == CNST+I && q->u.v.i == 0
                    447:                                ||  q->op == CNST+U && q->u.v.u == 0)
                    448:                                        q = bitnode(BAND, x, constnode(~mask, unsignedtype));
                    449:                                else if (q->op == CNST+I && (q->u.v.i&fmask) == fmask
                    450:                                ||       q->op == CNST+U && (q->u.v.u&fmask) == fmask)
                    451:                                        q = bitnode(BOR, x, constnode(mask, unsignedtype));
                    452:                                else
                    453:                                        q = bitnode(BOR,
                    454:                                                bitnode(BAND, x, constnode(~mask, unsignedtype)),
                    455:                                                bitnode(BAND, shnode(LSH, cast(q, unsignedtype),
                    456:                                                        constnode(fieldright(p), inttype)),
                    457:                                                        constnode(mask, unsignedtype)));
                    458:                                r = listnodes(q, 0, 0);
                    459:                        } else
                    460:                                r = listnodes(tp->kids[1], 0, 0);
                    461:                } else {
                    462:                        l = listnodes(tp->kids[0], 0, 0);
                    463:                        r = listnodes(tp->kids[1], 0, 0);
                    464:                }
                    465:                trash(isaddrop(tp->kids[0]->op) && !tp->kids[0]->u.sym->computed ? l : 0);
                    466:                p = newnode(tp->op, l, r, 0);
                    467:                p->syms[0] = intconst(tp->kids[1]->type->size);
                    468:                p->syms[1] = intconst(tp->kids[1]->type->align);
                    469:                list(p);
                    470:                p = listnodes(tp->kids[1], 0, 0);
                    471:                break;
                    472:        case BAND:
                    473:                assert(tlab == 0 && flab == 0);
                    474:                l = listnodes(tp->kids[0], 0, 0);
                    475:                if (IR->compl_band)
                    476:                        r = listnodes(cast(
                    477:                                simplify(BCOM+U, unsignedtype,
                    478:                                        cast(tp->kids[1], unsignedtype), 0),
                    479:                                tp->kids[1]->type), 0, 0);
                    480:                else
                    481:                        r = listnodes(tp->kids[1], 0, 0);
                    482:                p = node(tp->op, l, r, 0);
                    483:                break;
                    484:        case RSH:
                    485:                assert(tlab == 0 && flab == 0);
                    486:                l = listnodes(tp->kids[0], 0, 0);
                    487:                if (IR->compl_band && tp->op == RSH+I)
                    488:                        r = listnodes(simplify(NEG+I, inttype, tp->kids[1], 0), 0, 0);
                    489:                else
                    490:                        r = listnodes(tp->kids[1], 0, 0);
                    491:                p = node(tp->op, l, r, 0);
                    492:                break;
                    493:        case ADD: case SUB:  case DIV: case MUL: case MOD:
                    494:        case BOR: case BXOR: case LSH:
                    495:                assert(tlab == 0 && flab == 0);
                    496:                l = listnodes(tp->kids[0], 0, 0);
                    497:                r = listnodes(tp->kids[1], 0, 0);
                    498:                p = node(tp->op, l, r, 0);
                    499:                if (IR->mulops_are_calls &&
                    500:                   (p->op == DIV+I || p->op == MOD+I || p->op == MUL+I
                    501:                ||  p->op == DIV+U || p->op == MOD+U || p->op == MUL+U))
                    502:                        list(p);
                    503:                break;
                    504:        case RET:
                    505:                assert(tlab == 0 && flab == 0);
                    506:                l = listnodes(tp->kids[0], 0, 0);
                    507:                p = newnode(tp->op, l, 0, 0);
                    508:                list(p);
                    509:                break;
                    510:        case CVC: case CVD: case CVF: case CVI:
                    511:        case CVP: case CVS: case CVU: case NEG: case BCOM:
                    512:                assert(tlab == 0 && flab == 0);
                    513:                l = listnodes(tp->kids[0], 0, 0);
                    514:                p = node(tp->op, l, 0, 0);
                    515:                break;
                    516:        case INDIR: {
                    517:                Type ty = tp->kids[0]->type;
                    518:                if (isptr(ty))
                    519:                        ty = unqual(ty)->type;
                    520:                assert(tlab == 0 && flab == 0);
                    521:                l = listnodes(tp->kids[0], 0, 0);
                    522:                if (isvolatile(ty) || (isstruct(ty) && unqual(ty)->u.sym->u.s.vfields))
                    523:                        p = newnode(tp->op, l, 0, 0);
                    524:                else
                    525:                        p = node(tp->op, l, 0, 0);
                    526:                break;
                    527:                }
                    528:        case FIELD: {
                    529:                Tree q;
                    530:                assert(tlab == 0 && flab == 0);
                    531:                q = shnode(RSH,
                    532:                        shnode(LSH, tp->kids[0],
                    533:                                constnode(fieldleft(tp->u.field), inttype)),
                    534:                        constnode(8*tp->type->size - fieldsize(tp->u.field), inttype));
                    535:                p = listnodes(q, 0, 0);
                    536:                break;
                    537:                }
                    538:        case ADDRL:
                    539:                assert(tlab == 0 && flab == 0);
                    540:                if (tp->u.sym->temporary) {
                    541:                        addlocal(tp->u.sym);
                    542:                        release(tp->u.sym);
                    543:                }
                    544:                p = node(tp->op, 0, 0, tp->u.sym);
                    545:                break;
                    546:        case ADDRG: case ADDRF:
                    547:                assert(tlab == 0 && flab == 0);
                    548:                if (tp->u.sym->scope == LABELS)
                    549:                        tp->u.sym->ref++;
                    550:                p = node(tp->op, 0, 0, tp->u.sym);
                    551:                break;
                    552:        default:assert(0);
                    553:        }
                    554:        return tp->node = p;
                    555: }
                    556: 
                    557: /* jump - return tree for a jump to lab */
                    558: Node jump(lab) {
                    559:        Symbol p = findlabel(lab);
                    560: 
                    561:        p->ref++;
                    562:        return newnode(JUMP+V, node(ADDRG+P, 0, 0, p), 0, 0);
                    563: }
                    564: 
                    565: /* newnode - allocate a node with the given fields */
                    566: Node newnode(op, l, r, sym) Node l, r; Symbol sym; {
                    567:        return &dagnode(op, l, r, sym)->node;
                    568: }
                    569: 
                    570: /* node - search for a node with the given fields, or allocate it */
                    571: Node node(op, l, r, sym) Node l, r; Symbol sym; {
                    572:        int i = (opindex(op)^((unsigned)sym>>2))&(NBUCKETS-1);
                    573:        register struct dag *p;
                    574: 
                    575:        for (p = buckets[i]; p; p = p->hlink)
                    576:                if (p->node.op == op && p->node.syms[0] == sym
                    577:                && p->node.kids[0] == l && p->node.kids[1] == r)
                    578:                        return &p->node;
                    579:        p = dagnode(op, l, r, sym);
                    580:        p->hlink = buckets[i];
                    581:        buckets[i] = p;
                    582:        ++nodecount;
                    583:        return &p->node;
                    584: }
                    585: 
                    586: dclproto(static void printdag1,(Node, int, int));
                    587: dclproto(static void printnode,(Node, int, int));
                    588: 
                    589: /* printdag - print dag p on fd, or the node list if p == 0 */
                    590: void printdag(p, fd) Node p; {
                    591:        printed(0);
                    592:        if (p == 0) {
                    593:                if (p = nodelist)
                    594:                        do {
                    595:                                p = p->link;
                    596:                                printdag1(p, fd, 0);
                    597:                        } while (p != nodelist);
                    598:        } else if (*printed(nodeid((Tree)p)))
                    599:                fprint(fd, "node'%d printed above\n", nodeid((Tree)p));
                    600:        else
                    601:                printdag1(p, fd, 0);
                    602: }
                    603: 
                    604: /* printdag1 - recursively print dag p */
                    605: static void printdag1(p, fd, lev) Node p; {
                    606:        int id, i;
                    607: 
                    608:        if (p == 0 || *printed(id = nodeid((Tree)p)))
                    609:                return;
                    610:        *printed(id) = 1;
                    611:        for (i = 0; i < MAXKIDS; i++)
                    612:                printdag1(p->kids[i], fd, lev + 1);
                    613:        printnode(p, fd, lev);
                    614: }
                    615: 
                    616: /* printnode - print fields of dag p */
                    617: static void printnode(p, fd, lev) Node p; {
                    618:        if (p) {
                    619:                int i, id = nodeid((Tree)p);
                    620:                fprint(fd, "%c%d%s", lev == 0 ? '\'' : '#', id,
                    621:                        &"   "[id < 10 ? 0 : id < 100 ? 1 : 2]);
                    622:                fprint(fd, "%s count=%d", opname(p->op), p->count);
                    623:                for (i = 0; i < MAXKIDS && p->kids[i]; i++)
                    624:                        fprint(fd, " #%d", nodeid((Tree)p->kids[i]));
                    625:                for (i = 0; i < MAXSYMS && p->syms[i]; i++)
                    626:                        fprint(fd, " %s", p->syms[i]->name);
                    627:                fprint(fd, "\n");
                    628:        }
                    629: }
                    630: 
                    631: /* remove - remove node p from the node list */
                    632: static void remove(p) Node p; {
                    633:        if (nodelist) {
                    634:                Node q = nodelist;
                    635:                for ( ; q->link != p && q->link != nodelist; q = q->link)
                    636:                        ;
                    637:                assert(q->link == p);
                    638:                q->link = p->link;
                    639:                if (p == nodelist)
                    640:                        nodelist = q;
                    641:        }
                    642: }
                    643: 
                    644: /* reset - clear the dag */
                    645: static void reset() {
                    646:        BZERO(buckets, struct dag *[NBUCKETS]);
                    647:        nodecount = 0;
                    648: }
                    649: 
                    650: /* trash - preclude future links to rvalue of p or all values */
                    651: static void trash(p) Node p; {
                    652:        if (p) {
                    653:                register int i;
                    654:                register struct dag *q, **r;
                    655:                for (i = 0; i < NBUCKETS; i++)
                    656:                        for (r = &buckets[i]; q = *r; )
                    657:                                if (generic(q->node.op) == INDIR && (!isaddrop(q->node.kids[0]->op)
                    658:                                || q->node.kids[0]->syms[0] == p->syms[0])) {
                    659:                                        *r = q->hlink;
                    660:                                        --nodecount;
                    661:                                } else
                    662:                                        r = &q->hlink;
                    663:        } else if (nodecount > 0)
                    664:                reset();
                    665: }
                    666: 
                    667: /* typestab - emit stab entries for p */
                    668: static void typestab(p, cl) Symbol p; Generic cl; {
                    669:        if (!isfunc(p->type) && (p->sclass == EXTERN || p->sclass == STATIC) && IR->stabsym)
                    670:                (*IR->stabsym)(p);
                    671:        else if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype)
                    672:                (*IR->stabtype)(p);
                    673: }
                    674: 
                    675: #define iscall(p) (generic((p)->op) == CALL || IR->mulops_are_calls \
                    676:        && ((p)->op == DIV+I || (p)->op == MOD+I || (p)->op == MUL+I \
                    677:        ||  (p)->op == DIV+U || (p)->op == MOD+U || (p)->op == MUL+U))
                    678: 
                    679: /* undag - replace multiply-referenced nodes in nodelist by temporaries, return new nodelist */
                    680: static Node undag(nodelist) Node nodelist; {
                    681:        Node p, pred;
                    682:        struct node head;
                    683: 
                    684:        head.link = nodelist;
                    685:        for (pred = &head; p = pred->link; ) {
                    686:                /*
                    687:                 * succ is p's successor,
                    688:                 * pred is p's predecessor, and
                    689:                 * p->link == pred;
                    690:                 * undag1(x, p) adds predecessors and maintains p->link == p->link->link.
                    691:                 */
                    692:                Node succ = p->link;
                    693:                p->link = pred;
                    694:                if (generic(p->op) == INDIR) {
                    695:                        assert(p->count >= 1);
                    696:                        undag1(p, p);
                    697:                        /*
                    698:                         * remove p from the node list,
                    699:                         * setting pred to the last node inserted (if any).
                    700:                         */
                    701:                        pred = p->link;
                    702:                        pred->link = succ;
                    703:                        p->link = 0;
                    704:                } else if (iscall(p) && p->count >= 1) {
                    705:                        Node q;
                    706:                        undag1(p, p);
                    707:                        /*
                    708:                         * p->link is p's predecessor,
                    709:                         * which is the ASGN of p to a temporary.
                    710:                         */
                    711:                        assert(p->link && generic(p->link->op) == ASGN && p->link->kids[1] == p);
                    712:                        /*
                    713:                         * remove p from the node list,
                    714:                         * setting pred to the ASGN node.
                    715:                         */
                    716:                        pred = p->link;
                    717:                        pred->link = succ;
                    718:                        /*
                    719:                         * re-insert p into the node list
                    720:                         * immediately before its predecessor;
                    721:                         * this places the CALL node before the ASGN node.
                    722:                         * / 
                    723:                        for (q = &head; q && q->link != pred; q = q->link)
                    724:                                ;
                    725:                        assert(q);
                    726:                        q->link = p;
                    727:                        p->link = pred; */
                    728:                        p->link = 0;
                    729:                } else {
                    730:                        assert(p->count == 0);
                    731:                        undag1(p, p);
                    732:                        /*
                    733:                         * reestablish p's successor, and
                    734:                         * advance pred so that pred->link == succ
                    735:                         */
                    736:                        p->link = succ;
                    737:                        pred = p;
                    738:                }
                    739:        }
                    740:        rmtemps(0, LOCAL);
                    741:        return head.link;
                    742: }
                    743: 
                    744: /* undag1 - return a reference to the temporary holding value of p, or p */
                    745: static Node undag1(p, root) Node p, root; {
                    746:        Node e;
                    747: 
                    748:        if (p == 0)
                    749:                ;
                    750:        else if (p->syms[2]) {
                    751:                e = newnode(INDIR + (isunsigned(p->syms[2]->type) ? I : ttob(p->syms[2]->type)),
                    752:                        newnode(ADDRL+P, 0, 0, p->syms[2]), 0, 0);
                    753:                e->count = 1;
                    754:                if (--p->count == 1) {
                    755:                        /* fprint(2, "releasing %s from ", p->syms[2]->name); printnode(p, 2, 1);
                    756:                        release(p->syms[2]); */
                    757:                        p->syms[2] = 0;
                    758:                }
                    759:                p = e;
                    760:        } else if (p->count <= 1 && !iscall(p)
                    761:        ||         p->count == 0 &&  iscall(p)) {
                    762:                p->kids[0] = undag1(p->kids[0], root);
                    763:                p->kids[1] = undag1(p->kids[1], root);
                    764:        } else if (p->op == ADDRL+P || p->op == ADDRF+P) {
                    765:                assert(p != root);
                    766:                p = newnode(p->op, 0, 0, p->syms[0]);
                    767:                p->count = 1;
                    768:        } else if (generic(p->op) == INDIR
                    769:        && (p->kids[0]->op == ADDRL+P || p->kids[0]->op == ADDRF+P)
                    770:        && p->kids[0]->syms[0]->sclass == REGISTER && p != root) {
                    771:                p = newnode(p->op, 
                    772:                        newnode(p->kids[0]->op, 0, 0, p->kids[0]->syms[0]), 0, 0);
                    773:                p->count = 1;
                    774:        } else if (p->op == INDIR+B) {
                    775:                --p->count;
                    776:                p = newnode(p->op, p->kids[0], 0, 0);
                    777:                p->count = 1;
                    778:                p->kids[0] = undag1(p->kids[0], root);
                    779:        } else {
                    780:                p->syms[2] = temporary(REGISTER, btot(p->op));
                    781:                /* fprint(2, "allocating %s to ", p->syms[2]->name); printnode(p, 2, 1); */
                    782:                if (!p->syms[2]->defined) {
                    783:                        p->syms[2]->scope = LOCAL;
                    784:                        p->syms[2]->ref = 1;
                    785:                        (*IR->local)(p->syms[2]);
                    786:                        p->syms[2]->defined = 1;
                    787:                }
                    788:                p->kids[0] = undag1(p->kids[0], root);
                    789:                p->kids[1] = undag1(p->kids[1], root);
                    790:                e = newnode(ASGN + (isunsigned(p->syms[2]->type) ? I : ttob(p->syms[2]->type)),
                    791:                        newnode(ADDRL+P, 0, 0, p->syms[2]), p, 0);
                    792:                e->syms[0] = intconst(p->syms[2]->type->size);
                    793:                e->syms[1] = intconst(p->syms[2]->type->align);
                    794:                /*
                    795:                 * root->link is the root's predecessor;
                    796:                 * point the root's predecessor to the ASGN,
                    797:                 * make the ASGN the root's new predecessor,
                    798:                 * and make root the ASGN's successor.
                    799:                 */
                    800:                root->link = root->link->link = e;
                    801:                e->link = root;
                    802:                if (p != root)
                    803:                        p = undag1(p, root);    /* returns reference to the temporary */
                    804:        }
                    805:        return p;
                    806: }
                    807: 
                    808: /* walk - list tree tp, generate code for current node list, reset node list */
                    809: void walk(tp, tlab, flab) Tree tp; {
                    810:        listnodes(tp, tlab, flab);
                    811:        if (nodelist) {
                    812:                trash(0);
                    813:                code(Gen);
                    814:                codelist->u.node = nodelist->link;
                    815:                nodelist->link = 0;
                    816:                nodelist = 0;
                    817:                rmtemps(REGISTER, 0);
                    818:        }
                    819:        reset();
                    820:        ntree = 0;
                    821: }

unix.superglobalmegacorp.com

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