?? cmath2.c
字號:
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 + -