📄 simp.c
字号:
#include "c.h"
#include <float.h>
static char rcsid[] = "$Id: simp.c,v 1.1 2002/08/28 23:12:45 drh Exp $";
#define foldcnst(TYPE,VAR,OP) \
if (l->op == CNST+TYPE && r->op == CNST+TYPE) \
return cnsttree(ty, l->u.v.VAR OP r->u.v.VAR)
#define commute(L,R) \
if (generic(R->op) == CNST && generic(L->op) != CNST) \
do { Tree t = L; L = R; R = t; } while(0)
#define xfoldcnst(TYPE,VAR,OP,FUNC)\
if (l->op == CNST+TYPE && r->op == CNST+TYPE\
&& FUNC(l->u.v.VAR,r->u.v.VAR,\
ty->u.sym->u.limits.min.VAR,\
ty->u.sym->u.limits.max.VAR, needconst)) \
return cnsttree(ty, l->u.v.VAR OP r->u.v.VAR)
#define xcvtcnst(FTYPE,SRC,DST,VAR,EXPR) \
if (l->op == CNST+FTYPE) do {\
if (!explicitCast\
&& ((SRC) < DST->u.sym->u.limits.min.VAR || (SRC) > DST->u.sym->u.limits.max.VAR))\
warning("overflow in converting constant expression from `%t' to `%t'\n", l->type, DST);\
if (needconst\
|| !((SRC) < DST->u.sym->u.limits.min.VAR || (SRC) > DST->u.sym->u.limits.max.VAR))\
return cnsttree(ty, (EXPR)); } while(0)
#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],\
cnsttree(unsignedtype, \
(unsigned long)fieldmask(l->u.field)<<fieldright(l->u.field))), r)
#define cfoldcnst(TYPE,VAR,OP) \
if (l->op == CNST+TYPE && r->op == CNST+TYPE) \
return cnsttree(inttype, (long)(l->u.v.VAR OP r->u.v.VAR))
#define foldaddp(L,R,RTYPE,VAR) \
if (L->op == CNST+P && R->op == CNST+RTYPE) { \
Tree e = tree(CNST+P, ty, NULL, NULL);\
e->u.v.p = (char *)L->u.v.p + R->u.v.VAR;\
return e; }
#define ufoldcnst(TYPE,EXP) if (l->op == CNST+TYPE) return EXP
#define sfoldcnst(OP) \
if (l->op == CNST+U && r->op == CNST+I \
&& r->u.v.i >= 0 && r->u.v.i < 8*l->type->size) \
return cnsttree(ty, (unsigned long)(l->u.v.u OP r->u.v.i))
#define geu(L,R,V) \
if (R->op == CNST+U && R->u.v.u == 0) do { \
warning("result of unsigned comparison is constant\n"); \
return tree(RIGHT, inttype, root(L), cnsttree(inttype, (long)(V))); } while(0)
#define idempotent(OP) if (l->op == OP) return l->kids[0]
int needconst;
int explicitCast;
static int addi(long x, long y, long min, long max, int needconst) {
int cond = x == 0 || y == 0
|| x < 0 && y < 0 && x >= min - y
|| x < 0 && y > 0
|| x > 0 && y < 0
|| x > 0 && y > 0 && x <= max - y;
if (!cond && needconst) {
warning("overflow in constant expression\n");
cond = 1;
}
return cond;
}
static int addd(double x, double y, double min, double max, int needconst) {
int cond = x == 0 || y == 0
|| x < 0 && y < 0 && x >= min - y
|| x < 0 && y > 0
|| x > 0 && y < 0
|| x > 0 && y > 0 && x <= max - y;
if (!cond && needconst) {
warning("overflow in constant expression\n");
cond = 1;
}
return cond;
}
static Tree addrtree(Tree e, long n, Type ty) {
Symbol p = e->u.sym, q;
if (p->scope == GLOBAL
|| p->sclass == STATIC || p->sclass == EXTERN)
NEW0(q, PERM);
else
NEW0(q, FUNC);
q->name = stringd(genlabel(1));
q->sclass = p->sclass;
q->scope = p->scope;
assert(isptr(ty) || isarray(ty));
q->type = isptr(ty) ? ty->type : ty;
q->temporary = p->temporary;
q->generated = p->generated;
q->addressed = p->addressed;
q->computed = 1;
q->defined = 1;
q->ref = 1;
assert(IR->address);
if (p->scope == GLOBAL
|| p->sclass == STATIC || p->sclass == EXTERN) {
if (p->sclass == AUTO)
q->sclass = STATIC;
(*IR->address)(q, p, n);
} else {
Code cp;
addlocal(p);
cp = code(Address);
cp->u.addr.sym = q;
cp->u.addr.base = p;
cp->u.addr.offset = n;
}
e = tree(e->op, ty, NULL, NULL);
e->u.sym = q;
return e;
}
/* div[id] - return 1 if min <= x/y <= max, 0 otherwise */
static int divi(long x, long y, long min, long max, int needconst) {
int cond = y != 0 && !(x == min && y == -1);
if (!cond && needconst) {
warning("overflow in constant expression\n");
cond = 1;
}
return cond;
}
static int divd(double x, double y, double min, double max, int needconst) {
int cond;
if (x < 0) x = -x;
if (y < 0) y = -y;
cond = y != 0 && !(y < 1 && x > max*y);
if (!cond && needconst) {
warning("overflow in constant expression\n");
cond = 1;
}
return cond;
}
/* mul[id] - return 1 if min <= x*y <= max, 0 otherwise */
static int muli(long x, long y, long min, long max, int needconst) {
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 && y >= min/x
|| x > 0 && y > 0 && x <= max/y;
if (!cond && needconst) {
warning("overflow in constant expression\n");
cond = 1;
}
return cond;
}
static int muld(double x, double y, double min, double max, int needconst) {
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 && y >= min/x
|| x > 0 && y > 0 && x <= max/y;
if (!cond && needconst) {
warning("overflow in constant expression\n");
cond = 1;
}
return cond;
}
/* sub[id] - return 1 if min <= x-y <= max, 0 otherwise */
static int subi(long x, long y, long min, long max, int needconst) {
return addi(x, -y, min, max, needconst);
}
static int subd(double x, double y, double min, double max, int needconst) {
return addd(x, -y, min, max, needconst);
}
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 (p->op == CNST+I || p->op == CNST+U)
n = cast(p, inttype)->u.v.i;
else
error("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 = mkop(op, ty);
switch (op) {
case ADD+U:
foldcnst(U,u,+);
commute(r,l);
identity(r,l,U,u,0);
break;
case ADD+I:
xfoldcnst(I,i,+,addi);
commute(r,l);
identity(r,l,I,i,0);
break;
case CVI+I:
xcvtcnst(I,l->u.v.i,ty,i,(long)extend(l->u.v.i,ty));
break;
case CVU+I:
if (l->op == CNST+U) {
if (!explicitCast && l->u.v.u > ty->u.sym->u.limits.max.i)
warning("overflow in converting constant expression from `%t' to `%t'\n", l->type, ty);
if (needconst || !(l->u.v.u > ty->u.sym->u.limits.max.i))
return cnsttree(ty, (long)extend(l->u.v.u,ty));
}
break;
case CVP+U:
xcvtcnst(P,(unsigned long)l->u.v.p,ty,u,(unsigned long)l->u.v.p);
break;
case CVU+P:
xcvtcnst(U,(void*)l->u.v.u,ty,p,(void*)l->u.v.u);
break;
case CVP+P:
xcvtcnst(P,l->u.v.p,ty,p,l->u.v.p);
break;
case CVI+U:
xcvtcnst(I,l->u.v.i,ty,u,((unsigned long)l->u.v.i)&ones(8*ty->size));
break;
case CVU+U:
xcvtcnst(U,l->u.v.u,ty,u,l->u.v.u&ones(8*ty->size));
break;
case CVI+F:
xcvtcnst(I,l->u.v.i,ty,d,(long double)l->u.v.i);
case CVU+F:
xcvtcnst(U,l->u.v.u,ty,d,(long double)l->u.v.u);
break;
case CVF+I:
xcvtcnst(F,l->u.v.d,ty,i,(long)l->u.v.d);
break;
case CVF+F: {
float d;
if (l->op == CNST+F)
if (l->u.v.d < ty->u.sym->u.limits.min.d)
d = ty->u.sym->u.limits.min.d;
else if (l->u.v.d > ty->u.sym->u.limits.max.d)
d = ty->u.sym->u.limits.max.d;
else
d = l->u.v.d;
xcvtcnst(F,l->u.v.d,ty,d,(long double)d);
break;
}
case BAND+U:
foldcnst(U,u,&);
commute(r,l);
identity(r,l,U,u,ones(8*ty->size));
if (r->op == CNST+U && r->u.v.u == 0)
return tree(RIGHT, ty, root(l), cnsttree(ty, 0UL));
break;
case BAND+I:
foldcnst(I,i,&);
commute(r,l);
identity(r,l,I,i,ones(8*ty->size));
if (r->op == CNST+I && r->u.v.u == 0)
return tree(RIGHT, ty, root(l), cnsttree(ty, 0L));
break;
case MUL+U:
commute(l,r);
if (l->op == CNST+U && (n = ispow2(l->u.v.u)) != 0)
return simplify(LSH, ty, r, cnsttree(inttype, (long)n));
foldcnst(U,u,*);
identity(r,l,U,u,1);
break;
case NE+I:
cfoldcnst(I,i,!=);
commute(r,l);
zerofield(NE,I,i);
break;
case EQ+I:
cfoldcnst(I,i,==);
commute(r,l);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -