treefold.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,648 行 · 第 1/4 页

C
1,648
字号
    if( !HasBigConst( tipe ) && rite->u.name->c.int_value == 1 ) {
        BurnTree( rite );
        return( left );
    }
    test = CFTest( rv );
    if( test == 0 ) {
        return( TGBinary( O_COMMA, TGTrash( left ), rite, tipe ) );
    }
    if( HasBigConst( tipe ) ) return( NULL );
    if( test < 0 ) {
        CFNegate( rv );
    }
    fold = NULL;
    if( CFIsU32( rv ) ) {
        log = GetLog2( CFConvertByType( rv, tipe ) );
        if( log != -1 ) {
            fold = TGBinary( O_LSHIFT, left,
                          IntToType( log, TypeInteger ), tipe );
            if( test < 0 ) {
                fold = TGUnary( O_UMINUS, fold, tipe );
            }
            BurnTree( rite );
        }
    }
    if( test < 0 ) {
        CFNegate( rv );
    }
    return( fold );
}


extern  cfloat  *OkToNegate( cfloat *value, type_def *tipe )
/**********************************************************/
/* make sure we don't negate an unsigned and get out of range */
/* for example -MAX_LONG is no longer an integer type */
{
    cfloat      *neg;

    if( HasBigConst( tipe ) && ( tipe->attr & TYPE_FLOAT ) == 0 ) return( NULL );
    neg = CFCopy( value );
    CFNegate( neg );
    if( HasBigConst( tipe ) ) return( neg );
    if( tipe->attr & TYPE_SIGNED ) return( neg );
    if( CFIsSize( neg,   tipe->length ) ) return( neg );
    CFFree( neg );
    return( NULL );
}

extern  tn      FoldMinus( tn left, tn rite, type_def *tipe )
/***********************************************************/
{
    tn          fold;
    cfloat      *lv;
    cfloat      *rv;
    unsigned_32 li;
    unsigned_32 ri;

    fold = NULL;
    if( left->class == TN_CONS ) {
        lv = left->u.name->c.value;
        if( rite->class == TN_CONS ) {
            rv = rite->u.name->c.value;
            if( !HasBigConst( tipe ) && CFIs32( lv ) && CFIs32( rv ) ) {
                li = CFConvertByType( lv, tipe );
                ri = CFConvertByType( rv, tipe );
                ri = li - ri;
                fold = IntToType( ri, tipe );
            } else {
                fold = CFToType( CFSub( lv, rite->u.name->c.value ),
                                  tipe );
            }
            BurnTree( rite );
            BurnTree( left );
        } else if( CFTest( lv ) == 0 ) {
            fold = TGUnary( O_UMINUS, rite, tipe );
            BurnTree( left );
        }
    } else if( rite->class == TN_CONS ) {
        rv = OkToNegate( rite->u.name->c.value, tipe );
        if( rv != NULL ) {
            fold = TGBinary( O_PLUS, left, TGConst( rv, rite->tipe ),
                              tipe );
            BurnTree( rite );
        }
    } else if( rite->class == TN_UNARY && rite->op == O_UMINUS ) {
        fold = TGBinary( OP_ADD, left, rite->u.left, tipe );
        rite->u.left = NULL;
        BurnTree( rite );
    }
    return( fold );
}


static type_def *FixAddType( tn left, tn rite, type_def *tipe )
{
    if( left->tipe != tipe ) {
        if( left->tipe == rite->tipe ) {
            tipe = left->tipe;
        }
    }
    return( tipe );
}


