asexpr.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 506 行 · 第 1/2 页

C
506
字号
/****************************************************************************
*
*                            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 "as.h"

static expr_tree *etAlloc( et_class type ) {
/*******************************************
    Alloc an expression node of the given
    type. No fields are initialized.
*/
    expr_tree   *node;

    node = MemAlloc( sizeof( expr_tree ) );
    node->type = type;
    return( node );
}

static void etFree( expr_tree *node ) {
/**************************************
    Free an expression node.
*/

    MemFree( node );
}

extern expr_tree *ETReloc( asm_reloc_type rtype, sym_handle sym ) {
/******************************************************************
    Allocate a leaf node for a relocatable constant.
*/
    expr_tree   *node;

    node = etAlloc( ET_RELOCATABLE );
    RELOC_SYMBOL( node ) = sym;
    RELOC_TYPE( node ) = rtype;
    RELOC_DISP( node ) = 0;
    return( node );
}

extern expr_tree *ETNumLabelReloc( asm_reloc_type rtype, int_32 label_num ) {
/****************************************************************************
    Allocate a leaf node for a reference to a numeric label (eg. 2f)
*/
    expr_tree   *node;

    node = etAlloc( ET_UNNAMED_RELOCATABLE );
    RELOC_LABELNUM( node ) = label_num;
    RELOC_TYPE( node ) = rtype;
    RELOC_DISP( node ) = 0;
    return( node );
}

extern expr_tree *ETConst( signed_32 value ) {
/*********************************************
    Allocate a leaf node for an integer constant.
*/
    expr_tree   *node;

    node = etAlloc( ET_CONSTANT );
    CONST_VALUE( node ) = value;
    return( node );
}

extern expr_tree *ETFPConst( double value ) {
/********************************************
    Allocate a leaf node for an floating point constant.
*/
    expr_tree   *node;

    node = etAlloc( ET_FP_CONSTANT );
    FP_CONST_VALUE( node ) = value;
    return( node );
}

extern expr_tree *ETUnary( et_class type, expr_tree *child ) {
/*************************************************************
    Allocate a unary node of the given type.
*/
    expr_tree   *node;

    assert( _IsUnary( type ) );
    node = etAlloc( type );
    UNARY_CHILD( node ) = child;
    return( node );
}

extern expr_tree *ETBinary( et_class type, expr_tree *left, expr_tree *right ) {
/*******************************************************************************
    Allocate a binary node of the given type.
*/
    expr_tree   *node;

    assert( _IsBinary( type ) );
    node = etAlloc( type );
    BINARY_LEFT( node ) = left;
    BINARY_RIGHT( node ) = right;
    return( node );
}

static expr_tree *unaryFold( expr_tree *tree ) {
/***********************************************
    To burn down a unary node, we burn our child and
    replace ourselves with it's value if it turns out
    to be a leaf. Note that NOT and UNARY_MINUS are
    not allowed on a relocatable constant, but we still
    need to check for them and report errors.
*/
    expr_tree   *left;

    assert( _IsUnary( tree->type ) );
    left = ETBurn( UNARY_CHILD( tree ) );
    if( _IsLeaf( left->type ) ) {
        switch( tree->type ) {
        case ET_NOT:
            if( left->type == ET_CONSTANT ) {
                CONST_VALUE( tree ) = ~CONST_VALUE( left );
            } else if( left->type == ET_FP_CONSTANT ) {
                Error( ILLEGAL_UNARY_EXPR );
            } else {    // reloc
                Error( ILLEGAL_UNARY_EXPR );
                // need to house-keep
                RELOC_TARGET( tree ) = RELOC_TARGET( left );
                RELOC_TYPE( tree ) = RELOC_TYPE( left );
                RELOC_DISP( tree ) = ~RELOC_DISP( left );
            }
            tree->type = left->type;
            break;
        case ET_UNARY_MINUS:
            if( left->type == ET_CONSTANT ) {
                CONST_VALUE( tree ) = -CONST_VALUE( left );
            } else if( left->type == ET_FP_CONSTANT ) {
                FP_CONST_VALUE( tree ) = -FP_CONST_VALUE( left );
            } else {
                Error( ILLEGAL_UNARY_EXPR );
                // need to house-keep
                RELOC_TARGET( tree ) = RELOC_TARGET( left );
                RELOC_TYPE( tree ) = RELOC_TYPE( left );
                RELOC_DISP( tree ) = -RELOC_DISP( left );
            }
            tree->type = left->type;
            break;
        case ET_PARENS:
            tree->type = left->type;
            if( left->type == ET_FP_CONSTANT ) {
                FP_CONST_VALUE( tree ) = FP_CONST_VALUE( left );
                break;
            }
            CONST_VALUE( tree ) = CONST_VALUE( left );
            if( left->type == ET_RELOCATABLE || left->type == ET_UNNAMED_RELOCATABLE ) {
                RELOC_TARGET( tree ) = RELOC_TARGET( left );
                RELOC_TYPE( tree ) = RELOC_TYPE( left );
                RELOC_DISP( tree ) = RELOC_DISP( left );
            }
            break;
        default:
            Error( UNEXPECTED_UNARY_CLASS );
        }
        etFree( left );
    }
    return( tree );
}

static expr_tree *binaryFold( expr_tree *tree ) {
/************************************************
    Try and fold a binary node. This routine does
    not even try to handle leafs with relocatable
    consts in them, see relocFold instead.
*/
    expr_tree   *left;
    expr_tree   *right;

    assert( _IsBinary( tree->type ) );
    left = ETBurn( BINARY_LEFT( tree ) );
    right = ETBurn( BINARY_RIGHT( tree ) );
    if( _IsConstant( left->type ) && _IsConstant( right->type ) ) {
        if( left->type == ET_CONSTANT && right->type == ET_CONSTANT ) {
            signed_32   l_val, r_val, result;

            l_val = CONST_VALUE( left );
            r_val = CONST_VALUE( right );
            switch( tree->type ) {
            case ET_TIMES:
                result = l_val * r_val;
                break;
            case ET_DIVIDE:
                result = l_val / r_val;
                break;
            case ET_MOD:
                result = l_val % r_val;
                break;
            case ET_PLUS:
                result = l_val + r_val;
                break;
            case ET_MINUS:
                result = l_val - r_val;
                break;
            case ET_SHIFT_L:
                result = l_val << r_val;
                break;
            case ET_SHIFT_R:
                result = l_val >> r_val;
                break;
            case ET_OR:
                result = l_val | r_val;
                break;
            case ET_XOR:
                result = l_val ^ r_val;
                break;
            case ET_AND:
                result = l_val & r_val;
                break;
            default:
                Error( UNEXPECTED_BINARY_CLASS );
            }
            CONST_VALUE( tree ) = result;
            tree->type = ET_CONSTANT;
        } else {
            double      l_val, r_val, result;

            if( left->type == ET_CONSTANT ) {
                l_val = (double)CONST_VALUE( left );
            } else {
                l_val = FP_CONST_VALUE( left );
            }
            if( right->type == ET_CONSTANT ) {

⌨️ 快捷键说明

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