⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cfold2.c

📁 Open Watcom 的 C 编译器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
        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 + -