|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.