📄 cfold2.c
字号:
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;
default:
#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;
if( opnd->op.opr == OPR_PUSHINT ) {
CastFloatValue( opnd, TYPE_DOUBLE );
}
flt = opnd->op.float_value;
if( flt->len != 0 ) {
__Strtold( flt->string, &ld, &endptr );
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;
#endif
break;
default:
value = 0;
break;
}
return( value );
}
void CastConstValue( TREEPTR leaf, DATA_TYPE newtyp )
{
int_32 val32;
int64 val64;
DATA_TYPE oldtyp;
oldtyp = leaf->op.const_type;
if( (newtyp == TYPE_DOUBLE || newtyp == TYPE_FLOAT)
&& (oldtyp == TYPE_DOUBLE || oldtyp == TYPE_FLOAT) ){
CastFloatValue( leaf, newtyp ); // float to float
return;
}else if( newtyp == TYPE_LONG64 || newtyp == TYPE_ULONG64 ){
val64 = LongValue64( leaf );
leaf->op.ulong64_value = val64;
}else{
val32 = LongValue( leaf );
switch( newtyp ) {
case TYPE_CHAR:
leaf->op.ulong_value = (signed char)val32;
break;
case TYPE_UCHAR:
leaf->op.ulong_value = (unsigned char)val32;
break;
case TYPE_SHORT:
leaf->op.ulong_value = (target_short)val32;
break;
case TYPE_USHORT:
leaf->op.ulong_value = (target_ushort)val32;
break;
case TYPE_INT:
leaf->op.ulong_value = (target_int)val32;
break;
case TYPE_UINT:
leaf->op.ulong_value = (target_uint)val32;
break;
case TYPE_LONG:
leaf->op.ulong_value = (target_long)val32;
break;
case TYPE_ULONG:
leaf->op.ulong_value = (target_ulong)val32;
break;
case TYPE_FLOAT:
case TYPE_DOUBLE:
CastFloatValue( leaf, newtyp );
return;
default:
return;
}
}
leaf->op.opr = OPR_PUSHINT;
leaf->op.const_type = newtyp;
}
void FoldQuestionTree( TREEPTR tree )
{
TREEPTR node;
TREEPTR true_part;
TREEPTR false_part;
op_flags ops;
node = tree->right; // point to OPR_COLON node
true_part = node->left;
false_part = node->right;
FreeExprNode( node );
if( tree->left->op.long_value == 0 ) {
node = false_part; // want false_part
FreeExprTree( true_part );
} else {
node = true_part; // want true_part
FreeExprTree( false_part );
}
ops = tree->op.flags;
FreeExprNode( tree->left );
*tree = *node;
node->op.opr = OPR_NOP;
FreeExprNode( node );
if( ops & OPFLAG_RVALUE ){
if( tree->op.opr == OPR_PUSHADDR ){
tree->op.opr = OPR_PUSHSYM;
ops &= ~OPFLAG_RVALUE;
}
tree->op.flags = ops;
}
}
static bool ConstantLeaf( TREEPTR opnd )
{
if( opnd->op.opr == OPR_PUSHINT || opnd->op.opr == OPR_PUSHFLOAT ) {
return( TRUE );
}else{
return( FALSE );
}
}
static bool FoldableTree( TREEPTR tree )
{
TREEPTR opnd;
TYPEPTR typ;
unsigned offset;
switch( tree->op.opr ) {
case OPR_ADD:
case OPR_SUB:
case OPR_MUL:
case OPR_DIV:
case OPR_CMP:
case OPR_MOD:
case OPR_OR:
case OPR_AND:
case OPR_XOR:
case OPR_RSHIFT:
case OPR_LSHIFT:
case OPR_OR_OR:
case OPR_AND_AND:
return( ConstantLeaf( tree->left ) && ConstantLeaf( tree->right ) );
case OPR_NEG:
case OPR_COM:
case OPR_NOT:
return( ConstantLeaf( tree->right ) );
case OPR_CONVERT:
opnd = tree->right;
if( opnd->op.opr == OPR_PUSHINT || opnd->op.opr == OPR_PUSHFLOAT ) {
typ = tree->expr_type;
CastConstValue( opnd, typ->decl_type );
*tree = *opnd;
tree->expr_type = typ;
opnd->op.opr = OPR_NOP;
FreeExprNode( opnd );
}
break;
case OPR_COMMA:
opnd = tree->left;
if( opnd->op.opr == OPR_PUSHINT || opnd->op.opr == OPR_PUSHFLOAT ) {
FreeExprNode( opnd );
opnd = tree->right;
*tree = *opnd;
opnd->op.opr = OPR_NOP;
FreeExprNode( opnd );
}
break;
case OPR_QUESTION:
if( tree->left->op.opr == OPR_PUSHINT ) {
FoldQuestionTree( tree );
}
break;
case OPR_ADDROF: // look for offsetof() pattern
offset = 0;
opnd = tree->right;
while( opnd->op.opr == OPR_DOT ) {
offset += opnd->right->op.long_value;
opnd = opnd->left;
}
if( opnd->op.opr == OPR_ARROW ) {
offset += opnd->right->op.long_value;
opnd = opnd->left;
if( opnd->op.opr == OPR_PUSHINT ) {
offset += opnd->op.long_value;
opnd = tree->right;
tree->op.opr = OPR_PUSHINT;
tree->op.long_value = offset;
tree->op.const_type = TYPE_UINT;
tree->expr_type = GetType( TYPE_UINT );
tree->right = NULL;
FreeExprTree( opnd );
}
}
break;
default:
break;
}
return( FALSE );
}
typedef enum {
SIGNED_INT,
UNSIGNED_INT,
SIGNED_INT64,
UNSIGNED_INT64,
FLOATING,
NOT_A_NUMBER
}arithmetic_type;
static arithmetic_type ArithmeticType( DATA_TYPE decl_type )
{
switch( decl_type ) {
case TYPE_CHAR:
case TYPE_SHORT:
case TYPE_INT:
case TYPE_LONG:
return( SIGNED_INT );
case TYPE_LONG64:
return( SIGNED_INT64 );
case TYPE_UCHAR:
case TYPE_USHORT:
case TYPE_UINT:
case TYPE_ULONG:
case TYPE_POINTER:
return( UNSIGNED_INT );
case TYPE_ULONG64:
return( UNSIGNED_INT64 );
case TYPE_FLOAT:
case TYPE_DOUBLE:
return( FLOATING );
}
return( NOT_A_NUMBER );
}
void DoConstFold( TREEPTR tree )
{
DATA_TYPE decl_type;
if( FoldableTree( tree ) ){
arithmetic_type con;
if( tree->op.opr == OPR_CMP ){
decl_type = tree->op.compare_type->decl_type;
}else{
decl_type = tree->expr_type->decl_type;
}
con = ArithmeticType( decl_type );
switch( con ){
case SIGNED_INT:
DoSignedOp( tree->left, tree, tree->right );
break;
case SIGNED_INT64:
DoSignedOp64( tree->left, tree, tree->right );
break;
case UNSIGNED_INT:
DoUnSignedOp( tree->left, tree, tree->right );
break;
case UNSIGNED_INT64:
DoUnSignedOp64( tree->left, tree, tree->right );
break;
case FLOATING:
DoFloatOp( tree->left, tree, tree->right );
break;
}
}
}
void FoldExprTree( TREEPTR tree )
{
WalkExprTree( tree, NoOp, NoOp, NoOp, DoConstFold );
}
bool BoolConstExpr( void )
{
const_val val;
uint64 tmp;
bool ret;
ConstExprAndType( &val );
//Must be int
if( val.type == TYPE_LONG64 || val.type == TYPE_ULONG64 ){
U32ToU64( 0, &tmp );
if( U64Cmp( &tmp, &val.val64 ) != 0 ){
ret = TRUE;
}else{
ret = FALSE;
}
}else{
if( val.val32 != 0 ){
ret = TRUE;
}else{
ret = FALSE;
}
}
return( ret );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -