📄 simp.c
字号:
/*simp.c:进行常量合并和简化处理*/#include "cmm.h"#include <limits.h>static int addover(double x, double y, double min, double max);static int subover(double x, double y, double min, double max);static int mulover(double x, double y, double min, double max);static int addover(double x, double y, double min, double max);static int divover(double x, double y, double min, double max);#define xfoldcnst(TYPE,VAR,OP,RTYPE,FUNC,MIN,MAX)\ if(l->op == CNST+TYPE && r->op == CNST+TYPE\ && FUNC((double)l->u.v.VAR,(double)r->u.v.VAR,\ (double)MIN,(double)MAX)) {\ p = tree(CNST+ttob(RTYPE), RTYPE,NULL,NULL);\ p->u.v.VAR = l->u.v.VAR OP r->u.v.VAR;\ return p;}#define commute(L,R) \ if(generic(R->op) == CNST && generic(L->op) != CNST)\ { Tree t = R; R = L; L = t;} #define identify(X,Y,TYPE,VAR,VAL) \ if(X->op == CNST+TYPE && X->u.v.VAR == VAL)\ return Y;#define cvtcnst(FTYPE, TYPE, EXPR)\ if(l->op == CNST+FTYPE) {\ p = tree(CNST+ttob(TYPE), TYPE, NULL,NULL);\ EXPR;\ return p;}#define xcvtcnst(FTYPE,TTYPE,VAR,MIN,MAX,EXPR) \ if (l->op == CNST+FTYPE) {\ if ( (VAR < MIN || VAR > MAX))\ warning("overflow in constant expression\n");\ if (VAR >= MIN && VAR <= MAX) {\ p = tree(CNST+ttob(TTYPE), TTYPE, NULL, NULL);\ EXPR;\ return p; } }#define cfoldcnst(FTYPE,VAR,OP,RTYPE)\ if(l->op == CNST+FTYPE && r->op == CNST+FTYPE) {\ p = tree(CNST+ttob(RTYPE), RTYPE, NULL, NULL);\ p->u.v.i = l->u.v.VAR OP r->u.v.VAR;\ return p;\ }#define foldaddp(L,R,RTYPE,VAR) \ if (L->op == CNST+P && R->op == CNST+RTYPE) {\ p = tree(CNST+P, ty, NULL, NULL);\ p->u.v.p = (char *)L->u.v.p + R->u.v.VAR;\ return p; }Tree constexpr(int tok){ Tree p; p = expr(tok); return p;}int intexpr(int tok){ int n = 0; Tree p = constexpr(tok); if(CNST == generic(p->op) && isarith(p->type)) n = p->u.v.i; else error("integer expression must be constant\n"); return n;}/*simplify对生成树进行常量合并*/Tree simplify(int op, Type ty, Tree l, Tree r){ Tree p; DEBUG(fprint(2,"simplify begin\n")); if(0 == optype(op)) op += ttob(ty); switch(op) { case ADD+I: xfoldcnst(I,i,+,inttype,addover,INT_MIN,INT_MAX); commute(r,l); identify(r,l,I,i,0); break; case ADD+P: foldaddp(l,r,I,i); foldaddp(r,l,I,i); commute(r, l); identify(r, retype(l, ty),I,i,0); break; case CVC+I: cvtcnst(C, inttype, p->u.v.i = (l->u.v.c&0200 ? (~0<<8):0)|(l->u.v.i &0377)); break; case CVP+U: cvtcnst(P, unsignedtype,p->u.v.u = (unsigned)l->u.v.p); break; case CVI+C: xcvtcnst(I, chartype, l->u.v.i, SCHAR_MIN,SCHAR_MAX, p->u.v.c = l->u.v.i);break; case CVI+U: cvtcnst(I,unsignedtype, p->u.v.u = l->u.v.i); break; case CVU+P: cvtcnst(I, voidptype, p->u.v.p = (void *)l->u.v.u); break; case NE+I: cfoldcnst(I,i,!=,inttype); break; case NE+U: case NE+P: cfoldcnst(U,u,!=,inttype); op = NE+I; break; case EQ+I: cfoldcnst(I,i,==,inttype); break; case EQ+U: cfoldcnst(U, u, ==, inttype); op = EQ+I; break; case DIV+I: identify(r,l,I,i,1); xfoldcnst(I,i,/,inttype,divover,INT_MIN,INT_MAX); break; case GE+I: cfoldcnst(I,i,>=,inttype); break; case GE+U: cfoldcnst(U,u,>=,inttype); op = GE+I; break; case GT+I: cfoldcnst(I,i,>,inttype); break; case GT+U: cfoldcnst(U,u,>,inttype); op = GT+I; break; case LE+I: cfoldcnst(I,i,<=,inttype); break; case LE+U: cfoldcnst(U,u,<=,inttype); op = LE+I; break; case LT+I: cfoldcnst(I,i,<,inttype); break; case LT+U: cfoldcnst(U,u,<=,inttype); op=LT+I; break; case MOD+I: if(CNST+I == r->op && 1 == r->u.v.i) return consttree(0,inttype); if(CNST+I == r->op && 0 == r->u.v.i) break; xfoldcnst(I,i,%,inttype,divover,INT_MIN,INT_MAX); break; case MUL+I: commute(l,r); if((CNST+I == l->op && 0 == l->u.v.i) ||(CNST+I == r->op && 0 == r->u.v.i)) return consttree(0,inttype); identify(l,retype(r,ty),I,i,1); xfoldcnst(I,i,*,inttype,mulover,INT_MIN,INT_MAX); break; case NEG+I: if(CNST+I == l->op) { if(INT_MIN == l->u.v.i) warning("overflow in constant expression\n"); if(l->u.v.i != INT_MIN) return consttree( -l->u.v.i, inttype); } if(NEG+I == l->op) return l->kids[0]; break; case NOT+I: if(CNST+I == l->op) return consttree(!l->u.v.i, inttype); break; case SUB+I: xfoldcnst(I,i,-,inttype,subover,INT_MIN,INT_MAX); identify(r,l,I,i,0); break; case SUB+P: if( CNST+P == l->op && CNST+P == r->op) return consttree((char *)l->u.v.p - (char *)r->u.v.p,inttype); if( CNST+I == r->op) return simplify(ADD+P, ty, l, consttree(-r->u.v.i,inttype)); break; default:assert(0);break; } DEBUG(fprint(2,"simplify end\n")); return tree(op, ty, l, r);}/*addover检查x与y的和是否溢出。*/int addover(double x, double y, double min, double max){ int cond = x == 0 || y == 0 || (x < 0 && y < 0 && x >= min - y) || (x > 0 && y > 0 && x <= max - y) || (x < 0 && y > 0) || (x > 0 && y < 0); if(!cond) warning("overflow in constant expression\n"); return cond;}/*mulover检查x与y的积是否溢出。*/int mulover(double x, double y, double min, double max){ int cond = (x > -1 && x <= 1) || (y > -1 && y <= 1) || (x < 0 && y < 0 && -x <= max/-y) || (x < 0 && y > 0 && x >= min/y) || (x > 0 && y > 0 && x <= max/y) || (x > 0 && y < 0 && x >= min/y); if(!cond) warning("overflow in constant expression\n"); return cond;}/* div - return 1 if min <= x/y <= max, 0 otherwise */int divover(double x, double y, double min, double max){ int cond; if (x < 0) x = -x; if (y < 0) y = -y; cond = y != 0 && (y > 1 || x <= max*y); if (!cond && y != 0 ) warning("overflow in constant expression\n"); return cond;}int subover(double x, double y, double min, double max){ return addover(x, -y, min, max);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -