bldins.c

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

C
818
字号
/****************************************************************************
*
*                            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:  Turn expression tree into pseudo-assembly instructions.
*
****************************************************************************/


#include "standard.h"
#include "cgdefs.h"
#include "model.h"
#include "coderep.h"
#include "procdef.h"
#include "sysmacro.h"
#include "opcodes.h"
#include "addrname.h"
#include "memcheck.h"
#include "cfloat.h"
#include "regset.h"
#include "rttable.h"
#include "rtclass.h"
#include "feprotos.h"

#include "addrfold.h"
#include "bldins.h"

extern  void            FPNotStack(name*);
extern  an              MakeConst(pointer,type_def*);
extern  uint            Length(char*);
extern  an              MakeAddrName(cg_class,sym_handle,type_def*);
extern  an              MakeTypeTempAddr(name*,type_def*);
extern  void            GenKillLabel(pointer);
extern  void            GenBlock(int,int);
extern  void            AddTarget(label_handle,bool);
extern  void            Generate(bool);
extern  void            EnLink(label_handle,bool);
extern  label_handle    AskForNewLabel( void );
extern  void            AddIns(instruction*);
extern  instruction     *MakeNop( void );
extern  void            BigLabel( void );
extern  void            BigGoto(int);
extern  bool            TGIsAddress( void );
extern  instruction     *MakeBinary(opcode_defs,name*,name*,name*,type_class_def);
extern  name            *GenIns(an);
extern  type_class_def  TypeClass(type_def*);
extern  an              InsName(instruction*,type_def*);
extern  an              MakePoints(an,type_def*);
extern  void            FixCodePtr(an);
extern  void            NamesCrossBlocks( void );
extern  instruction     *MakeCondition(opcode_defs,name*,name*,int,int,type_class_def);
extern  an              MakeGets(an,an,type_def*);
extern  an              AddrDuplicate(an);
extern  an              AddrCopy(an);
extern  void            AddrFree(an);
extern  an              AddrSave(an);
extern  void            AddrDemote(an);
extern  instruction     *MakeMove(name*,name*,type_class_def);
extern  name            *AllocIntConst(int);
extern  name            *AllocS32Const(signed_32);
extern  name            *AllocS64Const( unsigned_32 low, unsigned_32 high );
extern  name            *AllocU64Const( unsigned_32 low, unsigned_32 high );
extern  instruction     *MakeUnary(opcode_defs,name*,name*,type_class_def);
extern  instruction     *MakeConvert(name*,name*,type_class_def,type_class_def);
extern  instruction     *MakeNary(opcode_defs,name*,name*,name*,type_class_def,type_class_def,int);
extern  instruction     *NewIns(int);
extern  name            *AllocTemp(type_class_def);
extern  bool            BlkTooBig( void );
extern  bool            NeedPtrConvert(an,type_def*);
extern  type_def        *TypeAddress(cg_type );
extern  name            *AllocRegName( hw_reg_set );
extern  name            *AllocMemory(pointer,type_length,cg_class,type_class_def);
extern  hw_reg_set      ReturnAddrReg( void );
extern  hw_reg_set      ScratchReg( void );
extern  hw_reg_set      StackReg( void );
extern  hw_reg_set      VarargsHomePtr( void );
extern  an              RegName( hw_reg_set, type_def *);
extern  label_handle    RTLabel( int );
extern  name            *AllocIndex( name *, name *, type_length, type_class_def );

extern    bool          BlockByBlock;
extern    block         *CurrBlock;
extern    block         *BlockList;
extern    proc_def      *CurrProc;
extern    type_def      *TypeInteger;
extern    type_def      *TypeNone;
extern    bool          HaveCurrBlock;

static  void    BoolFree( bn b );

static  type_def        *LastCmpType;
static  unsigned_32     UnrollValue = 0;

extern  an      BGVarargsBasePtr( type_def *tipe ) {
/**************************************************/

    an                  addr;

    addr = RegName( VarargsHomePtr(), tipe );
    return( addr );
}

extern  an      BGStackValue( type_def *tipe ) {
/**********************************************/

    an                  addr;

    addr = RegName( StackReg(), tipe );
    return( addr );
}

