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