cfold.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,229 行 · 第 1/3 页
C
1,229 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Expression tree folding (compile time math).
*
****************************************************************************/
#include "cvars.h"
#include "i64.h"
static bool IsConstantZero( TREEPTR tree );
uint_32 DoOp32( uint_32 left, opr_code opr, uint_32 right, bool sign )
{
uint_32 value;
switch( opr ) {
case OPR_ADD:
value = left + right;
break;
case OPR_SUB:
value = left - right;
break;
case OPR_MUL:
value = left * right;
break;
case OPR_DIV:
if( right == 0 ) { /* 10-mar-90 */
value = 0;
} else {
if( sign ) {
value = (int_32)left / (int_32)right;
} else {
value = left / right;
}
}
break;
case OPR_MOD:
if( right == 0 ) { /* 10-mar-90 */
value = 0;
} else {
if( sign ) {
value = (int_32)left % (int_32)right;
} else {
value = left % right;
}
}
break;
case OPR_RSHIFT:
if( sign ) {
value = (int_32)left >> (int_32)right;
} else {
value = left >> right;
}
break;
case OPR_LSHIFT:
value = left << right;
break;
case OPR_OR:
value = left | right;
break;
case OPR_OR_OR:
value = left || right;
break;
case OPR_AND:
value = left & right;
break;
case OPR_AND_AND:
value = left && right;
break;
case OPR_XOR:
value = left ^ right;
break;
case OPR_NEG:
value = - right;
break;
case OPR_COM:
value = ~ right;
break;
case OPR_NOT:
value = ! right;
break;
default:
value = 0;
}
return( value );
}
uint64 DoOp64( uint64 left, opr_code opr, uint64 right, bool sign )
{
uint64 tmp;
uint64 value;
int shift;
switch( opr ) {
case OPR_ADD:
U64Add( &left, &right, &value );
break;
case OPR_SUB:
U64Sub( &left, &right, &value );
break;
case OPR_MUL:
U64Mul( &left, &right, &value );
break;
case OPR_DIV:
U32ToU64( 0, &value );
if( U64Cmp( &right, &value ) != 0 ) {
if( sign ) {
I64Div( &left, &right, &value, &tmp );
} else {
U64Div( &left, &right, &value, &tmp );
}
}
break;
case OPR_MOD:
U32ToU64( 0, &value );
if( U64Cmp( &right, &value ) != 0 ) {
if( sign ) {
I64Div( &left, &right, &tmp, &value );
} else {
U64Div( &left, &right, &tmp, &value );
}
}
break;
case OPR_LSHIFT:
shift = right.u._32[L];
shift = -shift;
goto do_shift;
case OPR_RSHIFT:
shift = right.u._32[L];
do_shift:
if( shift > 0 ) {
if( sign ) {
I64ShiftR( &left, shift, &value );
} else {
U64ShiftR( &left, shift, &value );
}
} else {
shift = -shift;
U64ShiftL( &left, shift, &value );
}
break;
case OPR_OR:
value = left;
value.u._32[L] |= right.u._32[L];
value.u._32[H] |= right.u._32[H];
break;
case OPR_OR_OR:
U32ToU64( 0, &value );
if( U64Cmp( &left, &value ) || U64Cmp( &right, &value ) ) {
U32ToU64( 1, &value );
}
break;
case OPR_AND:
value = left;
value.u._32[L] &= right.u._32[L];
value.u._32[H] &= right.u._32[H];
break;
case OPR_AND_AND:
U32ToU64( 0, &value );
if( U64Cmp( &left, &value ) && U64Cmp( &right, &value ) ) {
U32ToU64( 1, &value );
}
break;
case OPR_XOR:
value = left;
value.u._32[L] ^= right.u._32[L];
value.u._32[H] ^= right.u._32[H];
break;
case OPR_NEG:
U64Neg( &right, &value );
// value = - right;
break;
case OPR_COM:
value.u._32[L] = ~right.u._32[L];
value.u._32[H] = ~right.u._32[H];
break;
case OPR_NOT:
U32ToU64( 0, &value );
if( U64Cmp( &right, &value ) == 0 ) {
U32ToU64( 1, &value );
}
break;
default:
U32ToU64( 0, &value );
}
return( value );
}
int DoSignedOp( TREEPTR op1, TREEPTR tree, TREEPTR op2 )
/******************************************************/
{
int_32 value;
int_32 left;
int_32 right;
DATA_TYPE const_type;
const_type = tree->expr_type->decl_type;
if( op1 != NULL ) {
left = op1->op.long_value;
}
right = op2->op.long_value;
if( tree->op.opr == OPR_CMP ) {
switch( tree->op.cc ) {
case CC_EQ:
value = (left == right);
break;
case CC_NE:
value = (left != right);
break;
case CC_GT:
value = (left > right);
break;
case CC_GE:
value = (left >= right);
break;
case CC_LT:
value = (left < right);
break;
case CC_LE:
value = (left <= right);
break;
}
const_type = TYPE_INT;
tree->op.long_value = (target_int)value;
} else {
value = DoOp32( left, tree->op.opr, right, TRUE );
if( const_type == TYPE_LONG ) {
tree->op.long_value = value;
} else {
tree->op.long_value = (target_int)value;
}
}
tree->op.opr = OPR_PUSHINT;
tree->op.const_type = const_type;
tree->left = NULL;
tree->right = NULL;
FreeExprNode( op1 );
FreeExprNode( op2 );
return( 1 );
}
int DoUnSignedOp( TREEPTR op1, TREEPTR tree, TREEPTR op2 )
/********************************************************/
{
uint_32 value;
uint_32 left;
uint_32 right;
DATA_TYPE const_type;
const_type = tree->expr_type->decl_type;
if( op1 != NULL ) {
left = op1->op.ulong_value;
}
right = op2->op.ulong_value;
if( tree->op.opr == OPR_CMP ) {
switch( tree->op.cc ) {
case CC_EQ:
value = (left == right);
break;
case CC_NE:
value = (left != right);
break;
case CC_GT:
value = (left > right);
break;
case CC_GE:
value = (left >= right);
break;
case CC_LT:
value = (left < right);
break;
case CC_LE:
value = (left <= right);
break;
}
const_type = TYPE_INT;
tree->op.long_value = (target_int)value;
} else {
value = DoOp32( left, tree->op.opr, right, FALSE );
if( const_type == TYPE_ULONG ) {
tree->op.long_value = value;
} else {
tree->op.long_value = (target_uint)value;
}
}
tree->op.opr = OPR_PUSHINT;
tree->op.const_type = const_type;
tree->left = NULL;
tree->right = NULL;
FreeExprNode( op1 );
FreeExprNode( op2 );
return( 1 );
}
int64 LongValue64( TREEPTR leaf )
/*******************************/
{
int64 value;
int_32 val32;
FLOATVAL *flt;
char *endptr;
long_double ld;
bool sign;
switch( leaf->op.const_type ) {
case TYPE_CHAR:
sign = TRUE;
val32 = (signed char)leaf->op.ulong_value;
break;
case TYPE_UCHAR:
sign = FALSE;
val32 = (unsigned char)leaf->op.ulong_value;
break;
case TYPE_SHORT:
sign = TRUE;
val32 = (target_short)leaf->op.ulong_value;
break;
case TYPE_USHORT:
sign = FALSE;
val32 = (target_ushort)leaf->op.ulong_value;
break;
case TYPE_INT:
sign = TRUE;
val32 = (target_int)leaf->op.ulong_value;
break;
case TYPE_UINT:
sign = FALSE;
val32 = (target_uint)leaf->op.ulong_value;
break;
case TYPE_LONG:
sign = TRUE;
val32 = (target_long)leaf->op.ulong_value;
break;
case TYPE_POINTER:
case TYPE_ULONG:
sign = FALSE;
val32 = (target_ulong)leaf->op.ulong_value;
break;
case TYPE_LONG64:
case TYPE_ULONG64:
return( leaf->op.ulong64_value );
break;
case TYPE_FLOAT:
case TYPE_DOUBLE:
sign = TRUE;
flt = leaf->op.float_value;
if( flt->len == 0 ) {
ld = flt->ld;
} else {
__Strtold( flt->string, &ld, &endptr );
}
CMemFree( flt );
#ifdef _LONG_DOUBLE_
val32 = __LDI4( (long_double near *)&ld );
#else
val32 = ld.value;
#endif
break;
default:
val32 = 0;
break;
}
if( sign ) {
I32ToI64( val32, &value );
} else {
U32ToU64( val32, &value );
}
return( value );
}
int DoUnSignedOp64( TREEPTR op1, TREEPTR tree, TREEPTR op2 )
/**********************************************************/
{
uint64 value;
uint64 left;
uint64 right;
int tmp;
DATA_TYPE const_type;
if( op1 != NULL ) {
left = LongValue64( op1 );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?