extern  an      BGInteger( signed_32 value, type_def *tipe ) {
/***********************************************************/

    pointer     cf;

    if( tipe->attr & TYPE_SIGNED ) {
        cf = CFCnvI32F( value );
    } else {
        cf = CFCnvU32F( value );
    }
    return( MakeConst( cf, tipe ) );
}

extern  an      BGInt64( signed_64 value, type_def *tipe ) {
/***********************************************************/

    name   *cname;

    if( tipe->attr & TYPE_SIGNED ) {
        cname = AllocS64Const( value.u._32[I64LO32],value.u._32[I64HI32] );
    } else {
        cname = AllocU64Const( value.u._32[I64LO32],value.u._32[I64HI32] );
    }
    return( AddrName( cname, tipe ) );
}

extern  an      BGFloat( char *value, type_def *tipe ) {
/********************************************************/

    return( MakeConst( CFCnvSF( value, value + Length( value ) ), tipe ) );
}


extern  an      BGName( cg_class cl, pointer sym, type_def *tipe ) {
/*******************************************************************/

    return( MakeAddrName( cl, sym, tipe ) );
}


extern  an      BGTempName( name *temp, type_def *tipe ) {
/*************************************************************/

    temp->v.usage |= USE_IN_ANOTHER_BLOCK;
    return( MakeTypeTempAddr( temp, tipe ) );
}


extern  bool    FiniLabel( label_handle lbl, block *blk ) {
/*********************************************************/

    int         i;

    i = blk->targets;
    while( --i >= 0 ) {
        if( blk->edge[ i ].destination == lbl ) {
            blk->edge[ i ].flags |= DEST_LABEL_DIES;
            return( TRUE );
        }
    }
    if( blk->label == lbl ) {
        blk->edge[ 0 ].flags |= BLOCK_LABEL_DIES;
        return( TRUE );
    }
    return( FALSE );
}

extern  void    BGFiniLabel( label_handle lbl ) {
/***********************************************/

    block       *blk;

    if( HaveCurrBlock && FiniLabel( lbl, CurrBlock ) ) return;
    blk = BlockList;
    while( blk != NULL ) {
        if( FiniLabel( lbl, blk ) ) return;
        blk = blk->prev_block;
    }
    GenKillLabel( lbl );
}


extern  bool    NeedConvert( type_def *from, type_def *to ) {
/*********************************************************/

    if( from == to ) return( FALSE );
    if( from->attr & TYPE_FLOAT ) return( TRUE );
    if( to->attr & TYPE_FLOAT ) return( TRUE );
    if( from->length != to->length ) return( TRUE );
#if _TARGET & _TARG_IAPX86
    if( ( to->attr & TYPE_POINTER ) != ( from->attr & TYPE_POINTER )
        && to->length != WORD_SIZE ) return( TRUE ); /* long <=> pointer */
#endif
    return( FALSE );
}


static  cg_name Unary( cg_op op, an left, type_def *tipe ) {
/**********************************************************/

    instruction *ins;
    an          res;

    ins = MakeNary( op, GenIns( left ), NULL, NULL,
                    TypeClass( tipe ), TypeClass( left->tipe ), 1 );
    res = InsName( ins, tipe );
    AddIns( ins );
    BGDone( left );
    return( res );
}


static  an      CnvRnd( an name, type_def *tipe, cg_op op ) {
/***********************************************************/

    if( NeedConvert( name->tipe, tipe ) ) {
        name = Unary( op, name, tipe );
    } else if( name->tipe != tipe ) {
        AddrDemote( name ); /* it's not quite the right type */
    }
    name->tipe = tipe;
    return( name );
}


extern  name        *BGNewTemp( type_def *tipe ) {
/************************************************/

    name        *temp;

    temp = AllocTemp( TypeClass( tipe ) );
    if( temp->n.size == 0 ) {
        temp->n.size = tipe->length;
    }
    return( temp );
}


extern  temp_name       *BGGlobalTemp( type_def *tipe ) {
/*******************************************************/

    name        *temp;

    temp = BGNewTemp( tipe );
    temp->v.usage |= USE_IN_ANOTHER_BLOCK;
    return( &(temp->t) );
}


