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