rtcall.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 188 行

C
188
字号
/****************************************************************************
*
*                            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:  Generate runtime support call.
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "regset.h"
#include "opcodes.h"
#include "rttable.h"
#include "rtclass.h"

extern  name            *AllocRegName(hw_reg_set);
extern  name            *AllocMemory(pointer,type_length,cg_class,type_class_def);
extern  name            *AllocIntConst(int);
extern  instruction     *NewIns(int);
extern  instruction     *MakeMove(name*,name*,type_class_def);
extern  rt_class        AskHow(type_class_def,type_class_def);
extern  label_handle    RTLabel(int);
extern  hw_reg_set      FirstReg(reg_set_index);
extern  void            LookupRoutine(instruction*);
extern  void            LookupConvertRoutine(instruction*);
extern  void            SuffixIns(instruction*,instruction*);
extern  void            ReplIns(instruction*,instruction*);
extern  void            DelSeg(instruction*);
extern  void            UpdateLive(instruction*,instruction*);
extern  void            DoNothing(instruction*);
extern  void            MoveSegOp(instruction*,instruction*,int);
extern  void            PrefixIns(instruction*,instruction*);
extern  void            MoveSegRes(instruction*,instruction*);
extern  void            FixCallIns(instruction*);
#if _TARGET == _TARG_370
extern  hw_reg_set      RAReg( void );
extern  hw_reg_set      LNReg( void );
#endif
#if _TARGET == _TARG_AXP
extern  hw_reg_set      SavedRegs( void );
#endif

extern    reg_list      *RegSets[];

#if _TARGET & _TARG_AXP
    #define _ParmReg( x )       FirstReg( x )
#else
    #define _ParmReg( x )       FirstReg( x )
#endif

extern  instruction     *rMAKECALL( instruction *ins )
/*****************************************************
    Using the table RTInfo[], do all the necessary stuff to turn
    instruction "ins" into a call to a runtime support routine.  Move
    the parms into registers, and move the return register of the
    runtime routine into the result. Used for 386 and 370 versions
*/
{
    rtn_info            *info;
    label_handle        lbl;
    instruction         *left_ins;
    instruction         *new_ins;
    instruction         *last_ins;
    name                *reg_name;
    hw_reg_set          regs;
    hw_reg_set          all_regs;
    hw_reg_set          tmp;

    if( !_IsConvert( ins ) ) {
        LookupRoutine( ins );
    } else { /* look it up again in case we ran out of memory during expansion*/
        LookupConvertRoutine( ins );
    }
    info = &RTInfo[  RoutineNum  ];
    regs = _ParmReg( info->left );
    all_regs = regs;
    left_ins = MakeMove( ins->operands[ 0 ], AllocRegName( regs ),
                          info->operand_class );
    ins->operands[ 0 ] = left_ins->result;
    MoveSegOp( ins, left_ins, 0 );
    PrefixIns( ins, left_ins );
    regs = _ParmReg( info->right );
    if( !HW_CEqual( regs, HW_EMPTY ) ) {
        new_ins = MakeMove( ins->operands[ 1 ], AllocRegName( regs ),
                                info->operand_class );
        ins->operands[ 1 ] = new_ins->result;
        MoveSegOp( ins, new_ins, 0 );
        HW_TurnOn( all_regs, regs );
        PrefixIns( ins, new_ins );
    }
#if _TARGET == _TARG_370
    tmp = RAReg();
    HW_TurnOn( all_regs, tmp );
    tmp = LNReg();
    HW_TurnOn( all_regs, tmp );
#elif _TARGET == _TARG_80386
    {
    extern hw_reg_set ReturnReg(type_class_def,bool);
    tmp = ReturnReg( WD, FALSE );
    HW_TurnOn( all_regs, tmp );
    }
#endif
    reg_name = AllocRegName( all_regs );
    lbl = RTLabel( RoutineNum );
    new_ins = NewIns( 3 );
    new_ins->head.opcode = OP_CALL;
    new_ins->type_class = ins->type_class;
    new_ins->operands[ CALL_OP_USED ] = reg_name;
    new_ins->operands[ CALL_OP_USED2 ] = reg_name;
    new_ins->operands[ CALL_OP_ADDR ]= AllocMemory( lbl, 0, CG_LBL,
                                                    ins->type_class );
    new_ins->result = NULL;
    new_ins->num_operands = 2;         /* special case for OP_CALL*/
#if _TARGET == _TARG_AXP
    {
    extern hw_reg_set ReturnAddrReg( void );
    HW_CTurnOn( all_regs, HW_FULL );
    HW_TurnOff( all_regs, SavedRegs() );
    HW_CTurnOff( all_regs, HW_UNUSED );
    HW_TurnOn( all_regs, ReturnAddrReg() );
    }
#endif
    new_ins->zap = (register_name *) AllocRegName( all_regs );/* all parm regs could be zapped*/
    last_ins = new_ins;
    if( ins->result == NULL || _OpIsCondition( ins->head.opcode ) ) {
        /* comparison, still need conditional jumps*/
        ins->operands[ 0 ] = AllocIntConst( 0 );
        ins->operands[ 1 ] = AllocIntConst( 1 );
        DelSeg( ins );
        DoNothing( ins );               /* just conditional jumps for ins*/
        PrefixIns( ins, new_ins );
        new_ins->ins_flags |= INS_CC_USED;
        last_ins = ins;
    } else {
        regs = _ParmReg( info->result );
        tmp = regs;
        HW_TurnOn( tmp, new_ins->zap->reg );
        new_ins->zap = (register_name *) AllocRegName( tmp );
        reg_name = AllocRegName( regs );
        new_ins->result = reg_name;
        last_ins = MakeMove( reg_name, ins->result, ins->type_class );
        ins->result = last_ins->operands[ 0 ];
        MoveSegRes( ins, last_ins );
        SuffixIns( ins, last_ins );
        ReplIns( ins, new_ins );
    }
    FixCallIns( new_ins );
    UpdateLive( left_ins, last_ins );
    return( left_ins );
}


extern  hw_reg_set      FirstReg( reg_set_index index )
/******************************************************
    The table RTInfo[] uses reg_set_indexes instead of hw_reg_sets since
    they are only one byte long.  This retrieves the first hw_reg_set
    from the reg_set table "index".
*/
{
    hw_reg_set  *list;

    list = RegSets[  index  ];
    return( *list );
}

⌨️ 快捷键说明

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