static  an      FlowOut( bn node, type_def *tipe ) {
/**************************************************/

    name                *temp;
    label_handle        lbl;

    lbl = AskForNewLabel();
    temp = BGNewTemp( tipe );
    temp->v.usage |= USE_IN_ANOTHER_BLOCK;
    AddIns( MakeMove( AllocIntConst( FETrue() ), temp, temp->n.name_class ) );
    *(node->t) = CurrBlock->label;
    GenBlock( JUMP, 1 );
    AddTarget( lbl, FALSE );
    EnLink( AskForNewLabel(), TRUE );
    AddIns( MakeMove( AllocIntConst( 0 ), temp, temp->n.name_class ) );
    *(node->f) = CurrBlock->label;
    GenBlock( JUMP, 1 );
    AddTarget( lbl, FALSE );
    EnLink( lbl, TRUE );
    NamesCrossBlocks();
    BoolFree( node );
    return( AddrName( temp, tipe ) );
}


extern  an      Arithmetic( an name, type_def *tipe ) {
/*****************************************************/

    if( name->format == NF_BOOL ) {
        if( ( tipe->attr & TYPE_FLOAT ) != 0
          || ( tipe->length > TypeInteger->length ) ) {
            name = FlowOut( (bn)name, TypeInteger );
            name = Unary( O_CONVERT, name, tipe );
        } else {
            name = FlowOut( (bn)name, tipe );
        }
    }
    return( name );
}

extern  bn      BGCompare( cg_op op, an left, an rite,
                           label_handle entry, type_def *tipe ) {
/*****************************************************************************/

    bn                  new;
    instruction         *ins;
    name                *newleft;
    name                *newrite;

    LastCmpType = tipe;
    newleft = GenIns( left );
    newrite = GenIns( rite );
    BGDone( left );
    BGDone( rite );
    NamesCrossBlocks();
    ins = MakeCondition( op, newleft, newrite, 0, 1, TypeClass( tipe ) );
    AddIns( ins );
    GenBlock( CONDITIONAL, 2 );
    _Alloc( new, sizeof( bool_node ) );
    AddTarget( NULL, FALSE );
    AddTarget( NULL, FALSE );
    new->format = NF_BOOL;
    new->e = entry;
    new->t = &CurrBlock->edge[ 0 ].destination;
    new->f = &CurrBlock->edge[ 1 ].destination;
    EnLink( AskForNewLabel(), TRUE );
    return( new );
}



extern  bn      Boolean( an node, label_handle entry ) {
/******************************************************/

    if( node->format != NF_BOOL ) {
        node = (an) BGCompare( O_NE, node, BGInteger( 0, node->tipe ),
                           entry, node->tipe );
    }
    return( (bn) node );
}


extern  label_handle    BGGetEntry( void ) {
/************************************/

    return( CurrBlock->label );
}


extern  void    BG3WayControl( an node, label_handle lt,
                               label_handle eq, label_handle gt ) {
/*****************************************************************/

    instruction         *ins;
    name                *op;
    label_handle        lbl;
    type_class_def      class;

    node = Arithmetic( node, node->tipe );
    class = TypeClass( node->tipe );
    NamesCrossBlocks();
    op = GenIns( node );
    BGDone( node );
    ins = NULL;
    #if _TARGET & _TARG_80386
        if( class == FS ) {
            ins = MakeCondition( OP_BIT_TEST_FALSE, op,
                                 AllocS32Const( 0x7FFFFFFFL ),
                                 0, 1, SW );
        }
    #endif
    if( ins == NULL ) {
        ins = MakeCondition( OP_CMP_EQUAL, op, AllocIntConst( 0 ), 0, 1, class );
    }
    AddIns( ins );
    GenBlock( CONDITIONAL, 2 );
    AddTarget( eq, FALSE );
    lbl = AskForNewLabel();
    AddTarget( lbl, FALSE );

    EnLink( lbl, TRUE );
    #if _TARGET & _TARG_80386
        if( class == FS ) {
            class = SW;
        }
    #endif
    ins = MakeCondition( OP_CMP_LESS, op, AllocIntConst( 0 ), 0, 1, class );

⌨️ 快捷键说明

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