?? simp.c
字號:
#include "c.h"
#define foldcnst(TYPE,VAR,OP,RTYPE) \
if (l->op == CNST+TYPE && r->op == CNST+TYPE) {\
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 = L; L = R; R = t; }
#define xfoldcnst(TYPE,VAR,OP,RTYPE,FUNC,MIN,MAX,needconst)\
if (l->op == CNST+TYPE && r->op == CNST+TYPE\
&& FUNC((double)l->u.v.VAR,(double)r->u.v.VAR,\
(double)MIN,(double)MAX, needconst)) {\
p = tree(CNST+ttob(RTYPE), RTYPE, NULL, NULL);\
p->u.v.VAR = l->u.v.VAR OP r->u.v.VAR;\
return p; }
#define cvtcnst(FTYPE,TTYPE,EXPR) \
if (l->op == CNST+FTYPE) {\
p = tree(CNST+ttob(TTYPE), TTYPE, NULL, NULL);\
EXPR;\
return p; }
#define xcvtcnst(FTYPE,TTYPE,VAR,MIN,MAX,EXPR) \
if (l->op == CNST+FTYPE) {\
if (needconst && (VAR < MIN || VAR > MAX))\
warning("overflow in constant expression\n");\
if (needconst || VAR >= MIN && VAR <= MAX) {\
p = tree(CNST+ttob(TTYPE), TTYPE, NULL, NULL);\
EXPR;\
return p; } }
#define identity(X,Y,TYPE,VAR,VAL) \
if (X->op == CNST+TYPE && X->u.v.VAR == VAL)\
return Y
#define zerofield(OP,TYPE,VAR) \
if (l->op == FIELD\
&& r->op == CNST+TYPE && r->u.v.VAR == 0)\
return eqtree(OP, bittree(BAND, l->kids[0],\
consttree(\
fieldmask(l->u.field)<<fieldright(l->u.field),\
unsignedtype)), r);
#define cfoldcnst(TYPE,VAR,OP,RTYPE) \
if (l->op == CNST+TYPE && r->op == CNST+TYPE) {\
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; }
#define ufoldcnst(TYPE,EXP) if (l->op == CNST+TYPE) return EXP
#define sfoldcnst(TYPE,VAR,OP,RTYPE) \
if (l->op == CNST+TYPE && r->op == CNST+I \
&& r->u.v.i >= 0 && r->u.v.i < 8*l->type->size) { \
p = tree(CNST+ttob(RTYPE), RTYPE, NULL, NULL); \
p->u.v.VAR = l->u.v.VAR OP r->u.v.i; return p; }
#define geu(L,R,V) \
if (R->op == CNST+U && R->u.v.u == 0) { \
warning("result of unsigned comparison is constant\n"); \
return tree(RIGHT, inttype, root(L), consttree(V, inttype)); }
#define idempotent(OP) if (l->op == OP) return l->kids[0];
#define utod(x) (2.*(int)((unsigned)(x)>>1)+(int)((x)&1))
#define checkrange(val,minimum,maximum) \
if (val < minimum || val > maximum) warning("Overflow in constant expression\n");
int needconst;
static int add ARGS((double, double, double, double, int));
static Tree addrtree ARGS((Tree, int, Type));
static int div ARGS((double, double, double, double, int));
static int mul ARGS((double, double, double, double, int));
static int sub ARGS((double, double, double, double, int));
Tree constexpr(int tok)
{
Tree p;
needconst++;
p = expr1(tok);
needconst--;
return p;
}
int intexpr(int tok,int n)
{
Tree p = constexpr(tok);
needconst++;
if (generic(p->op) == CNST && isint(p->type))
n = cast(p, inttype)->u.v.i;
else
error(StrTab[85]);// <integer expression must be constant\n>
needconst--;
return n;
}
Tree simplify(int op,Type ty,Tree l,Tree r)
{
int n;
Tree p;
if (optype(op) == 0)
op += ttob(ty);
switch (op) {
case ADD+U:
if (r->op == CNSTU || r->op == CNSTI) {
if (r->u.v.i == 0)
return l;
if (l->op == ADD+U && l->kids[1]->op == CNSTU) {
l->kids[1]->u.v.i += r->u.v.i;
return l;
}
}
foldcnst(U,u,+,unsignedtype);
commute(r,l);
break;
case ADD+I:
if (r->op == CNSTU || r->op == CNSTI) {
if (r->u.v.i == 0)
return l;
if (l->op == ADD+I && l->kids[1]->op == CNSTI) {
l->kids[1]->u.v.i += r->u.v.i;
return l;
}
}
xfoldcnst(I,i,+,inttype,add,INT_MIN,INT_MAX,needconst);
commute(r,l);
break;
case ADD+L:
commute(r,l);
break;
case CVC+I:
cvtcnst(C,inttype, p->u.v.i =
(l->u.v.sc&0200 ? (~0<<8) : 0)|(l->u.v.sc&0377));
break;
case CVU+S:
if (l->op == CNSTU) {
if (l->u.v.u > 0xffff && (int)l->u.v.u < -32766)
warning(StrTab[86]);// <Overflow in constant expression\n>
}
cvtcnst(U,unsignedshort,p->u.v.us = l->u.v.u);
break;
case CVI+L:
case CVU+L:
cvtcnst(I,longlongtype,p->u.v.d = l->u.v.i); break;
case CVL+I:
case CVL+U:
op = CVL+I;
// xcvtcnst(L, inttype,l->u.v.d, INT_MIN,INT_MAX,
// p->u.v.i = (int)l->u.v.d); break;
break;
case CVL+D:
break;
case CVP+U:
cvtcnst(P,unsignedtype, p->u.v.u = (unsigned)l->u.v.p);
break;
case CVI+U:
cvtcnst(I,unsignedtype, p->u.v.u = l->u.v.i); break;
case CVC+U:
cvtcnst(C, unsignedtype,p->u.v.u = l->u.v.uc);
break;
case CVF+D: cvtcnst(F, doubletype,p->u.v.d = l->u.v.f); break;
case CVI+D: cvtcnst(I, doubletype,p->u.v.d = l->u.v.i); break;
case CVS+I: cvtcnst(S, inttype,p->u.v.i = l->u.v.ss); break;
case CVS+U: cvtcnst(S, unsignedtype,p->u.v.u = l->u.v.us); break;
case CVU+C:
if (l->op == CNSTU && l->u.v.u > 255)
warning(StrTab[87]);// <Overflow in constat expression\n>
cvtcnst(U, unsignedchar,p->u.v.uc = l->u.v.u);
break;
case CVU+D: cvtcnst(U, doubletype,p->u.v.d = utod(l->u.v.u)); break;
case CVU+I:
if (needconst && l->u.v.u > INT_MAX)
warning(StrTab[88]);// <overflow in constant expression\n>
if (needconst || l->u.v.u <= INT_MAX)
cvtcnst(U, inttype,p->u.v.i = l->u.v.u);
break;
case CVU+P: cvtcnst(U, voidptype,p->u.v.p = (void *)l->u.v.u); break;
case CVD+L:
break;
case CVI+C:
if (l->op == CNSTI) {
checkrange(l->u.v.i,SCHAR_MIN,SCHAR_MAX);
}
xcvtcnst(I, chartype,l->u.v.i,SCHAR_MIN,SCHAR_MAX,
p->u.v.sc = l->u.v.i);
break;
case CVD+F:
if (l->op == CNSTD)
checkrange(l->u.v.d, -FLT_MAX,FLT_MAX);
xcvtcnst(D,floattype,l->u.v.d, -FLT_MAX,FLT_MAX,
p->u.v.f = (float)l->u.v.d);
break;
case CVD+I:
if (l->op == CNSTD)
checkrange(l->u.v.d,INT_MIN,INT_MAX);
xcvtcnst(D, inttype,l->u.v.d, INT_MIN,INT_MAX,
p->u.v.i = (int)l->u.v.d);
break;
case CVI+S:
if (l->op == CNSTI)
checkrange(l->u.v.i,SHRT_MIN,SHRT_MAX);
xcvtcnst(I,shorttype,l->u.v.i, SHRT_MIN,SHRT_MAX,
p->u.v.ss = l->u.v.i);
break;
case BAND+U:
foldcnst(U,u,&,unsignedtype);
commute(r,l);
identity(r,l,U,u,(~(unsigned)0));
if (r->op == CNST+U && r->u.v.u == 0)
return tree(RIGHT, unsignedtype, root(l),
consttree(0, unsignedtype));
break;
case MUL+U:
if ((r->op == CNST+U || r->op == CNST+I) && r->u.v.u == 1)
return l;
commute(l,r);
if (l->op == CNST+U && (n = ispow2(l->u.v.u)) != 0)
return simplify(LSH+U, unsignedtype, r,
consttree(n, inttype));
foldcnst(U,u,*,unsignedtype);
break;
case NE+I:
cfoldcnst(I,i,!=,inttype);
commute(r,l);
zerofield(NE,I,i);
break;
case EQ+I:
cfoldcnst(I,i,==,inttype);
commute(r,l);
zerofield(EQ,I,i);
break;
case ADD+P:
if (r->op == CNST+P) {
if (r->u.v.i == 0)
return retype(l,ty);
}
foldaddp(l,r,I,i);
foldaddp(l,r,U,u);
foldaddp(r,l,I,i);
foldaddp(r,l,U,u);
commute(r,l);
identity(r,retype(l,ty),I,i,0);
identity(r,retype(l,ty),U,u,0);
if (isaddrop(l->op)
&& (r->op == CNST+I || r->op == CNST+U))
return addrtree(l, cast(r, inttype)->u.v.i, ty);
if (l->op == ADD+P && isaddrop(l->kids[1]->op)
&& (r->op == CNST+I || r->op == CNST+U))
return simplify(ADD+P, ty, l->kids[0],
addrtree(l->kids[1], cast(r, inttype)->u.v.i, ty));
if ((l->op == ADD+I || l->op == SUB+I)
&& l->kids[1]->op == CNST+I && isaddrop(r->op))
return simplify(ADD+P, ty, l->kids[0],
simplify(generic(l->op)+P, ty, r, l->kids[1]));
if (l->op == ADD+P && generic(l->kids[1]->op) == CNST
&& generic(r->op) == CNST)
return simplify(ADD+P, ty, l->kids[0],
(*optree['+'])(ADD, l->kids[1], r));
if (l->op == ADD+I && generic(l->kids[1]->op) == CNST
&& r->op == ADD+P && generic(r->kids[1]->op) == CNST)
return simplify(ADD+P, ty, l->kids[0],
simplify(ADD+P, ty, r->kids[0],
(*optree['+'])(ADD, l->kids[1], r->kids[1])));
if (l->op == RIGHT && l->kids[1])
return tree(RIGHT, ty, l->kids[0],
simplify(ADD+P, ty, l->kids[1], r));
else if (l->op == RIGHT && l->kids[0])
return tree(RIGHT, ty,
simplify(ADD+P, ty, l->kids[0], r), NULL);
break;
case ADD+D:
if (r->op == CNST+D &&
r->u.v.d == 0.0)
return l;
xfoldcnst(D,d,+,doubletype,add,-DBL_MAX,DBL_MAX,0);
commute(r,l);
break;
case ADD+F:
if (r->op == CNST+D &&
r->u.v.d == 0.0)
return l;
xfoldcnst(F,f,+,floattype,add,-FLT_MAX,FLT_MAX,0);
commute(r,l);
break;
case AND+I:
op = AND;
ufoldcnst(I,l->u.v.i ? cond(r) : l); /* 0&&r => 0, 1&&r => r */
break;
case AND+L:
case BAND+L:
break;
case OR+I:
op = OR;
/* 0||r => r, 1||r => 1 */
ufoldcnst(I,l->u.v.i ? consttree(1, inttype) : cond(r));
break;
case BCOM+I:
ufoldcnst(I,consttree(~l->u.v.i, inttype));
idempotent(BCOM+U);
op = BCOM+U;
break;
case BCOM+L:
ufoldcnst(I,consttree(~l->u.v.i, inttype));
break;
case BCOM+U:
ufoldcnst(U,consttree(~l->u.v.u, unsignedtype));
idempotent(BCOM+U);
break;
case BOR+U:
foldcnst(U,u,|,unsignedtype);
commute(r,l);
identity(r,l,U,u,0);
break;
case BXOR+U:
foldcnst(U,u,^,unsignedtype);
commute(r,l);
identity(r,l,U,u,0);
break;
case DIV+D:
xfoldcnst(D,d,/,doubletype,div,-DBL_MAX,DBL_MAX,0);
break;
case DIV+L:
xfoldcnst(L,d,/,longlongtype,div,-DBL_MAX,DBL_MAX,0);
break;
case DIV+F:
xfoldcnst(F,f,/,floattype,div,-FLT_MAX,FLT_MAX,0);
break;
case DIV+I:
identity(r,l,I,i,1);
#ifdef mips
if (l->op == CNST+I && r->op == CNST+I && r->u.v.i == -1
&& !div((double)l->u.v.i, (double)r->u.v.i, (double)INT_MIN, (double)INT_MAX, 0))
break;
#endif
xfoldcnst(I,i,/,inttype,div,INT_MIN,INT_MAX,needconst);
break;
case DIV+U:
identity(r,l,U,u,1);
if (r->op == CNST+U && r->u.v.u == 0)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -