tree.c

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

C
2,199
字号
/****************************************************************************
*
*                            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:  Functions to manipulate the expression tree.
*
****************************************************************************/


#include "standard.h"
#include "sysmacro.h"
#include "coderep.h"
#include "addrname.h"
#include "model.h"
#include "cgdefs.h"
#include "procdef.h"
#include "tree.h"
#include "hostsys.h"
#include "zoiks.h"
#include "opcodes.h"
#include "freelist.h"
#include "cfloat.h"
#include "targsys.h"
#include "cgaux.h"
#define BY_CG
#include "feprotos.h"
#include "cgprotos.h"
#ifndef NDEBUG
    #include "echoapi.h"
#endif

#include "addrfold.h"
#include "bgcall.h"
#include "bldcall.h"
#include "bldins.h"
#include "blips.h"
#include "data.h"
#include "display.h"
#include "foldins.h"
#include "inline.h"
#include "makeaddr.h"
#include "namelist.h"
#include "optask.h"
#include "patch.h"
#include "rgtbl.h"
#include "stack.h"
#include "treeprot.h"
#include "treeconv.h"
#include "treefold.h"
#include "typemap.h"
#include "types.h"
#include "i64.h"

#if _TARGET & ( _TARG_80386 | _TARG_IAPX86 )
    #include "i86segs.h"
#endif

static  void    FreeTreeNode( tn node );
static  void    Control( cg_op op, tn node, label_handle lbl, bool gen );

static  pointer TreeFrl;

static type_class_def BinMat[] = {
/*********************************
    What is the result type of a binary operation
*/
/*  U1 I1 U2 I2 U4 I4 U8 I8 CP PT FS FD FL*/
    U1,U1,U2,I2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* U1*/
    U1,I1,U2,I2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* I1*/
    U2,U2,U2,U2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* U2*/
    I2,I2,U2,I2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* I2*/
    U4,U4,U4,U4,U4,U4,U8,I8,CP,PT,FS,FD,FL,/* U4*/
    I4,I4,I4,I4,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* I4*/
    U8,U8,U8,U8,U8,U8,U8,U8,CP,PT,FD,FD,FL,/* U8*/
    I8,I8,I8,I8,I8,I8,U8,I8,CP,PT,FD,FD,FL,/* I8*/
    CP,CP,CP,CP,CP,CP,CP,CP,CP,PT,ER,ER,ER,/* CP*/
    PT,PT,PT,PT,PT,PT,PT,PT,PT,PT,ER,ER,ER,/* PT*/
    FS,FS,FS,FS,FS,FS,FD,FD,ER,ER,FS,FD,FL,/* FS*/
    FD,FD,FD,FD,FD,FD,FD,FD,ER,ER,FD,FD,FL,/* FD*/
    FL,FL,FL,FL,FL,FL,FL,FL,ER,ER,FL,FL,FL /* FL*/
};

static type_class_def SubMat[] = {
/*********************************
    what is the result type of a subtraction
*/
/*  U1 I1 U2 I2 U4 I4 U8 I8 CP PT FS FD FL*/
    U1,U1,U2,I2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* U1*/
    U1,I1,U2,I2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* I1*/
    U2,U2,U2,U2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* U2*/
    I2,I2,U2,I2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* I2*/
    U4,U4,U4,U4,U4,U4,U8,I8,CP,PT,FS,FD,FL,/* U4*/
    I4,I4,I4,I4,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* I4*/
    U8,U8,U8,U8,U8,U8,U8,U8,CP,PT,FD,FD,FL,/* U8*/
    I8,I8,I8,I8,I8,I8,U8,I8,CP,PT,FD,FD,FL,/* I8*/
    CP,CP,CP,CP,CP,CP,CP,CP,XX,PT,ER,ER,ER,/* CP*/
    PT,PT,PT,PT,PT,PT,PT,PT,PT,XX,ER,ER,ER,/* PT*/
    FS,FS,FS,FS,FS,FS,FD,FD,ER,ER,FS,FD,FL,/* FS*/
    FD,FD,FD,FD,FD,FD,FD,FD,ER,ER,FD,FD,FL,/* FD*/
    FL,FL,FL,FL,FL,FL,FL,FL,ER,ER,FL,FL,FL,/* FL*/
};

/*
    Routines TGxxxx build up the expression trees. TNxxx tear them down.
*/

