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

📄 cmath2.c

📁 Open Watcom 的 C 编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    while( typ->decl_type == TYPE_TYPEDEF )  typ = typ->object;
    if( typ->decl_type == TYPE_POINTER ) {
        return( PointerClass( savtyp ) );
    }
    return( PTR_NOT );               // indicate not a pointer type
}



#define Convert(opnd,opnd_type,result_type)     opnd

//  a <= x <=  b   i.e range of x is between a and b
enum   rel_op {
    REL_EQ,    // x == c
    REL_LT,    // x < c
    REL_LE,    // x <= c
    REL_SIZE
};
enum  case_range {
    CASE_LOW,         // c < a
    CASE_LOW_EQ,      // c == a
    CASE_HIGH,        // c > b
    CASE_HIGH_EQ,     // c == b
    CASE_SIZE
};

typedef enum{
    CMP_VOID    = 0,
    CMP_FALSE   = 1,
    CMP_TRUE    = 2,
}cmp_result;

static char const Meaningless[REL_SIZE][CASE_SIZE] = {
//    c < a      c == a     c >b       c==b
    { CMP_FALSE, CMP_VOID , CMP_FALSE, CMP_VOID },  // x == c
    { CMP_FALSE, CMP_FALSE, CMP_TRUE , CMP_VOID },  // x < c
    { CMP_FALSE, CMP_VOID , CMP_TRUE , CMP_TRUE },  // x <= c
};

#define NumSign( a )   ((a)&0x80)
#define NumBits( a )   ((a)&0x7f)
#define MAXSIZE        (sizeof( long )*8)
static char NumSize( int op_type ){
// return 0 not a num, else number of bits | 0x80 if signed
    char size;

    size = 0;
    switch( op_type ) {
    case TYPE_CHAR:
        size = 0x80;
    case TYPE_UCHAR:
        size |= 8;
        break;
    case TYPE_SHORT:
        size = 0x80;
    case TYPE_USHORT:
        size |= 16;
        break;
    case TYPE_LONG:
        size = 0x80;
    case TYPE_ULONG:
    case TYPE_POINTER:
        size |= 32;
        break;
    case TYPE_INT:
    case TYPE_FIELD:
        size = 0x80;
    case TYPE_UINT:
    case TYPE_UFIELD:
#if TARGET_INT == 2
        size |= 16;
#else
        size |= 32;
#endif
        break;
    }
    return( size );
}

static cmp_result IsMeaninglessCompare( long val, int op1_type, int op2_type, int opr )
{
    long                high;
    long                low;
    enum rel_op         rel;
    enum case_range     range;
    cmp_result          ret;
    int                 result_size;
    char                op1_size;
    char                rev_ret;

    op1_size = NumSize( op1_type );
    if( op1_size == 0 ){
        return( CMP_VOID );
    }
    result_size = NumSize( BinResult[ op1_type ][ op2_type ] );
    if( result_size == 0 ){
        return( CMP_VOID );
    }
    rev_ret = 0;
    switch( opr ){ // mapped rel ops to equivalent cases
    case T_NE:
        rev_ret = 1;
    case T_EQ:
        rel = REL_EQ;
        break;
    case T_GE:
        rev_ret = 1;
    case T_LT:
        rel = REL_LT;
        break;
    case T_GT:
        rev_ret = 1;
    case T_LE:
        rel = REL_LE;
        break;
    }
    if( NumSign(op1_size ) && NumSign(op1_size ) != NumSign(result_size) ){
        if( NumBits( op1_size) < NumBits( result_size ) ){
         // signed promoted to bigger unsigned num gets signed extended
        //  could have two ranges unsigned
            return( CMP_VOID ); //TODO: could check == & !=
        }else if( NumBits( op1_size) == NumBits( result_size ) ){
          // signed promoted to unsigned use unsigned range
          op1_size &= 0x7f;
        }
    }
    if( NumSign( result_size ) == 0 && NumBits( result_size ) == 16 ){
        val &= 0xffff; // num is truncated when compared
    }
    if( NumSign( op1_size ) ){
        low = (long)(0x80000000) >> MAXSIZE-NumBits( op1_size );
        high = ~low;
    }else{
        low = 0;
        high = 0xfffffffful >> MAXSIZE-NumBits( op1_size );
    }
    if( val == low ){
        range = CASE_LOW_EQ;
    }else if( val == high ){
        range = CASE_HIGH_EQ;
    }else if( NumBits( op1_size ) < MAXSIZE ){ // can't be outside range and
        if( val < low ){                       // don't have to do unsigned compare
            range = CASE_LOW;
        }else if( val > high ){
            range = CASE_HIGH;
        }else{
            range = CASE_SIZE;
        }
    }else{
        range = CASE_SIZE;
    }
    if( range != CASE_SIZE ){
        ret = Meaningless[rel][range];
        if( ret != CMP_VOID && rev_ret ){
            if( ret == CMP_FALSE ){
                ret = CMP_TRUE;
            }else{
                ret = CMP_FALSE;
            }
        }
    }else{
        ret = CMP_VOID;
    }
    return( ret );
}

