cfold.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,229 行 · 第 1/3 页
C
1,229 行
}
right = LongValue64( op2 );
const_type = tree->expr_type->decl_type;
if( tree->op.opr == OPR_CMP ) {
tmp = U64Cmp( &left, &right );
switch( tree->op.cc ) {
case CC_EQ:
tmp = tmp == 0;
break;
case CC_NE:
tmp = tmp != 0;
break;
case CC_GT:
tmp = tmp > 0;
break;
case CC_LE:
tmp = tmp <= 0;
break;
case CC_GE:
tmp = tmp >= 0;
break;
case CC_LT:
tmp = tmp < 0;
break;
}
const_type = TYPE_INT;
tree->op.long_value = (target_int)tmp;
} else {
value = DoOp64( left, tree->op.opr, right, FALSE );
if( const_type == TYPE_ULONG64 ) {
tree->op.long64_value = value;
} else {
tree->op.ulong_value = value.u._32[L];
}
}
tree->op.opr = OPR_PUSHINT;
tree->op.const_type = const_type;
tree->left = NULL;
tree->right = NULL;
FreeExprNode( op1 );
FreeExprNode( op2 );
return( 1 );
}
int DoSignedOp64( TREEPTR op1, TREEPTR tree, TREEPTR op2 )
/********************************************************/
{
int64 value;
int64 left;
int64 right;
int tmp;
DATA_TYPE const_type;
if( op1 != NULL ) {
left = LongValue64( op1 );
}
right = LongValue64( op2 );
const_type = tree->expr_type->decl_type;
if( tree->op.opr == OPR_CMP ) {
tmp = I64Cmp( &left, &right );
switch( tree->op.cc ) {
case CC_EQ:
tmp = tmp == 0;
break;
case CC_NE:
tmp = tmp != 0;
break;
case CC_GT:
tmp = tmp > 0;
break;
case CC_LE:
tmp = tmp <= 0;
break;
case CC_GE:
tmp = tmp >= 0;
break;
case CC_LT:
tmp = tmp < 0;
break;
}
const_type = TYPE_INT;
tree->op.long_value = (target_int)tmp;
} else {
value = DoOp64( left, tree->op.opr, right, TRUE );
if( const_type == TYPE_LONG64 ) {
tree->op.long64_value = value;
} else {
tree->op.long_value = value.u._32[L];
}
}
tree->op.opr = OPR_PUSHINT;
tree->op.const_type = const_type;
tree->left = NULL;
tree->right = NULL;
FreeExprNode( op1 );
FreeExprNode( op2 );
return( 1 );
}
void CastFloatValue( TREEPTR leaf, DATA_TYPE newtype )
{
FLOATVAL *flt;
char *endptr;
long_double ld;
#ifdef _LONG_DOUBLE_
double doubleval;
float floatval;
#endif
if( leaf->op.opr == OPR_PUSHFLOAT ) {
flt = leaf->op.float_value;
if( flt->len == 0 ) { // if contains binary value
ld = flt->ld;
} else {
__Strtold( flt->string, &ld, &endptr );
}
} else { // integer
switch( leaf->op.const_type ) {
//signed types
case TYPE_CHAR:
case TYPE_SHORT:
case TYPE_INT:
case TYPE_LONG:
#ifdef _LONG_DOUBLE_
__I4LD( leaf->op.long_value, (long_double near *)&ld );
#else
ld.value = (double)leaf->op.long_value;
#endif
break;
case TYPE_LONG64:
#ifdef _LONG_DOUBLE_
__I8LD( &leaf->op.long64_value, (long_double near *)&ld );
#else
#if defined(__WATCOM_INT64__) || defined(__GNUC__)
ld.value = (double)leaf->op.ulong64_value.u._64[0];
#else
ld.value = 0;//not implemented, issue a warning
#endif
#endif
break;
default:
//unsigned types
if( leaf->op.const_type == TYPE_ULONG64 ) {
#ifdef _LONG_DOUBLE_
__U8LD( &leaf->op.ulong64_value, (long_double near *)&ld );
#else
#if defined(__WATCOM_INT64__) || defined(__GNUC__)
ld.value = (double)leaf->op.ulong64_value.u._64[0];
#else
ld.value = 0;//not implemented, issue a warning
#endif
#endif
} else {
#ifdef _LONG_DOUBLE_
__U4LD( leaf->op.long_value, (long_double near *)&ld );
#else
ld.value = (double)leaf->op.ulong_value;
#endif
}
break;
}
flt = CMemAlloc( sizeof(FLOATVAL) );
leaf->op.float_value = flt;
leaf->op.opr = OPR_PUSHFLOAT;
}
leaf->op.const_type = newtype;
switch( newtype ) {
case TYPE_FLOAT:
#ifdef _LONG_DOUBLE_
__LDFS( (long_double near *)&ld, (float near *)&floatval );
__FSLD( (float near *)&floatval, (long_double near *)&ld );
#else
ld.value = (float)ld.value;
#endif
break;
case TYPE_DOUBLE:
#ifdef _LONG_DOUBLE_
__LDFD( (long_double near *)&ld, (double near *)&doubleval );
__FDLD( (double near *)&doubleval, (long_double near *)&ld );
#endif
break;
}
flt->len = 0;
flt->type = newtype;
flt->ld = ld;
flt->string[0] = '\0';
}
void MakeBinaryFloat( TREEPTR opnd )
{
FLOATVAL *flt;
char *endptr;
long_double ld;
#ifdef _LONG_DOUBLE_
double doubleval;
float floatval;
#endif
if( opnd->op.opr == OPR_PUSHINT ) {
CastFloatValue( opnd, TYPE_DOUBLE );
}
flt = opnd->op.float_value;
if( flt->len != 0 ) {
__Strtold( flt->string, &ld, &endptr );
if( flt->type == TYPE_FLOAT ) {
#ifdef _LONG_DOUBLE_
__LDFS( (long_double near *)&ld, (float near *)&floatval );
__FSLD( (float near *)&floatval, (long_double near *)&ld );
#else
ld.value = (float)ld.value;
#endif
} else if( flt->type == TYPE_DOUBLE ) {
#ifdef _LONG_DOUBLE_
__LDFD( (long_double near *)&ld, (double near *)&doubleval );
__FDLD( (double near *)&doubleval, (long_double near *)&ld );
#endif
}
flt->ld = ld;
flt->len = 0;
flt->string[0] = '\0';
}
}
int FltCmp( long_double near *ld1, long_double near *ld2 )
{
#ifdef _LONG_DOUBLE_
return( __FLDC( ld1, ld2 ) );
#else
if( ld1->value == ld2->value ) return( 0 );
if( ld1->value < ld2->value ) return( -1 );
return( 1 );
#endif
}
int DoFloatOp( TREEPTR op1, TREEPTR tree, TREEPTR op2 )
/*****************************************************/
{
int value;
int cond;
long_double ld1;
long_double ld2;
long_double result;
// load ld1 and ld2 from op1 and op2
if( op1 != NULL ) { // if not unary op
MakeBinaryFloat( op1 );
ld1 = op1->op.float_value->ld;
}
MakeBinaryFloat( op2 );
ld2 = op2->op.float_value->ld;
switch( tree->op.opr ) {
case OPR_CMP:
cond = FltCmp( (long_double near *)&ld1, (long_double near *)&ld2 );
switch( tree->op.cc ) {
case CC_EQ:
value = (cond == 0);
break;
case CC_NE:
value = (cond != 0);
break;
case CC_GT:
value = (cond > 0);
break;
case CC_GE:
value = (cond >= 0);
break;
case CC_LT:
value = (cond < 0);
break;
case CC_LE:
value = (cond <= 0);
break;
}
tree->op.opr = OPR_PUSHINT;
tree->op.ulong_value = value;
tree->op.const_type = TYPE_INT;
tree->expr_type = GetType( TYPE_INT );
tree->left = NULL;
tree->right = NULL;
FreeExprNode( op1 );
FreeExprNode( op2 );
return( 1 );
case OPR_ADD:
#ifdef _LONG_DOUBLE_
__FLDA( (long_double near *)&ld1,
(long_double near *)&ld2,
(long_double near *)&result );
#else
result.value = ld1.value + ld2.value;
#endif
break;
case OPR_SUB:
#ifdef _LONG_DOUBLE_
__FLDS( (long_double near *)&ld1,
(long_double near *)&ld2,
(long_double near *)&result );
#else
result.value = ld1.value - ld2.value;
#endif
break;
case OPR_MUL:
#ifdef _LONG_DOUBLE_
__FLDM( (long_double near *)&ld1,
(long_double near *)&ld2,
(long_double near *)&result );
#else
result.value = ld1.value * ld2.value;
#endif
break;
case OPR_DIV:
#ifdef _LONG_DOUBLE_
if( ld2.exponent == 0 && ld2.high_word == 0 && ld2.low_word == 0 ) {
result = ld2;
} else {
__FLDD( (long_double near *)&ld1,
(long_double near *)&ld2,
(long_double near *)&result );
}
#else
if( ld2.value == 0.0 ) {
result.value = 0.0;
} else {
result.value = ld1.value / ld2.value;
}
#endif
break;
case OPR_NEG:
#ifdef _LONG_DOUBLE_
result = ld2;
result.exponent ^= 0x8000;
#else
result.value = - ld2.value;
#endif
break;
default:
return( 0 );
}
// should the result be forced into a double or float?
tree->op.opr = OPR_PUSHFLOAT;
tree->op.float_value = op2->op.float_value;
tree->op.float_value->ld = result;
tree->op.const_type = TYPE_DOUBLE;
tree->expr_type = GetType( TYPE_DOUBLE );
tree->left = NULL;
tree->right = NULL;
FreeExprNode( op1 );
// we reused op2->op.float_value, so change op2->op.opr so that
// FreeExprNode doesn't try to free op2->op.float_value
op2->op.opr = OPR_NOP;
FreeExprNode( op2 );
return( 1 );
}
static int_32 LongValue( TREEPTR leaf )
{
int_32 value;
FLOATVAL *flt;
char *endptr;
long_double ld;
switch( leaf->op.const_type ) {
case TYPE_CHAR:
value = (signed char)leaf->op.ulong_value;
break;
case TYPE_UCHAR:
value = (unsigned char)leaf->op.ulong_value;
break;
case TYPE_SHORT:
value = (target_short)leaf->op.ulong_value;
break;
case TYPE_USHORT:
value = (target_ushort)leaf->op.ulong_value;
break;
case TYPE_INT:
value = (target_int)leaf->op.ulong_value;
break;
case TYPE_UINT:
value = (target_uint)leaf->op.ulong_value;
break;
case TYPE_LONG:
value = (target_long)leaf->op.ulong_value;
break;
case TYPE_ULONG:
case TYPE_POINTER:
value = (target_ulong)leaf->op.ulong_value;
break;
case TYPE_LONG64:
value = (target_long)leaf->op.ulong64_value.u._32[L];
break;
case TYPE_ULONG64:
value = (target_ulong)leaf->op.ulong64_value.u._32[L];
break;
case TYPE_FLOAT:
case TYPE_DOUBLE:
flt = leaf->op.float_value;
if( flt->len == 0 ) {
ld = flt->ld;
} else {
__Strtold( flt->string, &ld, &endptr );
}
CMemFree( flt );
#ifdef _LONG_DOUBLE_
value = __LDI4( (long_double near *)&ld );
#else
value = ld.value;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?