static  tn  NewTreeNode( void )
/******************************
    gimme a new tree node
*/
{
    tn  new;

    new = AllocFrl( &TreeFrl, sizeof( either_tree_node ) );
    new->base = NULL;
    new->alignment = 0;
#ifndef NDEBUG
    new->useinfo.hdltype = NO_HANDLE;
    new->useinfo.used = 0;
#endif
    return( new );
}


extern  tn  TGLeaf( an addr )
/****************************
    create a leaf node for "addr"
*/
{
    tn  node;

    node = NewTreeNode();
    node->op = O_NOP;
    node->u.addr = addr;
    node->rite = NULL;
    node->kids = 0;
    node->flags = TF_USED;
    node->tipe = addr->tipe;
    node->class = TN_LEAF;
    if( addr->format == NF_BOOL ) {
        node->tipe = TypeBoolean;
    } else if( addr->format == NF_CONS ) {
        node->class = TN_CONS;
        node->u.name = addr->u.name;
        BGDone( addr );
    }
    return( node );
}


extern  btn TGBitMask( tn left, byte start, byte len, type_def *tipe )
/*********************************************************************
    return a tree node for bits "start" for "len" selected from "left"
    whose type is "tipe".  Takes and yields an lvalue.
*/
{
    btn new;

    new = (btn)NewTreeNode();
    new->u.left = left;
    new->tipe = tipe;
    new->flags = TF_USED;
#if _TARGET & _TARG_370
    new->start = tipe->length*8 - start - len;
#else
    new->start = start;
#endif
    new->len = len;
    new->is_signed = FALSE;
    new->kids = left->kids + 1;
    new->class = TN_BIT_LVALUE;
#ifndef NDEBUG
    new->useinfo.hdltype = NO_HANDLE;
    new->useinfo.used = 0;
#endif
    return( new );
}


extern  tn  TGNode( tn_class class, cg_op op,
            tn left, tn rite, type_def *tipe )
/*********************************************
    create a general node
*/
{
    tn  node;

    node = NewTreeNode();
    node->class = class;
    node->op = op;
    node->u.left = left;
    node->rite = rite;
    node->tipe = tipe;
    node->flags = TF_USED;
    node->kids = 0;
    if( rite != NULL && class != TN_PARM ) {
        node->kids += rite->kids + 1;
    }
    if( left != NULL ) {
        node->kids  += left->kids + 1;
        node->flags |= TF_HAS_LEFT;
    }
    return( node );
}



extern  tn  TGWarp( tn before, label_handle label, tn after )
/************************************************************
    evaluate "before", call label "label" and yield value "after".
*/
{
    tn  result;

    result = TGNode( TN_COLON, O_NOP, NULL, before, after->tipe );
    result->u.handle = label;
    result = TGNode( TN_WARP, O_NOP, result, after, after->tipe );
    return( result );
}

extern  tn  TGHandle( void *ptr )
/********************************
    make a handle node - this is a leaf which holds a ptr
*/
{
    tn  node;

    node = NewTreeNode();
    node->tipe = TypeAddress( T_DEFAULT );
    node->class = TN_HANDLE;
    node->op = O_NOP;
    node->u.handle = ptr;
    return( node );
}

extern  tn  TGCallback( cg_callback rtn, callback_handle ptr )
/*************************************************************
    make a special callback node which will be used to communicate with
    the front end
*/
{
    tn      node;

    node = TGNode( TN_CALLBACK, O_NOP, NULL, TGHandle( ptr ), TypeAddress( T_DEFAULT ) );
    node->u.handle = TGHandle( rtn );
    return( node );
}

static  type_def    *ResultType( tn left, tn rite, type_def *tipe,
                     type_class_def *mat, bool demote_const )
