dbgexpr4.c

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

C
1,355
字号
/****************************************************************************
*
*                            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:  Debugger expression handling, Part IV (Arithmetic).
*
****************************************************************************/


#include <string.h>
#include "dbglit.h"
#include "dbgdefn.h"
#include "dbgtoken.h"
#include "dbgstk.h"
#include "dbgerr.h"
#include "dbgmem.h"
#include "dbgtoggl.h"
#include "dbgitem.h"
#include "dbgtback.h"
#include "dbgri.h"
#include "ldsupp.h"
#include "mad.h"
#include "i64.h"


extern void             BinOp( stack_entry *, stack_entry * );
extern void             AddOp( stack_entry *, stack_entry * );
extern address          AddrAdd( address, long );
extern int              AddrComp( address, address );
extern long             AddrDiff( address, address );
extern bool             NameResolve( stack_entry *, bool );
extern void             SymResolve( stack_entry *entry );
extern void             RValue( stack_entry * );
extern void             LRValue( stack_entry * );
extern void             LValue( stack_entry * );
extern void             ExprResolve( stack_entry * );
extern void             ConvertTo( stack_entry *, type_kind, type_modifier, unsigned );
extern void             ClassifyEntry( stack_entry *, type_info * );
extern bool             ClassifyType( location_context *, type_handle *, type_info * );
extern void             LclLValue( stack_entry * );
extern void             FreezeRegs( void );
extern bool             PerformCall( address, bool, unsigned int );
extern void             UnFreezeRegs( void );
extern void             SetRegSP( address );
extern void             CreateEntry( void );
extern void             DeleteEntry( stack_entry * );
extern stack_entry      *StkEntry( int );
extern void             MoveSP( int );
extern void             SwapStack( int );
extern char             *DupStringEntry( char *, unsigned long );
extern void             PushType( type_handle * );
extern void             FreePgmStack( bool );
extern void             RtnRetValSetup( sym_handle *, unsigned long, address * );
extern void             RtnRetValGet( sym_handle *, unsigned long, address * );
extern unsigned         ToItem( stack_entry *, item_mach * );
extern void             CombineEntries( stack_entry *, stack_entry *, stack_entry * );
extern void             PushAddr( address );
extern void             MoveTH( stack_entry *, stack_entry * );
extern bool             CreateSym( lookup_item *, type_info * );
extern dip_status       LocationAssign( location_list *, location_list *, unsigned long, bool );
extern void             LocationCreate( location_list *, location_type, void * );
extern void             LocationAdd( location_list *, unsigned long );
extern void             ExprSymbol( stack_entry *, sym_handle * );
extern void             CreateLC( stack_entry * );
extern void             MoveLC( stack_entry *, stack_entry * );
extern address          DefAddrSpaceForAddr( address );
extern address          GetRegSP( void );
extern void             SetRegSP( address );
extern void             ExprSetAddrInfo( stack_entry *, bool );
extern void             AddrFix( address * );
extern void             PushLocation( location_list *, type_info * );
extern unsigned         DefaultSize( default_kind );
extern void             GetMADTypeDefaultAt( address, mad_type_kind, mad_type_info * );

extern stack_entry      *ExprSP;
extern unsigned         NestedCallLevel;
extern int              PgmStackUsage[ MAX_NESTED_CALL ];
extern address          NilAddr;


/*
 * DoPlus - add two stack entries
 */

void DoPlus( void )
{
    stack_entry *left;

    left = StkEntry( 1 );
    LRValue( left );
    RValue( ExprSP );
    switch( ExprSP->info.kind ) {
    case TK_POINTER:
    case TK_ADDRESS:
        /* get the pointer as the left operand */
        left = ExprSP;
        SwapStack( 1 );
    }
    AddOp( left, ExprSP );
    switch( left->info.kind ) {
    case TK_BOOL:
    case TK_ENUM:
    case TK_CHAR:
    case TK_INTEGER:
        U64Add( &left->v.uint, &ExprSP->v.uint, &left->v.uint );
        break;
    case TK_POINTER:
    case TK_ADDRESS:
        switch( ExprSP->info.kind ) {
        case TK_BOOL:
        case TK_ENUM:
        case TK_CHAR:
        case TK_INTEGER:
            break;
        default:
            Error( ERR_NONE, LIT( ERR_ILL_TYPE ) );
        }
        if( (left->info.modifier & TM_MOD_MASK) == TM_NEAR ) {
            //NYI: 64 bit offsets
            left->v.addr.mach.offset += U32FetchTrunc( ExprSP->v.uint );
        } else {
            //NYI: 64 bit offsets
            left->v.addr = AddrAdd( left->v.addr, U32FetchTrunc( ExprSP->v.uint ) );
        }
        break;
    case TK_REAL:
        LDAdd( &left->v.real, &ExprSP->v.real, &left->v.real );
        break;
    case TK_COMPLEX:
        LDAdd( &left->v.cmplx.re, &ExprSP->v.cmplx.re, &left->v.cmplx.re );
        LDAdd( &left->v.cmplx.im, &ExprSP->v.cmplx.im, &left->v.cmplx.im );
        break;
    default:
        Error( ERR_NONE, LIT( ERR_ILL_TYPE ) );
        break;
    }
    CombineEntries( left, left, ExprSP );
}


