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