/*****************************************************************
    What is the resulting type of "left" op "rite" given that the front
    end says it should be "tipe" (T_DEFAULT if its not sure).
    "demote_const" is true if we are allowed to do demotion of type even
    if the front end said it wanted a different type.  For example if
    the front end says do ( (char)i & 3 ) as an integer, we know better.
*/
{
    tn              temp;
    type_def        *ltipe;
    type_def        *rtipe;

#if _TARGET & 0
    if( tipe->length < WORD_SIZE ) {
        if( tipe->attr & TYPE_SIGNED ) {
            return( TypeAddress( T_INTEGER ) );
        }
        return( TypeAddress( T_UNSIGNED ) );
    }
#endif
    if( !demote_const && tipe->refno != T_DEFAULT ) return( tipe );
    if( left->class == TN_CONS ) {
        temp = left;
        left = rite;
        rite = temp;
    }
    ltipe = left->tipe;
    if( ltipe == TypeBoolean ) {
        ltipe = TypeInteger;
    }
    rtipe = rite->tipe;
    if( rtipe == TypeBoolean ) {
        rtipe = TypeInteger;
    }
    if( tipe->refno == T_DEFAULT ) {
        return( ClassType( mat[ TypeClass(ltipe)*XX + TypeClass(rtipe) ] ));
    }
#if _TARGET & 0
    return( tipe );
#else
    if( left->tipe->length >= tipe->length ) return( tipe );
    if( rite->class != TN_CONS ) return( tipe );
    if( left->tipe->attr & TYPE_FLOAT ) return( tipe );
    if( rite->tipe->attr & TYPE_FLOAT ) return( tipe );
    if( tipe->length > TypeClassSize[ U4 ] ) return( tipe );
    if( left->tipe->attr & TYPE_SIGNED ) {
       if( !CFSignedSize( rite->u.name->c.value, left->tipe->length ) ) {
           return( tipe );
       }
       if( rite->u.name->c.int_value < 0 ) return( tipe );
       if( !( tipe->attr & TYPE_SIGNED ) ) return( tipe );
    } else {
       if( !CFUnSignedSize( rite->u.name->c.value, left->tipe->length ) )  {
           return( tipe );
       }
    }
    return( left->tipe );
#endif
}

#if _TARGET & ( _TARG_80386 | _TARG_IAPX86 )
static bool RHSLongPointer( tn rite )
{
    if( rite->class == TN_LEAF && rite->u.addr->format == NF_ADDR ) {
        switch( rite->u.addr->class ) {
        case CL_ADDR_GLOBAL:
        case CL_ADDR_TEMP:
            return( TRUE );
        default:
            break;
        }
    } else {
        switch( rite->tipe->refno ) {
        case T_LONG_POINTER:
        case T_HUGE_POINTER:
        case T_LONG_CODE_PTR:
            return( TRUE );
            break;
        }
    }
    return( FALSE );
}
#endif


extern  tn  TGCompare(  cg_op op,  tn left,  tn rite,  type_def  *tipe )
/***********************************************************************
    build a relational operator node
*/
{
    tn      new;
    tn_btn  left_tn_btn;
    bool    can_demote;

    can_demote = TRUE;
#if _TARGET & _TARG_AXP
    // FIXME: bad assumption being covered here
    if( tipe->length < 4 ) {
        tipe = TypeAddress( T_INTEGER );
        can_demote = FALSE;
    }
#endif
    if( ( left->tipe == rite->tipe )
        && ( left->tipe != TypeBoolean )
        && ( ( left->tipe->attr & ~TYPE_SIGNED ) == ( tipe->attr & ~TYPE_SIGNED ) ) ) {
        tipe = left->tipe;
    } else {
        tipe = ResultType( left, rite, tipe, BinMat, can_demote );
    }
    left = TGConvert( left, tipe );
    rite = TGConvert( rite, tipe );
    new = FoldCompare( op, left, rite, tipe );
    if( new != NULL ) return( new );
    left_tn_btn.t = left;
    new = FoldBitCompare( op, left_tn_btn, rite );
    if( new != NULL ) return( new );
    new = FoldPostGetsCompare( op, left, rite, tipe );
    if( new != NULL ) return( new );
    new = TGNode( TN_COMPARE, op, left, rite, TypeBoolean );
    return( new );
}


static  an  Int( unsigned_32 num )
/*********************************
    return an address name for an integer
*/
{
    return( BGInteger( num, TypeInteger ) );
}


static  an  Int64( unsigned_64 num )
/***********************************
    return an address name for a 64-bit integer
*/
{
    return( BGInt64( num, TypeLongLongInteger ) );
}

extern  unsigned_32    Mask( btn node )
/**************************************
    return a mask of 1's in the positions a bit field occupies.
*/
{
    unsigned_32     mask;
    uint            len;
    unsigned_32     bit;

    len = node->len;
    mask = 0;
    bit = (unsigned_32)1 << node->start;
    for( ;; ) {
        mask |= bit;
        bit <<= 1;
        if( --len == 0 ) break;
    }
    return( mask );
}


static  unsigned_64    Mask64( btn node )
/****************************************
    like Mask(), only 64-bit
*/
{
    unsigned_64     mask;
    uint            len;

⌨️ 快捷键说明

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