/*
 * DoMinus - subtract two stack entries
 */

void DoMinus( void )
{
    stack_entry *left;

    left = StkEntry( 1 );
    LRValue( left );
    RValue( ExprSP );
    AddOp( left, ExprSP );
    switch( left->info.kind ) {
    case TK_BOOL:
    case TK_ENUM:
    case TK_CHAR:
    case TK_INTEGER:
        U64Sub( &left->v.uint, &ExprSP->v.uint, &left->v.uint );
        left->info.modifier = TM_SIGNED;
        break;
    case TK_POINTER:
    case TK_ADDRESS:
        switch( ExprSP->info.kind ) {
        case TK_BOOL:
        case TK_CHAR:
        case TK_ENUM:
        case TK_INTEGER:
            //NYI: 64 bit offsets
            left->v.addr = AddrAdd( left->v.addr, -U32FetchTrunc( ExprSP->v.uint ) );
            break;
        case TK_POINTER:
        case TK_ADDRESS:
            I32ToI64( AddrDiff( left->v.addr, ExprSP->v.addr ), &left->v.sint );
            left->info.kind = TK_INTEGER;
            left->info.modifier = TM_SIGNED;
            left->info.size = sizeof( signed_64 );
            left->th = NULL;
            break;
        default:
            Error( ERR_NONE, LIT( ERR_ILL_TYPE ) );
        }
        break;
    case TK_REAL:
        LDSub( &left->v.real, &ExprSP->v.real, &left->v.real );
        break;
    case TK_COMPLEX:
        LDSub( &left->v.cmplx.re, &ExprSP->v.cmplx.re, &left->v.cmplx.re );
        LDSub( &left->v.cmplx.im, &ExprSP->v.cmplx.im, &left->v.cmplx.im );
        break;
    default:
        Error( ERR_NONE, LIT( ERR_ILL_TYPE ) );
        break;
    }
    CombineEntries( left, left, ExprSP );
}


/*
 * DoMul - multiply two stack entries
 */

void DoMul( void )
{
    stack_entry *left;
    xreal       re, im, t1, t2;

    left = StkEntry( 1 );
    BinOp( left, ExprSP );
    switch( left->info.kind ) {
    case TK_BOOL:
    case TK_ENUM:
    case TK_CHAR:
    case TK_INTEGER:
        U64Mul( &left->v.uint, &ExprSP->v.uint, &left->v.uint );
        break;
    case TK_REAL:
        LDMul( &left->v.real, &ExprSP->v.real, &left->v.real );
        break;
    case TK_COMPLEX:
        /*  (a,b) * (c,d) = (ac-bd,ad+bc)   */
        LDMul( &left->v.cmplx.re, &ExprSP->v.cmplx.re, &t1 );
        LDMul( &left->v.cmplx.im, &ExprSP->v.cmplx.im, &t2 );
        LDSub( &t1, &t2, &re );
        LDMul( &left->v.cmplx.re, &ExprSP->v.cmplx.im, &t1 );
        LDMul( &left->v.cmplx.im, &ExprSP->v.cmplx.re, &t2 );
        LDAdd( &t1, &t2, &im );
        left->v.cmplx.re = re;
        left->v.cmplx.im = im;
        break;
    default:
        Error( ERR_NONE, LIT( ERR_ILL_TYPE ) );
        break;
    }
    CombineEntries( left, left, ExprSP );
}


/*
 * DoDiv - divide two stack entries
 */

