newer version
This commit is contained in:
parent
f2b68c8261
commit
3de71150a6
|
@ -1,4 +1,4 @@
|
|||
/* C O N S T A N T E X P R E S S I O N H A N D L I N G */
|
||||
/* C O N S T A N T E X P R E S S I O N H A N D L I N G */
|
||||
|
||||
static char *RcsId = "$Header$";
|
||||
|
||||
|
@ -14,33 +14,66 @@ static char *RcsId = "$Header$";
|
|||
|
||||
long mach_long_sign; /* sign bit of the machine long */
|
||||
int mach_long_size; /* size of long on this machine == sizeof(long) */
|
||||
long full_mask[MAXSIZE];/* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */
|
||||
long full_mask[MAXSIZE];/* full_mask[1] == 0xFF, full_mask[2] == 0xFFFF, .. */
|
||||
arith max_int; /* maximum integer on target machine */
|
||||
arith max_unsigned; /* maximum unsigned on target machine */
|
||||
arith max_longint; /* maximum longint on target machine */
|
||||
|
||||
#if 0
|
||||
cstunary(expp, oper)
|
||||
register struct node *expp;
|
||||
{
|
||||
/* The unary operation oper is performed on the constant
|
||||
expression expp, and the result restored in expp.
|
||||
*/
|
||||
arith o1 = expp->nd_INT;
|
||||
|
||||
switch(oper) {
|
||||
case '+':
|
||||
return;
|
||||
case '-':
|
||||
o1 = -o1;
|
||||
break;
|
||||
case NOT:
|
||||
o1 = !o1;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
expp->nd_INT = o1;
|
||||
cut_size(expp);
|
||||
}
|
||||
|
||||
cstbin(expp, oper, expr)
|
||||
struct expr **expp, *expr;
|
||||
register struct node *expp, *expr;
|
||||
{
|
||||
/* The operation oper is performed on the constant
|
||||
expressions *expp(ld) and expr(ct), and the result restored in
|
||||
*expp.
|
||||
/* The binary operation oper is performed on the constant
|
||||
expressions expp and expr, and the result restored in
|
||||
expp.
|
||||
*/
|
||||
arith o1 = (*expp)->VL_VALUE;
|
||||
arith o2 = expr->VL_VALUE;
|
||||
int uns = (*expp)->ex_type->tp_unsigned;
|
||||
arith o1 = expp->nd_INT;
|
||||
arith o2 = expr->nd_INT;
|
||||
int uns = expp->nd_type != int_type;
|
||||
|
||||
ASSERT(is_ld_cst(*expp) && is_cp_cst(expr));
|
||||
assert(expp->nd_class == Value && expr->nd_class == Value);
|
||||
switch (oper) {
|
||||
case IN:
|
||||
/* ??? */
|
||||
return;
|
||||
case '*':
|
||||
if (expp->nd_type->tp_fund == SET) {
|
||||
/* ??? */
|
||||
return;
|
||||
}
|
||||
o1 *= o2;
|
||||
break;
|
||||
case '/':
|
||||
assert(expp->nd_type->tp_fund == SET);
|
||||
/* ??? */
|
||||
return;
|
||||
case DIV:
|
||||
if (o2 == 0) {
|
||||
expr_error(expr, "division by 0");
|
||||
break;
|
||||
node_error(expr, "division by 0");
|
||||
return;
|
||||
}
|
||||
if (uns) {
|
||||
/* this is more of a problem than you might
|
||||
|
@ -74,10 +107,10 @@ cstbin(expp, oper, expr)
|
|||
else
|
||||
o1 /= o2;
|
||||
break;
|
||||
case '%':
|
||||
case MOD:
|
||||
if (o2 == 0) {
|
||||
expr_error(expr, "modulo by 0");
|
||||
break;
|
||||
node_error(expr, "modulo by 0");
|
||||
return;
|
||||
}
|
||||
if (uns) {
|
||||
if (o2 & mach_long_sign) {/* o2 > max_long */
|
||||
|
@ -104,24 +137,18 @@ cstbin(expp, oper, expr)
|
|||
o1 %= o2;
|
||||
break;
|
||||
case '+':
|
||||
if (expp->nd_type->tp_fund == SET) {
|
||||
/* ??? */
|
||||
return;
|
||||
}
|
||||
o1 += o2;
|
||||
break;
|
||||
case '-':
|
||||
o1 -= o2;
|
||||
break;
|
||||
case LEFT:
|
||||
o1 <<= o2;
|
||||
break;
|
||||
case RIGHT:
|
||||
if (o2 == 0)
|
||||
break;
|
||||
if (uns) {
|
||||
o1 >>= 1;
|
||||
o1 & = ~mach_long_sign;
|
||||
o1 >>= (o2-1);
|
||||
if (expp->nd_type->tp_fund == SET) {
|
||||
/* ??? */
|
||||
return;
|
||||
}
|
||||
else
|
||||
o1 >>= o2;
|
||||
o1 -= o2;
|
||||
break;
|
||||
case '<':
|
||||
if (uns) {
|
||||
|
@ -143,7 +170,11 @@ cstbin(expp, oper, expr)
|
|||
else
|
||||
o1 = o1 > o2;
|
||||
break;
|
||||
case LESSEQ:
|
||||
case LESSEQUAL:
|
||||
if (expp->nd_type->tp_fund == SET) {
|
||||
/* ??? */
|
||||
return;
|
||||
}
|
||||
if (uns) {
|
||||
o1 = (o1 & mach_long_sign ?
|
||||
(o2 & mach_long_sign ? o1 <= o2 : 0) :
|
||||
|
@ -153,7 +184,11 @@ cstbin(expp, oper, expr)
|
|||
else
|
||||
o1 = o1 <= o2;
|
||||
break;
|
||||
case GREATEREQ:
|
||||
case GREATEREQUAL:
|
||||
if (expp->nd_type->tp_fund == SET) {
|
||||
/* ??? */
|
||||
return;
|
||||
}
|
||||
if (uns) {
|
||||
o1 = (o1 & mach_long_sign ?
|
||||
(o2 & mach_long_sign ? o1 >= o2 : 1) :
|
||||
|
@ -163,59 +198,64 @@ cstbin(expp, oper, expr)
|
|||
else
|
||||
o1 = o1 >= o2;
|
||||
break;
|
||||
case EQUAL:
|
||||
case '=':
|
||||
if (expp->nd_type->tp_fund == SET) {
|
||||
/* ??? */
|
||||
return;
|
||||
}
|
||||
o1 = o1 == o2;
|
||||
break;
|
||||
case NOTEQUAL:
|
||||
case '#':
|
||||
if (expp->nd_type->tp_fund == SET) {
|
||||
/* ??? */
|
||||
return;
|
||||
}
|
||||
o1 = o1 != o2;
|
||||
break;
|
||||
case '&':
|
||||
o1 &= o2;
|
||||
case AND:
|
||||
o1 = o1 && o2;
|
||||
break;
|
||||
case '|':
|
||||
o1 |= o2;
|
||||
break;
|
||||
case '^':
|
||||
o1 ^= o2;
|
||||
case OR:
|
||||
o1 = o1 || o2;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
(*expp)->VL_VALUE = o1;
|
||||
cut_size(*expp);
|
||||
(*expp)->ex_flags |= expr->ex_flags;
|
||||
(*expp)->ex_flags &= ~EX_PARENS;
|
||||
expp->nd_INT = o1;
|
||||
cut_size(expp);
|
||||
}
|
||||
|
||||
cut_size(expr)
|
||||
struct expr *expr;
|
||||
register struct node *expr;
|
||||
{
|
||||
/* The constant value of the expression expr is made to
|
||||
conform to the size of the type of the expression.
|
||||
*/
|
||||
arith o1 = expr->VL_VALUE;
|
||||
int uns = expr->ex_type->tp_unsigned;
|
||||
int size = (int) expr->ex_type->tp_size;
|
||||
arith o1 = expr->nd_INT;
|
||||
int uns = expr->nd_type == card_type || expr->nd_type == intorcard_type;
|
||||
int size = expr->nd_type->tp_size;
|
||||
|
||||
ASSERT(expr->ex_class == Value);
|
||||
assert(expr->nd_class == Value);
|
||||
if (uns) {
|
||||
if (o1 & ~full_mask[size])
|
||||
expr_warning(expr,
|
||||
"overflow in unsigned constant expression");
|
||||
if (o1 & ~full_mask[size]) {
|
||||
node_warning(expr,
|
||||
"overflow in constant expression");
|
||||
}
|
||||
o1 &= full_mask[size];
|
||||
}
|
||||
else {
|
||||
int nbits = (int) (mach_long_size - size) * 8;
|
||||
long remainder = o1 & ~full_mask[size];
|
||||
|
||||
if (remainder != 0 && remainder != ~full_mask[size])
|
||||
expr_warning(expr, "overflow in constant expression");
|
||||
o1 <<= nbits; /* ??? */
|
||||
if (remainder != 0 && remainder != ~full_mask[size]) {
|
||||
node_warning(expr, "overflow in constant expression");
|
||||
}
|
||||
o1 <<= nbits;
|
||||
o1 >>= nbits;
|
||||
}
|
||||
expr->VL_VALUE = o1;
|
||||
expr->nd_INT = o1;
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
init_cst()
|
||||
{
|
||||
int i = 0;
|
||||
|
|
|
@ -13,7 +13,12 @@ struct node {
|
|||
#define Call 4 /* cast or procedure - or function call */
|
||||
#define Link 5
|
||||
struct type *nd_type; /* type of this node */
|
||||
struct token nd_token;
|
||||
union {
|
||||
struct token ndu_token;
|
||||
char *ndu_set; /* Pointer to a set constant */
|
||||
} nd_val;
|
||||
#define nd_token nd_val.ndu_token
|
||||
#define nd_set nd_val.ndu_set
|
||||
#define nd_symb nd_token.tk_symb
|
||||
#define nd_lineno nd_token.tk_lineno
|
||||
#define nd_filename nd_token.tk_filename
|
||||
|
|
Loading…
Reference in a new issue