static int CommRelOp( int opr ){
// map opr to commuted oprand equivelent
    switch( opr ){
    case T_NE:  // a != b => b != a
    case T_EQ:
        break;
    case T_GE: // a >= b => b <= a
        opr = T_LE;
        break;
    case T_LT:
        opr = T_GT;
        break;
    case T_GT:
        opr = T_LT;
        break;
    case T_LE:
        opr = T_GE;
        break;
    }
    return( opr );
}

bool IsZero(  TREEPTR tree ){
    bool ret;
    if( tree->op.opr == OPR_PUSHINT && tree->op.long_value == 0 ){
        ret = TRUE;
    }else{
        ret = FALSE;
    }
    return( ret );
}

static TREEPTR BaseConv( TYPEPTR typ1, TREEPTR op2  )
{
    TYPEPTR typ2;
    type_modifiers  typ1_flags, typ2_flags;

    typ2 =  op2->expr_type;
    typ1 = SkipTypeFluff( typ1 ); // skip typedefs go into enums base
    typ2 = SkipTypeFluff( typ2 );
    if( typ1->decl_type == TYPE_POINTER && typ2->decl_type == TYPE_POINTER ){
        typ1_flags = typ1->u.p.decl_flags;
        typ2_flags = typ2->u.p.decl_flags;
        if( ( typ1_flags & FLAG_FAR) && (typ2_flags & FLAG_BASED) ){
            op2 = BasedPtrNode( typ2, op2 );
        }
    }
    return( op2 );
}