void DoDiv( void )
{
    stack_entry *left;
    xreal       re, im, mag, t1, t2;

    left = StkEntry( 1 );
    BinOp( left, ExprSP );
    switch( left->info.kind ) {
    case TK_BOOL:
    case TK_ENUM:
    case TK_CHAR:
    case TK_INTEGER:
        if( U64Test( &ExprSP->v.uint ) == 0 ) {
            Error( ERR_NONE, LIT( ERR_ZERO_DIV ) );
        }
        if( (left->info.modifier & TM_MOD_MASK) == TM_UNSIGNED ) {
            U64Div( &left->v.uint, &ExprSP->v.uint, &left->v.uint, NULL );
        } else {
            I64Div( &left->v.sint, &ExprSP->v.sint, &left->v.sint, NULL );
        }
        break;
    case TK_REAL:
        DToLD( 0.0, &t1 );
        if( LDCmp( &ExprSP->v.real, &t1 ) == 0 ) {
            Error( ERR_NONE, LIT( ERR_ZERO_DIV ) );
        }
        LDDiv( &left->v.real, &ExprSP->v.real, &left->v.real );
        break;
    case TK_COMPLEX:
        DToLD( 0.0, &t1 );
        if( LDCmp( &ExprSP->v.cmplx.re, &t1 ) == 0
         && LDCmp( &ExprSP->v.cmplx.im, &t1 ) == 0 ) {
            Error( ERR_NONE, LIT( ERR_ZERO_DIV ) );
        }
        /*   (a,b)/(c,d) = (ac+bd,bc-ad) / (c^2+d^2)     */
        LDMul( &ExprSP->v.cmplx.re, &ExprSP->v.cmplx.re, &t1 );
        LDMul( &ExprSP->v.cmplx.im, &ExprSP->v.cmplx.im, &t2 );
        LDAdd( &t1, &t2, &mag );

        LDMul( &left->v.cmplx.re, &ExprSP->v.cmplx.re, &t1 );
        LDMul( &left->v.cmplx.im, &ExprSP->v.cmplx.im, &t2 );
        LDAdd( &t1, &t2, &re );

        LDMul( &left->v.cmplx.im, &ExprSP->v.cmplx.re, &t1 );
        LDMul( &left->v.cmplx.re, &ExprSP->v.cmplx.im, &t2 );
        LDSub( &t1, &t2, &im );

        LDDiv( &re, &mag, &left->v.cmplx.re );
        LDDiv( &im, &mag, &left->v.cmplx.im );
        break;
    default:
        Error( ERR_NONE, LIT( ERR_ILL_TYPE ) );
        break;
    }
    CombineEntries( left, left, ExprSP );
}


/*
 * DoMod - calculate modulus of two stack entries
 */

void DoMod( void )
{
    stack_entry *left;
    union {
        signed_64       s;
        unsigned_64     u;
    }   dummy;

    left = StkEntry( 1 );
    BinOp( left, ExprSP );
    switch( left->info.kind ) {
    case TK_BOOL:
    case TK_ENUM:
    case TK_CHAR:
    case TK_INTEGER:
        if( U64Test( &ExprSP->v.uint ) == 0 ) {
            Error( ERR_NONE, LIT( ERR_ZERO_MOD ) );
        }
        if( (left->info.modifier & TM_MOD_MASK) == TM_UNSIGNED ) {
            U64Div( &left->v.uint, &ExprSP->v.uint, &dummy.u, &left->v.uint );
        } else {
            I64Div( &left->v.sint, &ExprSP->v.sint, &dummy.s, &left->v.sint );
        }
        break;
    default:
        Error( ERR_NONE, LIT( ERR_ILL_TYPE ) );
        break;
    }
    CombineEntries( left, left, ExprSP );
}


/*
 * DoAnd - AND two stack entries
 */

void DoAnd( void )
{
    stack_entry *left;

    left = StkEntry( 1 );
    BinOp( left, ExprSP );
    switch( left->info.kind ) {
    case TK_BOOL:
    case TK_ENUM:
    case TK_CHAR:
    case TK_INTEGER:
        U64And( &left->v.uint, &ExprSP->v.uint, &left->v.uint );
        break;
    default:
        Error( ERR_NONE, LIT( ERR_ILL_TYPE ) );
        break;
    }
    CombineEntries( left, left, ExprSP );
}


/*
 * DoOr - OR two stack entries
 */

void DoOr( void )
{
    stack_entry *left;

    left = StkEntry( 1 );
    BinOp( left, ExprSP );
    switch( left->info.kind ) {
    case TK_BOOL:
    case TK_ENUM:
    case TK_CHAR:
    case TK_INTEGER:
        U64Or( &left->v.uint, &ExprSP->v.uint, &left->v.uint );
        break;
    default:
        Error( ERR_NONE, LIT( ERR_ILL_TYPE ) );
        break;
    }
    CombineEntries( left, left, ExprSP );
}


/*
 * DoXor - XOR two stack entries
 */

void DoXor( void )
{
    stack_entry *left;

    left = StkEntry( 1 );
    BinOp( left, ExprSP );
    switch( left->info.kind ) {
    case TK_BOOL:
    case TK_ENUM:
    case TK_CHAR:
    case TK_INTEGER:
        U64Xor( &left->v.uint, &ExprSP->v.uint, &left->v.uint );
        break;
    default:
        Error( ERR_NONE, LIT( ERR_ILL_TYPE ) );
        break;
    }
    CombineEntries( left, left, ExprSP );
}


/*
 * DoShift - shift a stack entry left or right
 */

void DoShift( void )
{
    stack_entry *left;
    int          shift;

    left = StkEntry( 1 );
    RValue( ExprSP );
    ConvertTo( ExprSP, TK_INTEGER, TM_SIGNED, 0 );
    shift = I32FetchTrunc( ExprSP->v.sint );
    RValue( left );
    switch( left->info.kind ) {
    case TK_BOOL:
    case TK_ENUM:
    case TK_CHAR:
    case TK_INTEGER:
        if( shift >= 0 ) {

⌨️ 快捷键说明

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