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 + -
显示快捷键?