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

1.1     ! root        1: /* C compiler: tree simplification and constant folding */
        !             2: 
        !             3: #include "c.h"
        !             4: 
        !             5: int needconst;         /* >=1 if parsing a constant expression */
        !             6: 
        !             7: dclproto(static int add,(double, double, double, double, int));
        !             8: dclproto(static Tree addrnode,(Symbol, int, Type));
        !             9: dclproto(static int div,(double, double, double, double, int));
        !            10: dclproto(static int mul,(double, double, double, double, int));
        !            11: dclproto(static int sub,(double, double, double, double, int));
        !            12: 
        !            13: /* add - return 1 if min <= x+y <= max, 0 otherwise */
        !            14: static int add(x, y, min, max, needconst) double x, y, min, max; {
        !            15:        int cond = x == 0 || y == 0
        !            16:        || x < 0 && y < 0 && x >= min - y
        !            17:        || x < 0 && y > 0
        !            18:        || x > 0 && y < 0
        !            19:        || x > 0 && y > 0 && x <= max - y;
        !            20:        if (!cond && needconst) {
        !            21:                warning("overflow in constant expression\n");
        !            22:                cond = 1;
        !            23:        }
        !            24:        return cond;
        !            25: }
        !            26: 
        !            27: /* addrnode - create a tree for addressing expression p+n, type ty */
        !            28: static Tree addrnode(p, n, ty) Symbol p; Type ty; {
        !            29:        Symbol q = (Symbol)talloc(sizeof *q);
        !            30:        Tree e;
        !            31:        static struct symbol z;
        !            32: 
        !            33:        *q = z;
        !            34:        q->name = stringd(genlabel(1));
        !            35:        q->sclass = p->sclass;
        !            36:        q->scope = p->scope;
        !            37:        q->type = ty;
        !            38:        q->defined = 1;
        !            39:        q->temporary = p->temporary;
        !            40:        q->generated = p->generated;
        !            41:        q->computed = 1;
        !            42:        q->addressed = p->addressed;
        !            43:        q->ref = 1;
        !            44:        if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN) {
        !            45:                q->sclass = p->sclass == AUTO ? STATIC : p->sclass;
        !            46:                (*IR->address)(q, p, n);
        !            47:                e = tree(ADDRG+P, ty, 0, 0);
        !            48:        } else {
        !            49:                Code cp;
        !            50:                if (!p->defined)
        !            51:                        addlocal(p);
        !            52:                cp = code(Address);
        !            53:                cp->u.addr.sym = q;
        !            54:                cp->u.addr.base = p;
        !            55:                cp->u.addr.offset = n;
        !            56:                e = tree(p->scope == PARAM ? ADDRF+P : ADDRL+P, ty, 0, 0);
        !            57:        }
        !            58:        e->u.sym = q;
        !            59:        return e;
        !            60: }
        !            61: 
        !            62: /* div - return 1 if min <= x/y <= max, 0 otherwise */
        !            63: static int div(x, y, min, max, needconst) double x, y, min, max; {
        !            64:        int cond;
        !            65: 
        !            66:        if (x < 0) x = -x;
        !            67:        if (y < 0) y = -y;
        !            68:        cond = y != 0 && (y > 1 || x <= max*y);
        !            69:        if (!cond && y != 0 && needconst) {
        !            70:                warning("overflow in constant expression\n");
        !            71:                cond = 1;
        !            72:        }
        !            73:        return cond;
        !            74: }
        !            75: 
        !            76: /* ispow2 - if u > 1 && u == 2^n, return n, otherwise return 0 */
        !            77: int ispow2(u) unsigned u; {
        !            78:        int n;
        !            79: 
        !            80:        if (u > 1 && (u&(u-1)) == 0)
        !            81:                for (n = 0; u; u >>= 1, n++)
        !            82:                        if (u&1)
        !            83:                                return n;
        !            84:        return 0;
        !            85: }
        !            86: 
        !            87: /* mul - return 1 if min <= x*y <= max, 0 otherwise */
        !            88: static int mul(x, y, min, max, needconst) double x, y, min, max; {
        !            89:        int cond = x > -1 && x <= 1 || y > -1 && y <= 1
        !            90:        || x < 0 && y < 0 && -x <= max/-y
        !            91:        || x < 0 && y > 0 &&  x >= min/y
        !            92:        || x > 0 && y < 0 &&  x >= min/y
        !            93:        || x > 0 && y > 0 &&  x <= max/y;
        !            94:        if (!cond && needconst) {
        !            95:                warning("overflow in constant expression\n");
        !            96:                cond = 1;
        !            97:        }
        !            98:        return cond;
        !            99: }
        !           100: 
        !           101: #define xcvtcnst(FTYPE,TTYPE,EXP,VAR,MIN,MAX) \
        !           102:        if (l->op == CNST+FTYPE) { \
        !           103:                if (needconst && (VAR < MIN || VAR > MAX)) \
        !           104:                        warning("overflow in constant expression\n"); \
        !           105:                if (needconst || VAR >= MIN && VAR <= MAX) { \
        !           106:                        p = tree(CNST+ttob(TTYPE), TTYPE, 0, 0); EXP; return p; } }
        !           107: #define cvtcnst(FTYPE,TTYPE,EXP) \
        !           108:        if (l->op == CNST+FTYPE) { \
        !           109:                p = tree(CNST+ttob(TTYPE), TTYPE, 0, 0); EXP; return p; }
        !           110: #define commute(L,R) \
        !           111:        if (generic(R->op) == CNST && generic(L->op) != CNST) { \
        !           112:                Tree t = L; L = R; R = t; }
        !           113: #define zerofield(OP,TYPE,VAR) \
        !           114:        if (l->op == FIELD && r->op == CNST+TYPE && r->u.v.VAR == 0) \
        !           115:                return eqnode(OP, bitnode(BAND, l->kids[0], \
        !           116:                        constnode(fieldmask(l->u.field)<<fieldright(l->u.field), \
        !           117:                                unsignedtype)), r);
        !           118: #define ufoldcnst(TYPE,EXP) if (l->op == CNST+TYPE) return EXP
        !           119: #define xfoldcnst(TYPE,VAR,OP,RTYPE,FUNC,MIN,MAX,needconst) \
        !           120:        if (l->op == CNST+TYPE && r->op == CNST+TYPE \
        !           121:        && FUNC((double)l->u.v.VAR,(double)r->u.v.VAR,(double)MIN,(double)MAX, needconst)) { \
        !           122:                p = tree(CNST+ttob(RTYPE), RTYPE, 0, 0); \
        !           123:                p->u.v.VAR = l->u.v.VAR OP r->u.v.VAR; return p; }
        !           124: #define foldcnst(TYPE,VAR,OP,RTYPE) \
        !           125:        if (l->op == CNST+TYPE && r->op == CNST+TYPE) { \
        !           126:                p = tree(CNST+ttob(RTYPE), RTYPE, 0, 0); \
        !           127:                p->u.v.VAR = l->u.v.VAR OP r->u.v.VAR; return p; }
        !           128: #define cfoldcnst(TYPE,VAR,OP,RTYPE) \
        !           129:        if (l->op == CNST+TYPE && r->op == CNST+TYPE) { \
        !           130:                p = tree(CNST+ttob(RTYPE), RTYPE, 0, 0); \
        !           131:                p->u.v.i = l->u.v.VAR OP r->u.v.VAR; return p; }
        !           132: #define sfoldcnst(TYPE,VAR,OP,RTYPE) \
        !           133:        if (l->op == CNST+TYPE && r->op == CNST+I \
        !           134:        && r->u.v.i >= 0 && r->u.v.i < 8*l->type->size) { \
        !           135:                p = tree(CNST+ttob(RTYPE), RTYPE, 0, 0); \
        !           136:                p->u.v.VAR = l->u.v.VAR OP r->u.v.i; return p; }
        !           137: #define foldaddp(L,R,RTYPE,VAR) \
        !           138:        if (L->op == CNST+P && R->op == CNST+RTYPE) { \
        !           139:                p = tree(CNST+P, ty, 0, 0); \
        !           140:                p->u.v.p = L->u.v.p + R->u.v.VAR; return p; }
        !           141: #define geu(L,R,V) \
        !           142:        if (R->op == CNST+U && R->u.v.u == 0) { \
        !           143:                warning("result of unsigned comparison is constant\n"); \
        !           144:                return tree(RIGHT, inttype, root(L), constnode(V, inttype)); }
        !           145: #define idempotent(OP) if (l->op == OP) return l->kids[0];
        !           146: #define identity(X,Y,TYPE,VAR,VAL) if (X->op == CNST+TYPE && X->u.v.VAR == VAL) return Y
        !           147: 
        !           148: /* simplify - build node for op, simplifying and folding constants, if possible */
        !           149: Tree simplify(op, ty, l, r) Type ty; Tree l, r; {
        !           150:        int n;
        !           151:        Tree p;
        !           152: 
        !           153:        if (optype(op) == 0)
        !           154:                op += ttob(ty);
        !           155:        switch (op) {
        !           156:        case ADD+D:
        !           157:                xfoldcnst(D,d,+,doubletype,add,-DBL_MAX,DBL_MAX,0);
        !           158:                commute(r,l);
        !           159:                break;
        !           160:        case ADD+F:
        !           161:                xfoldcnst(F,f,+,floattype,add,-FLT_MAX,FLT_MAX,0);
        !           162:                commute(r,l);
        !           163:                break;
        !           164:        case ADD+I:
        !           165:                xfoldcnst(I,i,+,inttype,add,INT_MIN,INT_MAX,needconst);
        !           166:                commute(r,l);
        !           167:                break;
        !           168:        case ADD+P:
        !           169:                foldaddp(l,r,I,i);
        !           170:                foldaddp(l,r,U,u);
        !           171:                foldaddp(r,l,I,i);
        !           172:                foldaddp(r,l,U,u);
        !           173:                commute(r,l);
        !           174:                identity(r,retype(l,ty),I,i,0);
        !           175:                identity(r,retype(l,ty),U,u,0);
        !           176:                if (isaddrop(l->op) && (r->op == CNST+I || r->op == CNST+U))
        !           177:                        /* l + c => l+c, where l is a symbolic address */
        !           178:                        return addrnode(l->u.sym, r->op == CNST+I ? r->u.v.i : r->u.v.u, ty);
        !           179:                if ((l->op == ADD+I || l->op == SUB+I)
        !           180:                && l->kids[1]->op == CNST+I && isaddrop(r->op))
        !           181:                        /* (x +- c) + r => x + r+-c, where r is a symbolic address */
        !           182:                        return simplify(ADD+P, ty, l->kids[0],
        !           183:                                simplify(l->op == ADD+I ? ADD+P : SUB+P, ty, r, l->kids[1]));
        !           184:                if (l->op == ADD+P && isaddrop(l->kids[1]->op)
        !           185:                && (r->op == CNST+I || r->op == CNST+U))
        !           186:                        /* (x + a) + r => x + a+r */
        !           187:                        return simplify(ADD+P, ty, l->kids[0],
        !           188:                                addrnode(l->kids[1]->u.sym, r->op == CNST+I ? r->u.v.i : r->u.v.u, ty));
        !           189:                if (l->op == ADD+P && generic(l->kids[1]->op) == CNST && generic(r->op) == CNST)
        !           190:                        /* (x + c) + r => x + c+r */
        !           191:                        return simplify(ADD+P, ty, l->kids[0], (*opnode['+'])(ADD, l->kids[1], r));
        !           192:                if (l->op == ADD+I && generic(l->kids[1]->op) == CNST
        !           193:                &&  r->op == ADD+P && generic(r->kids[1]->op) == CNST)
        !           194:                        /* (x + c1) + (y + c2) => x + (y + c1+c2) */
        !           195:                        return simplify(ADD+P, ty, l->kids[0],
        !           196:                                simplify(ADD+P, ty, r->kids[0],
        !           197:                                (*opnode['+'])(ADD, l->kids[1], r->kids[1])));
        !           198:                if (l->op == RIGHT && isstruct(l->type))        /* f().x */
        !           199:                        return tree(RIGHT, ty, l->kids[0],
        !           200:                                simplify(ADD+P, ty, l->kids[1], r));
        !           201:                if (l->op == RIGHT)
        !           202:                        if (l->kids[1])
        !           203:                                return tree(RIGHT, ty, l->kids[0],
        !           204:                                        simplify(ADD+P, ty, l->kids[1], r));
        !           205:                        else
        !           206:                                return tree(RIGHT, ty,
        !           207:                                        simplify(ADD+P, ty, l->kids[0], r), 0);
        !           208:                break;
        !           209:        case ADD+U:
        !           210:                foldcnst(U,u,+,unsignedtype);
        !           211:                commute(r,l);
        !           212:                break;
        !           213:        case AND+I:
        !           214:                op = AND;
        !           215:                ufoldcnst(I,l->u.v.i ? cond(r) : l);    /* 0&&r => 0, 1&&r => r */
        !           216:                break;
        !           217:        case OR+I:
        !           218:                op = OR;
        !           219:                /* 0||r => r, 1||r => 1 */
        !           220:                ufoldcnst(I,l->u.v.i ? constnode(1, inttype) : cond(r));
        !           221:                break;
        !           222:        case BAND+U:
        !           223:                foldcnst(U,u,&,unsignedtype);
        !           224:                commute(r,l);
        !           225:                identity(r,l,U,u,(~0));
        !           226:                if (r->op == CNST+U && r->u.v.u == 0)   /* l&0 => (l,0) */
        !           227:                        return tree(RIGHT, unsignedtype, root(l),
        !           228:                                constnode(0, unsignedtype));
        !           229:                break;
        !           230:        case BCOM+I:
        !           231:                ufoldcnst(I,constnode(~l->u.v.i, inttype));
        !           232:                idempotent(BCOM+U);
        !           233:                op = BCOM+U;
        !           234:                break;
        !           235:        case BCOM+U:
        !           236:                ufoldcnst(U,constnode(~l->u.v.u, unsignedtype));
        !           237:                idempotent(BCOM+U);
        !           238:                break;
        !           239:        case BOR+U:
        !           240:                foldcnst(U,u,|,unsignedtype);
        !           241:                commute(r,l);
        !           242:                identity(r,l,U,u,0);
        !           243:                break;
        !           244:        case BXOR+U:
        !           245:                foldcnst(U,u,^,unsignedtype);
        !           246:                commute(r,l);
        !           247:                identity(r,l,U,u,0);
        !           248:                break;
        !           249:        case CVC+I:  cvtcnst(C,      inttype,p->u.v.i  = (l->u.v.sc&0200 ? (~0<<8) : 0)|(l->u.v.sc&0377)); break;
        !           250:        case CVC+U:  cvtcnst(C, unsignedtype,p->u.v.u  = l->u.v.uc); break;
        !           251:        case CVD+F: xcvtcnst(D,    floattype,p->u.v.f  = l->u.v.d,l->u.v.d,-FLT_MAX,FLT_MAX); break;
        !           252:        case CVD+I: xcvtcnst(D,      inttype,p->u.v.i  = l->u.v.d,l->u.v.d,INT_MIN,INT_MAX); break;
        !           253:        case CVF+D:  cvtcnst(F,   doubletype,p->u.v.d  = l->u.v.f);  break;
        !           254:        case CVI+C: xcvtcnst(I,     chartype,p->u.v.sc = l->u.v.i,l->u.v.i,SCHAR_MIN,SCHAR_MAX); break;
        !           255:        case CVI+D:  cvtcnst(I,   doubletype,p->u.v.d  = l->u.v.i);  break;
        !           256:        case CVI+S: xcvtcnst(I,    shorttype,p->u.v.ss = l->u.v.i,l->u.v.i,SHRT_MIN,SHRT_MAX); break;
        !           257:        case CVI+U:  cvtcnst(I, unsignedtype,p->u.v.u  = l->u.v.i);  break;
        !           258:        case CVP+U:  cvtcnst(P, unsignedtype,p->u.v.u  = (unsigned)l->u.v.p); break;
        !           259:        case CVS+I:  cvtcnst(S,      inttype,p->u.v.i  = l->u.v.ss); break;
        !           260:        case CVS+U:  cvtcnst(S, unsignedtype,p->u.v.u  = l->u.v.us); break;
        !           261:        case CVU+C:  cvtcnst(U, unsignedchar,p->u.v.uc = l->u.v.u);  break;
        !           262:        case CVU+D:  cvtcnst(U,   doubletype,p->u.v.d  = utod(l->u.v.u));  break;
        !           263:        case CVU+I:
        !           264:                if (needconst && l->u.v.u > INT_MAX)
        !           265:                        warning("overflow in constant expression\n");
        !           266:                if (needconst || l->u.v.u <= INT_MAX)
        !           267:                        cvtcnst(U,   inttype,p->u.v.i  = l->u.v.u);
        !           268:                break;
        !           269:        case CVU+P:  cvtcnst(U,    voidptype,p->u.v.p  = (char *)l->u.v.u);  break;
        !           270:        case CVU+S:  cvtcnst(U,unsignedshort,p->u.v.us = l->u.v.u);  break;
        !           271:        case DIV+D:
        !           272:                xfoldcnst(D,d,/,doubletype,div,-DBL_MAX,DBL_MAX,0);
        !           273:                break;
        !           274:        case DIV+F:
        !           275:                xfoldcnst(F,f,/,floattype,div,-FLT_MAX,FLT_MAX,0);
        !           276:                break;
        !           277:        case DIV+I:
        !           278:                identity(r,l,I,i,1);
        !           279: #ifdef mips
        !           280:                if (l->op == CNST+I && r->op == CNST+I && r->u.v.i == -1
        !           281:                && !div((double)l->u.v.i, (double)r->u.v.i, (double)INT_MIN, (double)INT_MAX, 0))
        !           282:                        break;
        !           283: #endif
        !           284:                xfoldcnst(I,i,/,inttype,div,INT_MIN,INT_MAX,needconst);
        !           285:                break;
        !           286:        case DIV+U:             
        !           287:                identity(r,l,U,u,1);
        !           288:                if (r->op == CNST+U && r->u.v.u == 0)
        !           289:                        break;
        !           290:                if (r->op == CNST+U && (n = ispow2(r->u.v.u)))
        !           291:                        return simplify(RSH+U, unsignedtype, l, constnode(n, inttype));
        !           292:                foldcnst(U,u,/,unsignedtype);
        !           293:                break;
        !           294:        case EQ+D:
        !           295:                cfoldcnst(D,d,==,inttype);
        !           296:                commute(r,l);
        !           297:                break;
        !           298:        case EQ+F:
        !           299:                cfoldcnst(F,f,==,inttype);
        !           300:                commute(r,l);
        !           301:                break;
        !           302:        case EQ+I:
        !           303:                cfoldcnst(I,i,==,inttype);
        !           304:                commute(r,l);
        !           305:                zerofield(EQ,I,i);
        !           306:                break;
        !           307:        case EQ+U:
        !           308:                cfoldcnst(U,u,==,inttype);
        !           309:                commute(r,l);
        !           310:                zerofield(EQ,U,u);
        !           311:                op = EQ+I;
        !           312:                break;
        !           313:        case GE+D: cfoldcnst(D,d,>=,inttype); break;
        !           314:        case GE+F: cfoldcnst(F,f,>=,inttype); break;
        !           315:        case GE+I: cfoldcnst(I,i,>=,inttype); break;
        !           316:        case GE+U:
        !           317:                geu(l,r,1);     /* l >= 0 => (l,1) */
        !           318:                cfoldcnst(U,u,>=,inttype);
        !           319:                if (l->op == CNST+U && l->u.v.u == 0)   /* 0 >= r => 0 == r */
        !           320:                        return tree(EQ+I, ty, l, r);
        !           321:                break;
        !           322:        case GT+D: cfoldcnst(D,d, >,inttype); break;
        !           323:        case GT+F: cfoldcnst(F,f, >,inttype); break;
        !           324:        case GT+I: cfoldcnst(I,i, >,inttype); break;
        !           325:        case GT+U:
        !           326:                geu(r,l,0);     /* 0 > r => (r,0) */
        !           327:                cfoldcnst(U,u, >,inttype);
        !           328:                if (r->op == CNST+U && r->u.v.u == 0)   /* l > 0 => l != 0 */
        !           329:                        return tree(NE+I, ty, l, r);
        !           330:                break;
        !           331:        case LE+D: cfoldcnst(D,d,<=,inttype); break;
        !           332:        case LE+F: cfoldcnst(F,f,<=,inttype); break;
        !           333:        case LE+I: cfoldcnst(I,i,<=,inttype); break;
        !           334:        case LE+U:
        !           335:                geu(r,l,1);     /* 0 <= r => (r,1) */
        !           336:                cfoldcnst(U,u,<=,inttype);
        !           337:                if (r->op == CNST+U && r->u.v.u == 0)   /* l <= 0 => l == 0 */
        !           338:                        return tree(EQ+I, ty, l, r);
        !           339:                break;
        !           340:        case LSH+I:
        !           341:                identity(r,l,I,i,0);
        !           342:                if (l->op == CNST+I && r->op == CNST+I
        !           343:                && r->u.v.i >= 0 && r->u.v.i < 8*l->type->size
        !           344:                && mul((double)l->u.v.i, (double)(1<<r->u.v.i), (double)INT_MIN, (double)INT_MAX, needconst))
        !           345:                        return constnode(l->u.v.i<<r->u.v.i, inttype);
        !           346:                break;
        !           347:        case LSH+U:
        !           348:                identity(r,l,I,i,0);
        !           349:                sfoldcnst(U,u,<<,unsignedtype);
        !           350:                break;
        !           351:        case LT+D: cfoldcnst(D,d, <,inttype); break;
        !           352:        case LT+F: cfoldcnst(F,f, <,inttype); break;
        !           353:        case LT+I: cfoldcnst(I,i, <,inttype); break;
        !           354:        case LT+U:
        !           355:                geu(l,r,0);     /* l < 0 => (l,0) */
        !           356:                cfoldcnst(U,u, <,inttype);
        !           357:                if (l->op == CNST+U && l->u.v.u == 0)   /* 0 < r => 0 != r */
        !           358:                        return tree(NE+I, ty, l, r);
        !           359:                break;
        !           360:        case MOD+I:
        !           361:                if (r->op == CNST+I && r->u.v.i == 1)   /* l%1 => (l,0) */
        !           362:                        return tree(RIGHT, inttype, root(l), constnode(0, inttype));
        !           363:                if (r->op == CNST+I && r->u.v.i == 0)
        !           364:                        break;
        !           365: #ifdef mips
        !           366:                if (l->op == CNST+I && r->op == CNST+I && r->u.v.i == -1
        !           367:                && !div((double)l->u.v.i, (double)r->u.v.i, (double)INT_MIN, (double)INT_MAX, 0))
        !           368:                        break;
        !           369: #endif
        !           370:                xfoldcnst(I,i,%,inttype,div,INT_MIN,INT_MAX,needconst);
        !           371:                break;
        !           372:        case MOD+U:             
        !           373:                if (r->op == CNST+U && ispow2(r->u.v.u))        /* l%2^n => l&(2^n-1) */
        !           374:                        return bitnode(BAND, l,
        !           375:                                constnode(r->u.v.u - 1, unsignedtype));
        !           376:                if (r->op == CNST+U && r->u.v.u == 0)
        !           377:                        break;
        !           378:                foldcnst(U,u,%,unsignedtype);
        !           379:                break;
        !           380:        case MUL+D:
        !           381:                xfoldcnst(D,d,*,doubletype,mul,-DBL_MAX,DBL_MAX,0);
        !           382:                commute(l,r);
        !           383:                break;
        !           384:        case MUL+F:
        !           385:                xfoldcnst(F,f,*,floattype,mul,-FLT_MAX,FLT_MAX,0);
        !           386:                commute(l,r);
        !           387:                break;
        !           388:        case MUL+I:
        !           389:                commute(l,r);
        !           390:                if (l->op == CNST+I && r->op == ADD+I && r->kids[1]->op == CNST+I)
        !           391:                        /* c1*(x + c2) => c1*x + c1*c2 */
        !           392:                        return simplify(ADD+I, inttype, simplify(MUL+I, inttype, l, r->kids[0]),
        !           393:                                simplify(MUL+I, inttype, l, r->kids[1]));
        !           394:                if (l->op == CNST+I && r->op == SUB+I && r->kids[1]->op == CNST+I)
        !           395:                        /* c1*(x - c2) => c1*x - c1*c2 */
        !           396:                        return simplify(SUB+I, inttype, simplify(MUL+I, inttype, l, r->kids[0]),
        !           397:                                simplify(MUL+I, inttype, l, r->kids[1]));
        !           398:                if (l->op == CNST+I && l->u.v.i > 0 && (n = ispow2(l->u.v.i)))
        !           399:                        /* 2^n * r => r<<n */
        !           400:                        return simplify(LSH+I, inttype, r, constnode(n, inttype));
        !           401:                xfoldcnst(I,i,*,inttype,mul,INT_MIN,INT_MAX,needconst);
        !           402:                break;
        !           403:        case MUL+U:
        !           404:                commute(l,r);
        !           405:                if (l->op == CNST+U && (n = ispow2(l->u.v.u)))
        !           406:                        /* 2^n * r => r<<n */
        !           407:                        return simplify(LSH+U, unsignedtype, r, constnode(n, inttype));
        !           408:                foldcnst(U,u,*,unsignedtype);
        !           409:                break;
        !           410:        case NE+D:
        !           411:                foldcnst(D,d,!=,inttype);
        !           412:                commute(r,l);
        !           413:                break;
        !           414:        case NE+F:
        !           415:                cfoldcnst(F,f,!=,inttype);
        !           416:                commute(r,l);
        !           417:                break;
        !           418:        case NE+I:
        !           419:                cfoldcnst(I,i,!=,inttype);
        !           420:                commute(r,l);
        !           421:                zerofield(NE,I,i);
        !           422:                break;
        !           423:        case NE+U:
        !           424:                cfoldcnst(U,u,!=,inttype);
        !           425:                commute(r,l);
        !           426:                zerofield(NE,U,u);
        !           427:                op = NE+I;
        !           428:                break;
        !           429:        case NEG+D:
        !           430:                ufoldcnst(D,(p = tree(CNST+D, doubletype, 0, 0), p->u.v.d = -l->u.v.d, p));
        !           431:                idempotent(NEG+D);
        !           432:                break;
        !           433:        case NEG+F:
        !           434:                ufoldcnst(F,(p = tree(CNST+F, floattype, 0, 0), p->u.v.f = -l->u.v.f, p));
        !           435:                idempotent(NEG+F);
        !           436:                break;
        !           437:        case NEG+I:
        !           438:                if (l->op == CNST+I) {
        !           439:                        if (needconst && l->u.v.i == INT_MIN)
        !           440:                                warning("overflow in constant expression\n");
        !           441:                        if (needconst || l->u.v.i != INT_MIN)
        !           442:                                return constnode(-l->u.v.i, inttype);
        !           443:                }
        !           444:                idempotent(NEG+I);
        !           445:                break;
        !           446:        case NOT+I:
        !           447:                op = NOT;
        !           448:                ufoldcnst(I,constnode(!l->u.v.i, inttype));
        !           449:                break;
        !           450:        case RSH+I:
        !           451:                identity(r,l,I,i,0);
        !           452:                if (l->op == CNST+I && r->op == CNST+I
        !           453:                && r->u.v.i >= 0 && r->u.v.i < 8*l->type->size) {
        !           454:                        int n = l->u.v.i>>r->u.v.i;
        !           455:                        if (l->u.v.i < 0)
        !           456:                                n |= ~0<<(8*l->type->size - r->u.v.i);
        !           457:                        return constnode(n, inttype);
        !           458:                }
        !           459:                break;
        !           460:        case RSH+U:
        !           461:                identity(r,l,I,i,0);
        !           462:                sfoldcnst(U,u,>>,unsignedtype);
        !           463:                break;
        !           464:        case SUB+D:
        !           465:                xfoldcnst(D,d,-,doubletype,sub,-DBL_MAX,DBL_MAX,0);
        !           466:                break;
        !           467:        case SUB+F:
        !           468:                xfoldcnst(F,f,-,floattype,sub,-FLT_MAX,FLT_MAX,0);
        !           469:                break;
        !           470:        case SUB+I:
        !           471:                xfoldcnst(I,i,-,inttype,sub,INT_MIN,INT_MAX,needconst);
        !           472:                break;
        !           473:        case SUB+U:
        !           474:                foldcnst(U,u,-,unsignedtype);
        !           475:                break;
        !           476:        case SUB+P:
        !           477:                if (l->op == CNST+P && r->op == CNST+P)
        !           478:                        return constnode(l->u.v.p - r->u.v.p, inttype);
        !           479:                if (r->op == CNST+I || r->op == CNST+U)
        !           480:                        return simplify(ADD+P, ty, l,
        !           481:                                constnode(r->op == CNST+I ? -r->u.v.i : -(int)r->u.v.u, inttype));
        !           482:                if (isaddrop(l->op) && r->op == ADD+I && r->kids[1]->op == CNST+I)
        !           483:                        /* l - (x + c) => l-c - x */
        !           484:                        return simplify(SUB+P, ty,
        !           485:                                simplify(SUB+P, ty, l, r->kids[1]), r->kids[0]);
        !           486:                break;
        !           487:        default:assert(0);
        !           488:        }
        !           489:        return tree(op, ty, l, r);
        !           490: }
        !           491: 
        !           492: /* sub - return 1 if min <= x-y <= max, 0 otherwise */
        !           493: static int sub(x, y, min, max, needconst) double x, y, min, max; {
        !           494:        return add(x, -y, min, max, needconst);
        !           495: }
        !           496: 
        !           497: /* vtoa - return string for the constant v of type ty */
        !           498: char *vtoa(ty, v) Type ty; Value v; {
        !           499:        char buf[50];
        !           500: 
        !           501:        ty = unqual(ty);
        !           502:        switch (ty->op) {
        !           503:        case CHAR:
        !           504:                return stringf("%d", v.uc);
        !           505:        case SHORT:
        !           506:                return stringf("%d", v.ss);
        !           507:        case INT:
        !           508:                return stringf("%d", v.i);
        !           509:        case UNSIGNED:
        !           510:                if ((v.u&~0x7fff) == 0)
        !           511:                        return stringf("%d", v.u);
        !           512:                else
        !           513:                        return stringf("0x%x", v.u);
        !           514:        case FLOAT:
        !           515:                if (v.f == 0.0)
        !           516:                        return "0";
        !           517:                sprintf(buf, "%.*g", 8, v.f);
        !           518:                return string(buf);
        !           519:        case DOUBLE:
        !           520:                if (v.d == 0.0)
        !           521:                        return "0";
        !           522:                sprintf(buf, "%.*g", 18, v.d);
        !           523:                return string(buf);
        !           524:        case ARRAY:
        !           525:                if (ty->type->op == CHAR)
        !           526:                        return v.p;
        !           527:                /* else fall thru */
        !           528:        case POINTER: case FUNCTION:
        !           529:                if (((unsigned)v.p&~0x7fff) == 0)
        !           530:                        return stringf("%d", v.p);
        !           531:                else
        !           532:                        return stringf("0x%x", v.p);
        !           533:        default:assert(0);
        !           534:        }
        !           535:        return 0;
        !           536: }

unix.superglobalmegacorp.com

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