extern  tn      FoldPlus( tn left, tn rite, type_def *tipe )
/**********************************************************/
{
    tn          fold;
    tn          temp;
    cfloat      *lv;
    cfloat      *rv;
    unsigned_32 li;
    unsigned_32 ri;

    if( left->class == TN_CONS ) {
        temp = left;
        left = rite;
        rite = temp;
    }
    fold = NULL;
    if( left->class == TN_CONS ) {
        lv = left->u.name->c.value;
        if( rite->class == TN_CONS ) {
            rv = rite->u.name->c.value;
            if( !HasBigConst( tipe ) && CFIs32( lv ) && CFIs32( rv ) ) {
                li = CFConvertByType( lv, tipe );
                ri = CFConvertByType( rv, tipe );
                ri = li + ri;
                fold = IntToType( ri, tipe );
            } else {
                fold = CFToType( CFAdd( lv, rite->u.name->c.value ),
                                  tipe );
            }
            BurnTree( rite );
            BurnTree( left );
        } else if( CFTest( lv ) == 0 ) {
            fold = TGConvert( rite, tipe );
            BurnTree( left );
        }
    } else if( rite->class == TN_CONS ) {
        if( CFTest( rite->u.name->c.value ) == 0 ) {
            fold = TGConvert( left, tipe );
            BurnTree( rite );
        } else if( left->class == TN_BINARY && left->op == O_PLUS &&
                   tipe == left->tipe && !HasBigConst( tipe ) ) {
            if( left->u.left->class == TN_CONS ) {
                tipe = FixAddType( left->u.left, rite, tipe );
                if( left->u.left->tipe == tipe ) {
                    fold = FoldPlus( left->u.left, rite, tipe );
                    left->u.left = fold;
                    fold = left;
                }
            } else if( left->rite->class == TN_CONS ) {
                tipe = FixAddType( left->rite, rite, tipe );
                if( left->rite->tipe == tipe ) {
                    fold = FoldPlus( left->rite, rite, tipe );
                    left->rite = fold;
                    fold = left;
                }
            }
        }
    } else if( rite->class == TN_UNARY && rite->op == O_UMINUS ) {
        fold = TGBinary( OP_SUB, left, rite->u.left, tipe );
        rite->u.left = NULL;
        BurnTree( rite );
    } else if( left->class == TN_UNARY && left->op == O_UMINUS ) {
        fold = TGBinary( OP_SUB, rite, left->u.left, tipe );
        left->u.left = NULL;
        BurnTree( left );
    }
    return( fold );
}


static  tn      Halve( tn left, type_def *tipe )
/**********************************************/
{
#define ONE_HALF "0.5"
    char        *value;

    value = ONE_HALF;
    return( TGBinary( OP_MUL, left,
                      TGConst( CFCnvSF( value, value + sizeof( ONE_HALF ) - 1 ), tipe ),
                      tipe ) );
}

extern  tn      FoldPow( tn left, tn rite, type_def *tipe )
/*********************************************************/
{
    tn          fold;

    fold = NULL;
    if( left->class == TN_UNARY && left->op == OP_SQRT ) {
        fold = Halve( rite, tipe );
        fold = TGBinary( OP_POW, left->u.left, fold, tipe );
        left->u.left = NULL;
        BurnTree( left );
    } else if( left->class == TN_UNARY && left->op == OP_EXP ) {
        left->u.left = TGBinary( OP_MUL, left->u.left, rite, tipe );
        fold = left;
    } else if( left->class == TN_BINARY && left->op == OP_POW ) {
        left->rite = TGBinary( OP_MUL, left->rite, rite, tipe );
        fold = left;
    }
    return( fold );
}


extern  tn      FoldAnd( tn left, tn rite, type_def *tipe )
/*********************************************************/
{
    tn          fold;
    cfloat      *rv;
    cfloat      *lv;

    if( left->class == TN_CONS ) {
        fold = left;
        left = rite;
        rite = fold;
    }
    fold = NULL;
    if( left->class == TN_CONS ) {
        lv = left->u.name->c.value;
        rv = rite->u.name->c.value;
        if( CFIs32( lv ) && CFIs32( rv ) ) {
            unsigned_32     and;

            and = CFConvertByType( rv, tipe ) & CFConvertByType( lv, tipe );
            fold = IntToType( and, tipe );
            BurnTree( left );
            BurnTree( rite );
        } else if( CFIs64( lv ) && CFIs64( rv ) ) {
            unsigned_64     and;
            unsigned_64     li;
            unsigned_64     ri;

            li = CFGetInteger64Value( lv );
            ri = CFGetInteger64Value( rv );

            U64And( &li, &ri, &and );
            fold = Int64ToType( and, tipe );
            BurnTree( left );
            BurnTree( rite );
        }
    } else if( rite->class == TN_CONS ) {
        rv = rite->u.name->c.value;
        /* For any X: X & 0 = 0, and X & ~0 = X */
        if( CFTest( rv ) == 0 ) {
            left = TGTrash( left );
            fold = TGBinary( O_COMMA, left, IntToType( 0, tipe ), tipe );
            BurnTree( rite );
        } else if( !HasBigConst( tipe ) && rite->u.name->c.int_value == -1 ) {
            fold = TGConvert( left, tipe );
            BurnTree( rite );
        }
    }
    return( fold );
}