static bool IsInt( DATA_TYPE op )
    /*
     * what's target compatible between default int as ret type
     * and a later declaration
     */
{
    bool        ret;

    switch( op ) {
    case TYPE_CHAR:
    case TYPE_UCHAR:
    case TYPE_SHORT:
    case TYPE_USHORT:
    case TYPE_INT:
    case TYPE_LONG:
    case TYPE_LONG64:
    case TYPE_ULONG64:
        ret = TRUE;
        break;
    default:
       ret = FALSE;
    }
    return( ret );
}
TREEPTR RelOp( TREEPTR op1, TOKEN opr, TREEPTR op2 )
{
    TYPEPTR         typ1;
    TYPEPTR         typ2;
    TYPEPTR         cmp_type;
    DATA_TYPE       op1_type, op2_type, result_type;
    TREEPTR         tree;
    cmp_result      cmp_cc;

    FoldExprTree( op1 );   // Needed for meaning less compare
    FoldExprTree( op2 );
    op1 = RValue( op1 );
    op2 = RValue( op2 );
    if( op1->op.opr == OPR_ERROR ) {
        FreeExprTree( op2 );
        return( op1 );
    }
    if( op2->op.opr == OPR_ERROR ) {
        FreeExprTree( op1 );
        return( op2 );
    }
    typ1 = TypeOf( op1 );
    typ2 = TypeOf( op2 );
    if( typ1->decl_type == TYPE_POINTER && typ2->decl_type == TYPE_POINTER  ){
        op2 = BaseConv( typ1, op2 );
        op1 = BaseConv( typ2, op1 );
        typ1 = TypeOf( op1 );
        typ2 = TypeOf( op2 );
    }
    op1_type = DataTypeOf( typ1->decl_type );
    op2_type = DataTypeOf( typ2->decl_type );
    cmp_type = typ1;
    result_type = op1_type;

    /* check for meaningless comparison:  04-feb-91 */
    //TODO this would be a better check maybe in foldtree
    if( !CompFlags.pre_processing ) {            /* 07-feb-89 */
        cmp_cc = CMP_VOID;
        if( op2->op.opr == OPR_PUSHINT ) {
            cmp_cc = IsMeaninglessCompare( op2->op.long_value, op1_type, op2_type, opr );
        }else if( op1->op.opr == OPR_PUSHINT ) {
            cmp_cc = IsMeaninglessCompare( op1->op.long_value, op2_type, op1_type, CommRelOp( opr ) );
        }
        if( cmp_cc != CMP_VOID ){
            int res = cmp_cc == CMP_TRUE;
            CWarn2( WARN_COMPARE_ALWAYS, ERR_COMPARE_ALWAYS, res );
        }
    }
    if( op1_type == TYPE_VOID  ||  op2_type == TYPE_VOID ) {
        ;           /* do nothing, since error has already been given */
    } else if( op1_type == TYPE_POINTER  &&  op2_type == TYPE_POINTER ) {
         CompatiblePtrType( typ1, typ2 );
    } else if( (op1_type == TYPE_POINTER  && IsInt( op2_type ) ) ||
               (op2_type == TYPE_POINTER  && IsInt( op1_type ) ) ){
        /* ok to compare pointer with constant 0 */
        if( opr != T_EQ  &&  opr != T_NE ){
            CWarn1( WARN_POINTER_TYPE_MISMATCH,
                    ERR_POINTER_TYPE_MISMATCH );
        }else if( !( IsZero( op1  )||IsZero( op2) ) ){
            CWarn1( WARN_POINTER_TYPE_MISMATCH,
                    NON_ZERO_CONST );
        }
        if( op2_type == TYPE_POINTER ) {
            cmp_type = typ2;
        }
    } else if( op1_type == TYPE_STRUCT ||
               op1_type == TYPE_UNION  ||
               op2_type == TYPE_STRUCT ||
               op2_type == TYPE_UNION ) {
            CErr1( ERR_INVALID_RELOP_FOR_STRUCT_OR_UNION );
            result_type = ERR;
    } else {
        result_type = BinResult[ op1_type ][ op2_type ];
        if( result_type == ERR ) {                      /* 12-sep-89 */
            CErr1( ERR_TYPE_MISMATCH );
        } else {
            cmp_type = GetType( result_type );
        }
#if 0
        op1 = Convert( op1, op1_type, result_type );
        op2 = Convert( op2, op2_type, result_type );
#endif
    }
    tree = ExprNode( op1, OPR_CMP, op2 );
    if( result_type == ERR ) {
        tree = ErrorNode( tree );
    } else {
        switch( opr ) {
        case T_EQ:      opr = CC_EQ;    break;
        case T_NE:      opr = CC_NE;    break;
        case T_LT:      opr = CC_LT;    break;
        case T_LE:      opr = CC_LE;    break;
        case T_GT:      opr = CC_GT;    break;
        case T_GE:      opr = CC_GE;    break;
        }
        tree->op.cc = opr;
        tree->op.compare_type = cmp_type;
        tree->expr_type = GetType( TYPE_INT );
    }
    return( tree );
}


TREEPTR FlowOp( TREEPTR op1, int opr, TREEPTR op2 )
{
    TREEPTR     tree;

    if( op1->op.opr == OPR_ERROR ) {
        FreeExprTree( op2 );
        return( op1 );
    }
    if( op2->op.opr == OPR_ERROR ) {
        FreeExprTree( op1 );
        return( op2 );
    }
    if( op1->op.opr == OPR_PUSHINT ) {
        if( opr == OPR_OR_OR ) {
            if( op1->op.long_value == 0 ) {
                FreeExprNode( op1 );
                return( op2 );
            }
        } else {        // OPR_AND_AND

⌨️ 快捷键说明

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