Annotation of researchv10no/cmd/lcc/c/enode.c, revision 1.1

1.1     ! root        1: /* C compiler: type-checking and tree construction for expressions */
        !             2: 
        !             3: #include "c.h"
        !             4: 
        !             5: dclproto(static Tree addnode,(int, Tree, Tree));
        !             6: dclproto(static Tree andnode,(int, Tree, Tree));
        !             7: dclproto(static Type binary,(Type, Type));
        !             8: dclproto(static Tree cmpnode,(int, Tree, Tree));
        !             9: dclproto(static int compatible,(Type, Type));
        !            10: dclproto(static Tree mulnode,(int, Tree, Tree));
        !            11: dclproto(static Tree subnode,(int, Tree, Tree));
        !            12: 
        !            13: dclproto(Tree (*opnode[]),(int, Tree, Tree)) = {
        !            14: #define xx(a,b,c,d,e,f,g) e,
        !            15: #include "token.h"
        !            16: };
        !            17: 
        !            18: /* addnode - construct tree for l + r */
        !            19: static Tree addnode(op, l, r) Tree l, r; {
        !            20:        int n;
        !            21:        Type ty = inttype;
        !            22: 
        !            23:        if (isarith(l->type) && isarith(r->type)) {
        !            24:                ty = binary(l->type, r->type);
        !            25:                l = cast(l, ty);
        !            26:                r = cast(r, ty);
        !            27:        } else if (isptr(l->type) && isint(r->type))
        !            28:                return addnode(ADD, r, l);
        !            29:        else if (isptr(r->type) && isint(l->type)) {
        !            30:                ty = unqual(r->type);
        !            31:                if ((n = ty->type->size) == 0)
        !            32:                        error("unknown size of type `%t'\n", ty->type);
        !            33:                l = cast(l, promote(l->type));
        !            34:                if (n > 1)
        !            35:                        l = mulnode(MUL, constnode(n, inttype), l);
        !            36:                return simplify(ADD+P, ty, l, r);
        !            37:        } else
        !            38:                typeerror(op, l, r);
        !            39:        return simplify(op, ty, l, r);
        !            40: }
        !            41: 
        !            42: /* andnode - construct tree for l [&& ||] r */
        !            43: static Tree andnode(op, l, r) Tree l, r; {
        !            44:        if (!isscalar(l->type) || !isscalar(r->type))
        !            45:                typeerror(op, l, r);
        !            46:        return simplify(op, inttype, cond(l), cond(r));
        !            47: }
        !            48: 
        !            49: /* asgnnode - construct tree for l = r */
        !            50: Tree asgnnode(op, l, r) Tree l, r; {
        !            51:        Type aty, ty;
        !            52: 
        !            53:        r = pointer(r);
        !            54:        if ((ty = assign(l->type, r)) == 0) {
        !            55:                typeerror(ASGN, l, r);
        !            56:                if (r->type == voidtype)
        !            57:                        r = retype(r, inttype);
        !            58:                ty = r->type;
        !            59:        }
        !            60:        if (l->op != FIELD)
        !            61:                l = lvalue(l);
        !            62:        aty = l->type;
        !            63:        if (isptr(aty))
        !            64:                aty = unqual(aty)->type;
        !            65:        if (isconst(aty) || (isstruct(aty) && unqual(aty)->u.sym->u.s.cfields))
        !            66:                if (isaddrop(l->op) && !l->u.sym->computed && !l->u.sym->generated)
        !            67:                        error("assignment to const identifier `%s'\n", l->u.sym->name);
        !            68:                else
        !            69:                        error("assignment to const location\n");
        !            70:        r = cast(r, ty);
        !            71:        if (l->op == FIELD && fieldsize(l->u.field) < 8*l->u.field->type->size)
        !            72:                if (isunsigned(l->u.field->type))
        !            73:                        r = bitnode(BAND, r,
        !            74:                                constnode(fieldmask(l->u.field), unsignedtype));
        !            75:                else {
        !            76:                        int n = 8*l->u.field->type->size - fieldsize(l->u.field);
        !            77:                        /*
        !            78:                         * The value of assignment is the value of the left
        !            79:                         * operand (sec. 3.3.16), which for bit fields is the
        !            80:                         * same as extracting the field. When r is a constant,
        !            81:                         * the explicit left shift below avoids overflow that
        !            82:                         * would occur if shnode(LSH, ...) were used. The
        !            83:                         * subsequent shnode(RSH, ...) will be signed and thus
        !            84:                         * extend the sign bit correctly.
        !            85:                         */
        !            86:                        if (r->op == CNST+I)
        !            87:                                r = constnode(r->u.v.i<<n, inttype);
        !            88:                        else
        !            89:                                r = shnode(LSH, r, constnode(n, inttype));
        !            90:                        r = shnode(RSH, r, constnode(n, inttype));
        !            91:                }
        !            92:        if (isstruct(ty)) {
        !            93:                if (r->op == RIGHT && r->kids[0] && r->kids[0]->op == CALL+B
        !            94:                && isaddrop(l->op)) {
        !            95:                        /*
        !            96:                         * When x=f() where f returns a struct and x is a simple
        !            97:                         * address, release the temporary generated to hold f's
        !            98:                         * return value and use x in its place. The RIGHT tree
        !            99:                         * assigned to r below returns x's address, and
        !           100:                         * rvalue(r) hangs that tree under an INDIR+B,
        !           101:                         * thus identifying the result as an lvalue.
        !           102:                         */
        !           103:                        r = r->kids[0]; /* CALL+B node */
        !           104:                        release(r->kids[1]->u.sym);
        !           105:                        r = tree(RIGHT, l->type,
        !           106:                                tree(CALL+B, r->kids[0]->type, r->kids[0], l),
        !           107:                                retype(isarray(l->u.sym->type) ? idnode(l->u.sym) : addrof(idnode(l->u.sym)), l->type));
        !           108:                        return rvalue(r);
        !           109:                }
        !           110:                return tree(ASGN+B, ty, l, r);
        !           111:        }
        !           112:        return tree(op + (isunsigned(ty) ? I : ttob(ty)), ty, l, r);
        !           113: }
        !           114: 
        !           115: /* binary - usual arithmetic conversions, return target type */
        !           116: static Type binary(xty, yty) Type xty, yty; {
        !           117:        if (isdouble(xty) || isdouble(yty))
        !           118:                return doubletype;
        !           119:        if (xty == floattype || yty == floattype)
        !           120:                return floattype;
        !           121:        if (isunsigned(xty) || isunsigned(yty))
        !           122:                return unsignedtype;
        !           123:        return inttype;
        !           124: }
        !           125: 
        !           126: /* bitnode - construct tree for l [& | ^ %] r */
        !           127: Tree bitnode(op, l, r) Tree l, r; {
        !           128:        Type ty = inttype;
        !           129: 
        !           130:        if (isint(l->type) && isint(r->type)) {
        !           131:                ty = binary(l->type, r->type);
        !           132:                l = cast(l, ty);
        !           133:                r = cast(r, ty);
        !           134:                if (op != MOD) {
        !           135:                        l = cast(l, unsignedtype);
        !           136:                        r = cast(r, unsignedtype);
        !           137:                }
        !           138:        } else
        !           139:                typeerror(op, l, r);
        !           140:        if (op == MOD)
        !           141:                return simplify(op, ty, l, r);
        !           142:        return cast(simplify(op, unsignedtype, l, r), ty);
        !           143: }
        !           144: 
        !           145: /* callnode - construct call node to f, return type ty, arguments args */
        !           146: Tree callnode(f, ty, args) Tree f, args; Type ty; {
        !           147:        Tree p;
        !           148: 
        !           149:        if (args)
        !           150:                f = tree(RIGHT, f->type, args, f);
        !           151:        if (isstruct(ty)) {
        !           152:                Symbol t1 = temporary(AUTO, unqual(ty));
        !           153:                if (ty->size == 0)
        !           154:                        error("illegal use of incomplete type `%t'\n", ty);
        !           155:                p = tree(RIGHT, ty, tree(CALL+B, ty, f, lvalue(idnode(t1))),
        !           156:                        idnode(t1));
        !           157:        } else {
        !           158:                Type rty = ty;
        !           159:                if (isenum(ty))
        !           160:                        rty = unqual(ty)->type;
        !           161:                else if (isptr(ty))
        !           162:                        rty = unsignedtype;
        !           163:                p = tree(CALL + widen(rty), rty, f, 0);
        !           164:                if (isptr(ty))
        !           165:                        p = cast(p, ty);
        !           166:        }
        !           167:        return p;
        !           168: }
        !           169: 
        !           170: /* cmpnode - construct tree for l [< <= >= >] r */
        !           171: static Tree cmpnode(op, l, r) Tree l, r; {
        !           172:        Type ty = unsignedtype;
        !           173: 
        !           174:        if (isarith(l->type) && isarith(r->type)) {
        !           175:                ty = binary(l->type, r->type);
        !           176:                l = cast(l, ty);
        !           177:                r = cast(r, ty);
        !           178:        } else if (compatible(l->type, r->type)) {
        !           179:                l = cast(l, ty);
        !           180:                r = cast(r, ty);
        !           181:        } else
        !           182:                typeerror(op, l, r);
        !           183:        return simplify(op + ttob(ty), inttype, l, r);
        !           184: }
        !           185: 
        !           186: /* compatible - are ty1 & ty2 sans qualifiers pointers to compatible object or incomplete types? */
        !           187: static int compatible(ty1, ty2) Type ty1, ty2; {
        !           188:        if (isptr(ty1) && !isfunc(ty1->type) && isptr(ty2) && !isfunc(ty2->type)) {
        !           189:                do {
        !           190:                        ty1 = unqual(ty1->type);
        !           191:                        ty2 = unqual(ty2->type);
        !           192:                } while (isptr(ty1) && isptr(ty2));
        !           193:                return eqtype(ty1, ty2, 0);
        !           194:        }
        !           195:        return 0;
        !           196: }
        !           197: 
        !           198: /* condnode - build a tree for e ? l : r */
        !           199: Tree condnode(e, l, r) Tree e, l, r; {
        !           200:        Symbol t1 = 0;
        !           201:        Type ty = 0, lty = l->type, rty = r->type;
        !           202:        Tree p;
        !           203:        
        !           204:        if (isarith(lty) && isarith(rty)) {
        !           205:                ty = binary(lty, rty);
        !           206:                l = cast(l, ty);
        !           207:                r = cast(r, ty);
        !           208:        } else if (eqtype(lty, rty, 1)
        !           209:        || isptr(lty) && isint(rty) && assign(lty, r))
        !           210:                ty = unqual(lty);
        !           211:        else if (isptr(rty) && isint(lty) && assign(rty, l))
        !           212:                ty = unqual(rty);
        !           213:        else if (isptr(lty) && isptr(rty)) {
        !           214:                lty = lty->type;
        !           215:                rty = rty->type;
        !           216:                if (unqual(lty) == voidtype || unqual(rty) == voidtype)
        !           217:                        ty = voidtype;
        !           218:                else if (eqtype(unqual(lty), unqual(rty), 1))
        !           219:                        ty = unqual(lty);
        !           220:                if (ty) {
        !           221:                        if (isconst(lty) || isconst(rty))
        !           222:                                ty = qual(CONST, ty);
        !           223:                        if (isvolatile(lty) || isvolatile(rty))
        !           224:                                ty = qual(VOLATILE, ty);
        !           225:                        ty = ptr(ty);
        !           226:                }
        !           227:        }
        !           228:        if (ty == 0) {
        !           229:                typeerror(COND, l, r);
        !           230:                ty = inttype;
        !           231:        } else if (e->op == CNST+D || e->op == CNST+F) {
        !           232:                e = cast(e, doubletype);
        !           233:                return retype(e->u.v.d != 0.0 ? l : r, ty);
        !           234:        } else if (generic(e->op) == CNST) {
        !           235:                e = cast(e, unsignedtype);
        !           236:                return retype(e->u.v.u ? l : r, ty);
        !           237:        } else if (ty != voidtype && ty->size > 0) {
        !           238:                Opcode op = generic(e->op);
        !           239:                t1 = temporary(REGISTER, ty);
        !           240:                l = root(asgn(t1, l));
        !           241:                if (op != AND && op != OR && op != NOT && op != EQ && op != NE
        !           242:                &&  op !=  LE && op != LT && op !=  GE && op != GT && op != RIGHT
        !           243:                && r->op == CNST+I && r->u.v.i == 0
        !           244:                && assign(e->type, r)) {
        !           245:                        /* e1?e2:0 => ((t1=e1,t1)?(t1=e2): ) */
        !           246:                        e = tree(RIGHT, ty, asgn(t1, cast(e, ty)), idnode(t1));
        !           247:                        r = 0;
        !           248:                } else
        !           249:                        r = root(asgn(t1, r));
        !           250:        }
        !           251:        p = tree(COND, ty, cond(e), tree(RIGHT, ty, l, r));
        !           252:        p->u.sym = t1;
        !           253:        return p;
        !           254: }
        !           255: 
        !           256: /* constnode - return a tree for a constant n of type ty (int or unsigned) */
        !           257: Tree constnode(n, ty) unsigned n; Type ty; {
        !           258:        Tree p;
        !           259: 
        !           260:        if (isarray(ty))
        !           261:                p = tree(CNST+P, atop(ty), 0, 0);
        !           262:        else
        !           263:                p = tree(CNST + ttob(ty), ty, 0, 0);
        !           264:        p->u.v.u = n;
        !           265:        return p;
        !           266: }
        !           267: 
        !           268: /* eqnode - construct tree for l [== !=] r */
        !           269: Tree eqnode(op, l, r) Tree l, r; {
        !           270:        if (isint(l->type) && isptr(r->type))
        !           271:                return eqnode(op, r, l);
        !           272:        if (isptr(l->type) && isint(r->type)) {
        !           273:                l = cast(l, unsignedtype);
        !           274:                r = cast(r, unsignedtype);
        !           275:                if (r->op != CNST+U || r->u.v.u)
        !           276:                        error("operands of %s have incompatible types\n",
        !           277:                                op == EQ ? "==" : "!=");
        !           278:                return simplify(op + U, inttype, l, r);
        !           279:        }
        !           280:        if (isptr(l->type) && isptr(r->type) && eqtype(unqual(l->type), unqual(r->type), 1)
        !           281:        ||  isptr(l->type) && !isfunc(l->type->type)
        !           282:        && (isptr(r->type) &&  unqual(r->type->type) == voidtype)
        !           283:        ||  isptr(r->type) && !isfunc(r->type->type)
        !           284:        && (isptr(l->type) &&  unqual(l->type->type) == voidtype)) {
        !           285:                l = cast(l, unsignedtype);
        !           286:                r = cast(r, unsignedtype);
        !           287:                return simplify(op + U, inttype, l, r);
        !           288:        }
        !           289:        return cmpnode(op, l, r);
        !           290: }
        !           291: 
        !           292: /* mulnode - construct tree for l [* /] r */
        !           293: static Tree mulnode(op, l, r) Tree l, r; {
        !           294:        Type ty = inttype;
        !           295: 
        !           296:        if (isarith(l->type) && isarith(r->type)) {
        !           297:                ty = binary(l->type, r->type);
        !           298:                l = cast(l, ty);
        !           299:                r = cast(r, ty);
        !           300:        } else
        !           301:                typeerror(op, l, r);
        !           302:        return simplify(op, ty, l, r);
        !           303: }
        !           304: 
        !           305: /* shnode - construct tree for l [>> <<] r */
        !           306: Tree shnode(op, l, r) Tree l, r; {
        !           307:        Type ty = inttype;
        !           308: 
        !           309:        if (isint(l->type) && isint(r->type)) {
        !           310:                ty = promote(l->type);
        !           311:                l = cast(l, ty);
        !           312:                r = cast(r, inttype);
        !           313:        } else
        !           314:                typeerror(op, l, r);
        !           315:        return simplify(op, ty, l, r);
        !           316: }
        !           317: 
        !           318: /* subnode - construct tree for l - r */
        !           319: static Tree subnode(op, l, r) Tree l, r; {
        !           320:        int n;
        !           321:        Type ty = inttype;
        !           322: 
        !           323:        if (isarith(l->type) && isarith(r->type)) {
        !           324:                ty = binary(l->type, r->type);
        !           325:                l = cast(l, ty);
        !           326:                r = cast(r, ty);
        !           327:        } else if (isptr(l->type) && !isfunc(l->type->type) && isint(r->type)) {
        !           328:                ty = unqual(l->type);
        !           329:                if ((n = ty->type->size) == 0)
        !           330:                        error("unknown size of type `%t'\n", ty->type);
        !           331:                r = cast(r, promote(r->type));
        !           332:                if (n > 1)
        !           333:                        r = mulnode(MUL, constnode(n, inttype), r);
        !           334:                return simplify(SUB+P, ty, l, r);
        !           335:        } else if (compatible(l->type, r->type)) {
        !           336:                if ((n = deref(l->type)->size) == 0)
        !           337:                        error("unknown size of type `%t'\n", deref(l->type));
        !           338:                l = simplify(SUB+U, unsignedtype, cast(l, unsignedtype),
        !           339:                        cast(r, unsignedtype));
        !           340:                return simplify(DIV+I, inttype, cast(l, inttype), constnode(n, inttype));
        !           341:        } else
        !           342:                typeerror(op, l, r);
        !           343:        return simplify(op, ty, l, r);
        !           344: }
        !           345: 
        !           346: /* typeerror - issue "operands of op have illegal types `l' and `r'" */
        !           347: void typeerror(op, l, r) Tree l, r; {
        !           348:        int i;
        !           349:        static struct { Opcode op; char *name; } ops[] = {
        !           350:                ASGN, "=",      INDIR, "*",     NEG,  "-",
        !           351:                ADD,  "+",      SUB,   "-",     LSH,  "<<",
        !           352:                MOD,  "%",      RSH,   ">>",    BAND, "&",
        !           353:                BCOM, "~",      BOR,   "|",     BXOR, "^",
        !           354:                DIV,  "/",      MUL,   "*",     EQ,   "==",
        !           355:                GE,   ">=",     GT,    ">",     LE,   "<=",
        !           356:                LT,   "<",      NE,    "!=",    AND,  "&&",
        !           357:                NOT,  "!",      OR,    "||",    COND, "?:",
        !           358:                0, 0
        !           359:        };
        !           360: 
        !           361:        op = generic(op);
        !           362:        for (i = 0; ops[i].op; i++)
        !           363:                if (op == ops[i].op)
        !           364:                        break;
        !           365:        assert(ops[i].name);
        !           366:        if (r)
        !           367:                error("operands of %s have illegal types `%t' and `%t'\n",
        !           368:                        ops[i].name, l->type, r->type);
        !           369:        else
        !           370:                error("operand of unary %s has illegal type `%t'\n", ops[i].name,
        !           371:                        l->type);
        !           372: }

unix.superglobalmegacorp.com

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