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