fold.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,425 行 · 第 1/3 页
C
1,425 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "plusplus.h"
#include <stddef.h>
#include <limits.h>
#include "errdefns.h"
#include "ptree.h"
#include "cgfront.h"
#include "fold.h"
#include "codegen.h"
#include "floatsup.h"
//-------------- Temporary Stubs -------------------------------
#define TWOTO32_STRING "4294967296"
static float_handle TwoTo32
( void )
{
char *p = { TWOTO32_STRING };
return( BFCnvSF( p, p + sizeof( TWOTO32_STRING ) - 1 ) );
}
static
float_handle BFCnvU64F( unsigned_64 val )
{
float_handle t0, t1, t2;
t0 = TwoTo32();
t1 = BFCnvUF( val.u._32[ I64HI32 ] );
t2 = BFMul( t0, t1 );
BFFree( t0 );
BFFree( t1 );
t0 = BFCnvUF( val.u._32[ I64LO32 ] );
t1 = BFAdd( t0, t2 );
BFFree( t0 );
BFFree( t2 );
return t1;
}
static
float_handle BFCnvI64F( signed_64 val )
{
float_handle t0, t1, t2;
t0 = TwoTo32();
t1 = BFCnvIF( val.u._32[ I64HI32 ] );
t2 = BFMul( t0, t1 );
BFFree( t0 );
BFFree( t1 );
if( val.u.sign.v ) {
t0 = BFCnvUF( ( val.u._32[ I64LO32 ] ^ ULONG_MAX ) + 1 );
BFNegate( t0 );
} else {
t0 = BFCnvUF( val.u._32[ I64LO32 ] );
}
t1 = BFAdd( t0, t2 );
BFFree( t0 );
BFFree( t2 );
return t1;
}
static
signed_64 BFCnvF64( float_handle flt )
{
signed_64 result;
float_handle absol, t0, t1, t2, t3;
boolean positive;
int sign = BFSign( flt );
if( 0 == sign ) {
result.u._32[0] = 0;
result.u._32[1] = 0;
return result;
}
positive = TRUE;
absol = flt;
if( sign < 0 ) {
positive = FALSE;
absol = BFCopy( flt );
BFNegate( absol );
}
t0 = TwoTo32();
t1 = BFDiv( flt, t0 );
t3 = BFTrunc( t1 );
BFFree( t1 );
result.u._32[ I64HI32 ] = BFCnvF32( t3 );
BFFree( t3 );
t1 = BFCnvUF( result.u._32[ I64HI32 ] );
t2 = BFMul( t0, t1 );
BFFree( t0 );
BFFree( t1 );
t0 = BFSub( flt, t2 );
BFFree( t2 );
t3 = BFTrunc( t0 );
BFFree( t0 );
result.u._32[ I64LO32 ] = BFCnvF32( t3 );
BFFree( t3 );
if( ! positive ) {
signed_64 neg;
BFFree( absol );
neg = result;
U64Neg( &neg, &result );
}
return result;
}
//--------------------------------------------------------------
target_long FoldSignedRShiftMax( target_long v )
/**********************************************/
{
if( v < 0 ) {
return -1;
}
return 0;
}
static boolean isCondDecor( // TEST IF CONDITIONALLY DECORATED
PTREE node ) // - the expression
{
boolean retn; // - TRUE ==> conditionally decorated
if( NodeIsBinaryOp( node, CO_COMMA ) ) {
node = node->u.subtree[0];
if( node->op == PT_IC ) {
if( node->u.ic.opcode == IC_COND_TRUE
|| node->u.ic.opcode == IC_COND_FALSE ) {
retn = TRUE;
} else {
retn = FALSE;
}
} else {
retn = FALSE;
}
} else {
retn = FALSE;
}
return retn;
}
static PTREE overCondDecor( // BY-PASS CONDITIONAL DECORATION
PTREE expr ) // - expression
{
if( isCondDecor( expr ) ) {
expr = expr->u.subtree[1];
}
return expr;
}
static boolean zero64 // TEST IF 64-BITTER IS ZERO
( signed_64 const *test ) // - value to e tested
{
return test->u._32[0] == 0
&& test->u._32[1] == 0;
}
#define nonZero64( t ) ( ! zero64( t ) )
static boolean zeroConstant( // TEST IF NODE IS ZERO CONSTANT
PTREE expr ) // - the expression
{
PTREE orig;
switch( expr->op ) {
case PT_INT_CONSTANT:
if( NULL == Integral64Type( expr->type ) ) {
return expr->u.int_constant == 0;
} else {
return zero64( &expr->u.int64_constant );
}
case PT_FLOATING_CONSTANT:
{ target_ulong ul_val = BFCnvF32( expr->u.floating_constant );
return 0 == ul_val;
}
case PT_BINARY:
orig = expr;
expr = NodeRemoveCasts( expr );
if( expr == orig ) break;
return( zeroConstant( expr ) );
}
return( FALSE );
}
static boolean nonZeroExpr( // TEST IF NODE IS NON-ZERO EXPRESSION
PTREE expr ) // - the expression
{
PTREE orig;
switch( expr->op ) {
case PT_INT_CONSTANT:
case PT_FLOATING_CONSTANT:
return ! zeroConstant( expr );
case PT_SYMBOL:
/* a symbol r-value has a fetch by now so this PTREE means &name */
return( TRUE );
case PT_BINARY:
orig = expr;
expr = NodeRemoveCasts( expr );
if( expr == orig ) break;
return( nonZeroExpr( expr ) );
}
if( expr->flags & PTF_PTR_NONZERO ) {
return( TRUE );
}
return( FALSE );
}
static boolean notFoldable( // TEST IF NON-FOLDABLE EXPRESSION
PTREE expr ) // - the expression
{
switch( expr->op ) {
case PT_INT_CONSTANT:
case PT_FLOATING_CONSTANT:
return( FALSE );
default :
if( zeroConstant( expr ) ) {
return( FALSE );
} else {
return( TRUE );
}
}
}
PTREE CastIntConstant( PTREE expr, TYPE type, boolean *happened )
{
PTREE new_expr;
target_ulong ul_val;
CPP_FLOAT *dbl_val;
type_id id;
boolean signed_type;
signed_type = SignedIntType( expr->type );
id = TypedefModifierRemove( type )->id;
ul_val = expr->u.uint_constant;
if( NULL == Integral64Type( expr->type ) ) {
switch( id ) {
case TYP_SCHAR:
ul_val = (target_schar) ul_val;
/* fall through */
case TYP_SSHORT:
ul_val = (target_short) ul_val;
/* fall through */
case TYP_SINT:
ul_val = (target_int) ul_val;
/* fall through */
case TYP_SLONG:
ul_val = (target_long) ul_val;
new_expr = PTreeIntConstant( ul_val, id );
break;
case TYP_UCHAR:
ul_val = (target_uchar) ul_val;
/* fall through */
case TYP_USHORT:
ul_val = (target_ushort) ul_val;
/* fall through */
case TYP_UINT:
ul_val = (target_uint) ul_val;
/* fall through */
case TYP_ULONG:
ul_val = (target_ulong) ul_val;
new_expr = PTreeIntConstant( ul_val, id );
break;
case TYP_ULONG64:
case TYP_SLONG64:
if( PT_FLOATING_CONSTANT == expr->op ) {
new_expr = PTreeInt64Constant
( BFCnvF64( expr->u.floating_constant )
, id );
} else {
new_expr = PTreeInt64Constant( expr->u.int64_constant, id );
}
break;
case TYP_POINTER:
case TYP_MEMBER_POINTER:
ul_val = (target_ulong) ul_val;
new_expr = PTreeIntConstant( ul_val, TYP_ULONG );
new_expr->type = type;
break;
case TYP_FLOAT:
#if 0
// these are now identical, with canonical floating point
if( signed_type ) {
flt_val = BFCnvIF( expr->u.int_constant );
} else {
flt_val = BFCnvUF( expr->u.uint_constant );
}
new_expr = PTreeFloatingConstant( flt_val, id );
break;
#endif
case TYP_LONG_DOUBLE:
case TYP_DOUBLE:
if( signed_type ) {
dbl_val = BFCnvIF( expr->u.int_constant );
} else {
dbl_val = BFCnvUF( expr->u.uint_constant );
}
new_expr = PTreeFloatingConstant( dbl_val, id );
break;
case TYP_WCHAR:
ul_val = (target_wchar) ul_val;
new_expr = PTreeIntConstant( ul_val, id );
break;
default:
return( expr );
}
} else {
ul_val = expr->u.int_constant;
switch( id ) {
case TYP_SCHAR:
ul_val = (target_schar) ul_val;
/* fall through */
case TYP_SSHORT:
ul_val = (target_short) ul_val;
/* fall through */
case TYP_SINT:
ul_val = (target_int) ul_val;
/* fall through */
case TYP_SLONG:
ul_val = (target_long) ul_val;
new_expr = PTreeIntConstant( ul_val, id );
break;
case TYP_SLONG64:
case TYP_ULONG64:
new_expr = PTreeInt64Constant( expr->u.int64_constant, id );
break;
case TYP_UCHAR:
ul_val = (target_uchar) ul_val;
/* fall through */
case TYP_USHORT:
ul_val = (target_ushort) ul_val;
/* fall through */
case TYP_UINT:
ul_val = (target_uint) ul_val;
/* fall through */
case TYP_ULONG:
ul_val = (target_ulong) ul_val;
new_expr = PTreeIntConstant( ul_val, id );
break;
case TYP_POINTER:
case TYP_MEMBER_POINTER:
ul_val = (target_ulong) ul_val;
new_expr = PTreeIntConstant( ul_val, TYP_ULONG );
new_expr->type = type;
break;
case TYP_FLOAT:
#if 0
// these are now identical, with canonical floating point
if( signed_type ) {
flt_val = BFCnvI64F( expr->u.int64_constant );
} else {
flt_val = BFCnvU64F( expr->u.uint64_constant );
}
new_expr = PTreeFloatingConstant( flt_val, id );
break;
#endif
case TYP_LONG_DOUBLE:
case TYP_DOUBLE:
if( signed_type ) {
dbl_val = BFCnvI64F( expr->u.int64_constant );
} else {
dbl_val = BFCnvU64F( expr->u.int64_constant );
}
new_expr = PTreeFloatingConstant( dbl_val, id );
break;
case TYP_WCHAR:
ul_val = (target_wchar) ul_val;
new_expr = PTreeIntConstant( ul_val, id );
break;
default:
return( expr );
}
}
*happened = TRUE;
new_expr->flags = expr->flags;
new_expr = PTreeCopySrcLocation( new_expr, expr );
PTreeFree( expr );
return( new_expr );
}
static PTREE castFloatingConstant( PTREE expr, TYPE type, boolean *happened )
{
target_long value;
PTREE new_expr;
type_id id;
id = TypedefModifierRemove( type )->id;
switch( id ) {
case TYP_POINTER:
case TYP_MEMBER_POINTER:
id = TYP_ULONG;
// drops thru
case TYP_SCHAR:
case TYP_SSHORT:
case TYP_SINT:
case TYP_SLONG:
case TYP_UCHAR:
case TYP_USHORT:
case TYP_UINT:
case TYP_ULONG:
case TYP_WCHAR:
value = BFGetLong( &(expr->u.floating_constant) );
new_expr = PTreeIntConstant( (target_ulong) value, id );
new_expr = CastIntConstant( new_expr, type, happened );
break;
case TYP_FLOAT: {
CPP_FLOAT *flt_val;
flt_val = BFCopy( expr->u.floating_constant );
new_expr = PTreeFloatingConstant( flt_val, id );
}
break;
case TYP_LONG_DOUBLE:
case TYP_DOUBLE:
{ CPP_FLOAT *flt_val;
flt_val = BFCopy( expr->u.floating_constant );
new_expr = PTreeFloatingConstant( flt_val, id );
} break;
case TYP_SLONG64:
case TYP_ULONG64:
{ signed_64 val = BFCnvF64( expr->u.floating_constant );
new_expr = PTreeInt64Constant( val, id );
} break;
default:
return( expr );
}
*happened = TRUE;
new_expr = PTreeCopySrcLocation( new_expr, expr );
PTreeFree( expr );
return( new_expr );
}
static PTREE castConstant( PTREE expr, TYPE type, boolean *happened )
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?