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