|
|
1.1 ! root 1: /* C compiler & debugger: expression evaluation */ ! 2: ! 3: #include "c.h" ! 4: ! 5: typedef struct { ! 6: Tree p; /* associated tree */ ! 7: Value r; /* the register */ ! 8: } Register; ! 9: static char *errcode; /* evaluation error string */ ! 10: static int nextr; ! 11: static Register regs[30]; ! 12: ! 13: dclproto(static Value *eval,(Tree)) ! 14: dclproto(static Value *treereg,(Tree)) ! 15: ! 16: /* evaluate - evaluate tree p */ ! 17: Symbol evaluate(p) Tree p; { ! 18: static struct symbol sym; ! 19: ! 20: nextr = 1; ! 21: errcode = 0; ! 22: sym.u.c.v = *eval(p); ! 23: if (errcode) ! 24: return 0; ! 25: sym.type = p->type; ! 26: return &sym; ! 27: } ! 28: ! 29: /* eval - recursively evaluate tree p, return allocated register */ ! 30: static Value *eval(p) Tree p; { ! 31: Value *r, *r1 = 0, *r2 = 0; ! 32: Tree left, right; ! 33: ! 34: if (r = treereg(p)) ! 35: return r; ! 36: if (nextr > sizeof regs/sizeof regs[0]) { ! 37: error("expression too complicated\n"); ! 38: return ®s[0].r; ! 39: } ! 40: regs[nextr].p = p; ! 41: r = ®s[nextr++].r; ! 42: switch (generic(p->op)) { /* control flow operators */ ! 43: case AND: ! 44: r1 = eval(p->kids[0]); ! 45: if (r1->i) ! 46: r1 = eval(p->kids[1]); ! 47: r->i = r1->i; ! 48: return r; ! 49: case COND: ! 50: r = eval(p->kids[0]); ! 51: r1 = eval(p->kids[r->i ? 1 : 2]); ! 52: *r = *r1; ! 53: return r; ! 54: case NOT: ! 55: r1 = eval(p->kids[0]); ! 56: r->i = !r1->i; ! 57: return r; ! 58: case OR: ! 59: r1 = eval(p->kids[0]); ! 60: if (r1->i == 0) ! 61: r1 = eval(p->kids[1]); ! 62: r->i = r1->i; ! 63: return r; ! 64: } ! 65: if (left = p->kids[0]) ! 66: r1 = eval(left); ! 67: if (right = p->kids[1]) ! 68: r2 = eval(right); ! 69: switch (p->op) { ! 70: case ADD+D: r->d = r1->d + r2->d; break; ! 71: case ADD+F: r->f = r1->f + r2->f; break; ! 72: case ADD+I: r->i = r1->i + r2->i; break; ! 73: case ADD+P: ! 74: if (isptr(left->type)) ! 75: r->s = r1->s + r2->i; ! 76: else ! 77: r->s = r1->i + r2->s; ! 78: break; ! 79: case ADD+U: r->u = r1->u + r2->u; break; ! 80: case ADDRF+P: ! 81: case ADDRG+P: ! 82: case ADDRL+P: goto bad; ! 83: case ARG+B: ! 84: case ARG+C: ! 85: case ARG+D: ! 86: case ARG+F: ! 87: case ARG+I: ! 88: case ARG+P: ! 89: case ARG+S: goto bad; ! 90: case ASGN+B: ! 91: case ASGN+C: ! 92: case ASGN+D: ! 93: case ASGN+F: ! 94: case ASGN+I: ! 95: case ASGN+P: ! 96: case ASGN+S: goto bad; ! 97: case BAND+I: r->i = r1->i&r2->i; break; ! 98: case BAND+U: r->u = r1->u&r2->u; break; ! 99: case BCOM+U: r->u = ~r1->u; break; ! 100: case BOR+I: r->i = r1->i|r2->i; break; ! 101: case BOR+U: r->u = r1->u|r2->u; break; ! 102: case BXOR+I: r->i = r1->i^r2->i; break; ! 103: case BXOR+U: r->u = r1->u^r2->u; break; ! 104: case CALL+B: ! 105: case CALL+D: ! 106: case CALL+F: ! 107: case CALL+I: ! 108: case CALL+V: goto bad; ! 109: case CNST+C: ! 110: case CNST+D: ! 111: case CNST+F: ! 112: case CNST+I: ! 113: case CNST+P: ! 114: case CNST+S: ! 115: case CNST+U: *r = p->u.v; break; ! 116: case CVC+I: r->i = r1->sc; break; ! 117: case CVC+U: r->u = r1->uc; break; ! 118: case CVD+F: r->f = r1->d; break; ! 119: case CVD+I: r->i = r1->d; break; ! 120: case CVD+U: r->u = r1->d; break; ! 121: case CVF+D: r->d = r1->f; break; ! 122: case CVI+C: r->sc = r1->i; break; ! 123: case CVI+D: r->d = r1->i; break; ! 124: case CVI+S: r->ss = r1->i; break; ! 125: case CVI+U: r->u = r1->i; break; ! 126: case CVP+U: r->u = (unsigned)r1->p; break; ! 127: case CVS+I: r->i = r1->ss; break; ! 128: case CVS+U: r->u = r1->us; break; ! 129: case CVU+C: r->uc = r1->u; break; ! 130: case CVU+D: r->d = r1->u; break; ! 131: case CVU+I: r->i = r1->u; break; ! 132: case CVU+P: r->p = (char *)r1->u; break; ! 133: case CVU+S: r->us = r1->u; break; ! 134: case DIV+D: ! 135: if (r2->d == 0.0) ! 136: errcode = "division by 0.0"; ! 137: else ! 138: r->d = r1->d/r2->d; ! 139: break; ! 140: case DIV+F: ! 141: if (r2->f == 0.0) ! 142: errcode = "division by 0"; ! 143: else ! 144: r->f = r1->f/r2->f; ! 145: break; ! 146: case DIV+I: ! 147: if (r2->i == 0) ! 148: errcode = "division by 0"; ! 149: else ! 150: r->i = r1->i/r2->i; ! 151: break; ! 152: case DIV+U: ! 153: if (r2->u == 0) ! 154: errcode = "division by 0"; ! 155: else ! 156: r->u = r1->u/r2->u; ! 157: break; ! 158: case EQ+D: r->i = r1->d == r2->d; break; ! 159: case EQ+F: r->i = r1->f == r2->f; break; ! 160: case EQ+I: r->i = r1->i == r2->i; break; ! 161: case EQ+U: r->i = r1->u == r2->u; break; ! 162: case FIELD: goto bad; ! 163: case GE+D: r->i = r1->d >= r2->d; break; ! 164: case GE+F: r->i = r1->f >= r2->f; break; ! 165: case GE+I: r->i = r1->i >= r2->i; break; ! 166: case GE+U: r->i = r1->u >= r2->u; break; ! 167: case GT+D: r->i = r1->d > r2->d; break; ! 168: case GT+F: r->i = r1->f > r2->f; break; ! 169: case GT+I: r->i = r1->i > r2->i; break; ! 170: case GT+U: r->i = r1->u > r2->u; break; ! 171: case INDIR+B: ! 172: case INDIR+C: ! 173: case INDIR+D: ! 174: case INDIR+F: ! 175: case INDIR+I: ! 176: case INDIR+P: ! 177: case INDIR+S: goto bad; ! 178: case JUMP+V: ! 179: fatal("eval", "unexpected %s operator\n", "JUMP+V"); ! 180: case LE+D: r->i = r1->d <= r2->d; break; ! 181: case LE+F: r->i = r1->f <= r2->f; break; ! 182: case LE+I: r->i = r1->i <= r2->i; break; ! 183: case LE+U: r->i = r1->u <= r2->u; break; ! 184: case LSH+I: r->i = r1->i<<r2->i; break; ! 185: case LSH+U: r->u = r1->u<<r2->u; break; ! 186: case LT+D: r->i = r1->d < r2->d; break; ! 187: case LT+F: r->i = r1->f < r2->f; break; ! 188: case LT+I: r->i = r1->i < r2->i; break; ! 189: case LT+U: r->i = r1->u < r2->u; break; ! 190: case MOD+I: ! 191: if (r2->i == 0) ! 192: errcode = "division by 0"; ! 193: else ! 194: r->i = r1->i%r2->i; ! 195: break; ! 196: case MOD+U: ! 197: if (r2->u == 0) ! 198: errcode = "division by 0"; ! 199: else ! 200: r->u = r1->u%r2->u; ! 201: break; ! 202: case MUL+D: r->d = r1->d*r2->d; break; ! 203: case MUL+F: r->f = r1->f*r2->f; break; ! 204: case MUL+I: r->i = r1->i*r2->i; break; ! 205: case MUL+U: r->u = r1->u*r2->u; break; ! 206: case NE+D: r->i = r1->d != r2->d; break; ! 207: case NE+F: r->i = r1->f != r2->f; break; ! 208: case NE+I: r->i = r1->i != r2->i; break; ! 209: case NE+U: r->i = r1->u != r2->i; break; ! 210: case NEG+D: r->d = -r1->d; break; ! 211: case NEG+F: r->f = -r1->f; break; ! 212: case NEG+I: r->i = -r1->i; break; ! 213: case RET+B: ! 214: case RET+D: ! 215: case RET+F: ! 216: case RET+I: ! 217: case RET+V: goto bad; ! 218: case RIGHT: r->d = r2->d; break; ! 219: case RSH+I: r->i = r1->i>>r2->i; break; ! 220: case RSH+U: r->u = r1->u>>r2->u; break; ! 221: case SUB+D: r->d = r1->d - r2->d; break; ! 222: case SUB+F: r->f = r1->f - r2->f; break; ! 223: case SUB+I: r->i = r1->i - r2->i; break; ! 224: case SUB+P: r->i = r1->s - r2->s; break; ! 225: case SUB+U: r->u = r1->u - r2->u; break; ! 226: default: bad: ! 227: fatal("eval", "unknown operator %d\n", p->op); ! 228: } ! 229: return r; ! 230: } ! 231: ! 232: /* treereg - return register associated with tree p or 0 */ ! 233: static Value *treereg(p) Tree p; { ! 234: int i; ! 235: ! 236: for (i = 0; i < nextr; i++) ! 237: if (regs[i].p == p) ! 238: return ®s[i].r; ! 239: return 0; ! 240: } ! 241: ! 242: /* vtoa - return string for the constant v of type ty */ ! 243: char *vtoa(ty, v) Type ty; Value v; { ! 244: static char buf[MAXLINE]; ! 245: ! 246: ty = unqual(ty); ! 247: switch (ty->op) { ! 248: case CHAR: ! 249: sprint(buf, "%d", v.uc); ! 250: break; ! 251: case SHORT: ! 252: sprint(buf, "%d", v.ss); ! 253: break; ! 254: case INT: ! 255: sprint(buf, "%d", v.i); ! 256: break; ! 257: case UNSIGNED: ! 258: if ((v.u&~0x7fff) == 0) ! 259: sprint(buf, "%d", v.u); ! 260: else ! 261: sprint(buf, "0x%x", v.u); ! 262: break; ! 263: case FLOAT: ! 264: if (v.f == 0.0) ! 265: return "0"; ! 266: sprintf(buf, "%.*g", 8, v.f); ! 267: break; ! 268: case DOUBLE: ! 269: if (v.d == 0.0) ! 270: return "0"; ! 271: sprintf(buf, "%.*g", 18, v.d); ! 272: break; ! 273: case ARRAY: ! 274: if (ty->type->op == CHAR) ! 275: return v.s; ! 276: /* else fall thru */ ! 277: case POINTER: case FUNCTION: ! 278: if (((unsigned)v.p&~0x7fff) == 0) ! 279: sprint(buf, "%d", v.p); ! 280: else ! 281: sprint(buf, "0x%x", v.p); ! 282: break; ! 283: default: ! 284: assert(0); ! 285: } ! 286: return buf; ! 287: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.