extern  tn      FoldOr( tn left, tn rite, type_def *tipe )
/********************************************************/
{
    tn          fold;
    cfloat      *rv;
    cfloat      *lv;

    if( left->class == TN_CONS ) {
        fold = left;
        left = rite;
        rite = fold;
    }
    fold = NULL;
    if( left->class == TN_CONS ) {
        lv = left->u.name->c.value;
        rv = rite->u.name->c.value;
        if( CFIs32( lv ) && CFIs32( rv ) ) {
            unsigned_32     or;

            or = CFConvertByType( rv, tipe ) | CFConvertByType( lv, tipe );
            fold = IntToType( or, tipe );
            BurnTree( left );
            BurnTree( rite );
        } else if( CFIs64( lv ) && CFIs64( rv ) ) {
            unsigned_64     or;
            unsigned_64     li;
            unsigned_64     ri;

            li = CFGetInteger64Value( lv );
            ri = CFGetInteger64Value( rv );

            U64Or( &li, &ri, &or );
            fold = Int64ToType( or, tipe );
            BurnTree( left );
            BurnTree( rite );
        }
    } else if( rite->class == TN_CONS ) {
        rv = rite->u.name->c.value;
        /* For any X: X | 0 = X, and X | ~0 = ~0 */
        if( CFTest( rv ) == 0 ) {
            fold = TGConvert( left, tipe );
            BurnTree( rite );
        } else if( !HasBigConst( tipe ) && rite->u.name->c.int_value == -1 ) {
            left = TGTrash( left );
            fold = TGBinary( O_COMMA, left, IntToType( -1, tipe ), tipe );
            BurnTree( rite );
        }
    }
    return( fold );
}


extern  tn      FoldXor( tn left, tn rite, type_def *tipe )
/*********************************************************/
{
    tn          fold;
    cfloat      *rv;
    cfloat      *lv;

    if( left->class == TN_CONS ) {
        fold = left;
        left = rite;
        rite = fold;
    }
    fold = NULL;
    if( left->class == TN_CONS ) {
        lv = left->u.name->c.value;
        rv = rite->u.name->c.value;
        if( CFIs32( lv ) && CFIs32( rv ) ) {
            unsigned_32     li;
            unsigned_32     ri;

            li = CFConvertByType( lv, tipe );
            ri = CFConvertByType( rv, tipe );
            ri = li ^ ri;
            fold = IntToType( ri, tipe );
            BurnTree( left );
            BurnTree( rite );
        } else if( CFIs64( lv ) && CFIs64( rv ) ) {
            unsigned_64     xor;
            unsigned_64     li;
            unsigned_64     ri;

            li = CFGetInteger64Value( lv );
            ri = CFGetInteger64Value( rv );

            U64Xor( &li, &ri, &xor );
            fold = Int64ToType( xor, tipe );
            BurnTree( left );
            BurnTree( rite );
        }
    } else if( rite->class == TN_CONS ) {
        rv = rite->u.name->c.value;
        /* For any X: X ^ 0 = X, and X ^ ~0 = ~X */
        if( CFTest( rv ) == 0 ) {
            fold = TGConvert( left, tipe );
            BurnTree( rite );
        } else if( !HasBigConst( tipe ) && rite->u.name->c.int_value == -1 ) {
            fold = TGUnary( O_COMPLEMENT, left, tipe );
            BurnTree( rite );
        }
    }
    return( fold );
}


extern  tn      FoldRShift( tn left, tn rite, type_def *tipe )
/************************************************************/
{
    tn          fold;
    cfloat      *rv;
    cfloat      *lv;
    signed_32   ri;

    fold = NULL;
    if( rite->class == TN_CONS ) {
        rv = rite->u.name->c.value;
        ri = CFConvertByType( rv, tipe );
        if( left->class == TN_CONS ) {
            bool    done = FALSE;

            if( ri >= (tipe->length * 8) ) {
                if( tipe->attr & TYPE_SIGNED ) {
                    // For signed shifts, reduce the shift amount and
                    // then do the math
                    ri = (tipe->length * 8) - 1;
                } else {
                    fold = IntToType( 0, tipe );
                    done = TRUE;
                }
            }
            if( !done ) {
                lv = left->u.name->c.value;
                if( !HasBigConst( tipe ) && CFIs32( lv ) && CFIs32( rv ) ) {
                    signed_32       li;
                    unsigned_32     shft;

                    li = CFConvertByType( lv, tipe );
                    if( tipe->attr & TYPE_SIGNED ) {
                        shft = li >> ri;
                    } else {
                        shft = (unsigned_32)li >> (unsigned_32)ri;
                    }
                    fold = IntToType( shft, tipe );
                } else if( CFIs64( lv ) && CFIs64( rv ) ) {
                    signed_64       rsh;
                    signed_64       li;

                    li = CFGetInteger64Value( lv );

                    U64ShiftR( &li, ri, &rsh );
                    fold = Int64ToType( rsh, tipe );

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?