i86call.c

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

C
505
字号
/****************************************************************************
*
*                            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 "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "procdef.h"
#include "model.h"
#include "sysmacro.h"
#include "addrname.h"
#include "cgdefs.h"
#include "hostsys.h"
#include "cgaux.h"
#include "regset.h"
#include "rtclass.h"
#include "zoiks.h"
#define BY_CG
#include "cgprotos.h"

extern  instruction     *MakeMove(name*,name*,type_class_def);
extern  instruction     *MakeUnary(opcode_defs,name*,name*,type_class_def);
extern  label_handle    AskForNewLabel(void);
extern  name            *SAllocMemory(pointer,type_length,cg_class,type_class_def,type_length);
extern  name            *AddrConst(name*,segment_id,constant_class);
extern  name            *AllocRegName(hw_reg_set);
extern  name            *AllocTemp(type_class_def);
extern  name            *NearSegment(void);
extern  name            *SAllocIndex(name*,name*,type_length,type_class_def,type_length);
extern  name            *SAllocTemp(type_class_def,type_length);
extern  seg_id          AskBackSeg(void);
extern  seg_id          SetOP(seg_id);
extern  type_class_def  TypeClass(type_def*);
extern  void            AddIns(instruction*);
extern  void            DataLabel(label_handle);
extern  void            SaveDisplay(opcode_defs);
extern  void            SetDisplay(name*);
extern  name            *GenIns(an);
extern  instruction     *MakeBinary(opcode_defs,name*,name*,name*,type_class_def);
extern  name            *AllocS32Const(signed_32);
extern  an              MakeTempAddr(name*,type_def*);
extern  bool            AssgnParms(cn,bool);
extern  type_class_def  AddCallBlock(sym_handle,type_def*);
extern  void            AddCallIns(instruction*,cn);
extern  void            FreeCallNode(cn);
extern  name            *SegmentPart(name*);
extern  name            *OffsetPart(name*);
extern  name            *DoParmDecl(sym_handle,type_def*,hw_reg_set);
extern  hw_reg_set      ReturnReg(type_class_def,bool);
extern  type_length     PushSize(type_length);
extern  type_def        *QParmType(sym_handle,sym_handle,type_def*);
extern  label_handle    RTLabel( int rtindex );
extern  name            *AllocMemory(pointer,type_length,cg_class,type_class_def);
extern  void            ReverseParmNodeList(pn *);
extern  name            *STempOffset(name*,type_length,type_class_def,type_length);
extern  void            SuffixIns( instruction *, instruction * );
extern  name            *BGNewTemp( type_def *tipe );
extern  void            BGDone( an );


extern  type_def        *TypeInteger;
extern  type_def        *TypeNone;
extern  type_def        *TypeProcParm;
extern  type_class_def  ClassPointer;
extern  proc_def        *CurrProc;
extern  type_length     MaxStack;
extern  block           *CurrBlock;


extern  type_length     TypeClassSize[];

static  void    AddCall( instruction *ins, cn call );

#if _TARGET & _TARG_80386
static  void    Far16Parms( cn call ) {
/*************************************/

    instruction         *ins;
    type_length         parm_size;
    pn                  parm, next;
    instruction         *call_ins;
    name                *eax;
    name                *ecx;
    name                *esi;
    label_handle        lbl;
    type_length         offset;
    name                *parmlist;
    call_state          *state;
    int                 thunk_rtn;

    call_ins = call->ins;
    parm_size = 0;
    state = call->state;
    for( parm = call->parms; parm != NULL; parm = parm->next ) {
        parm_size += (( parm->name->tipe->length ) + 1) & ~1;
    }
    parmlist = SAllocTemp( XX, parm_size );
    parmlist->v.usage |= NEEDS_MEMORY+USE_IN_ANOTHER_BLOCK+USE_ADDRESS;
    offset = 0;
    for( parm = call->parms; parm != NULL; parm = parm->next ) {
        parm->name->u.ins->result = STempOffset( parmlist, offset,
                                                 TypeClass( parm->name->tipe ),
                                                 parm->name->tipe->length );
        offset += (( parm->name->tipe->length ) + 1) & ~1;
    }
    for( parm = call->parms; parm != NULL; parm = next ) {
        parm->name->format = NF_ADDR;
        BGDone( parm->name );
        next = parm->next;
        _Free( parm, sizeof( parm_node ) );
    }
    eax = AllocRegName( HW_EAX );
    ecx = AllocRegName( HW_ECX );
    esi = AllocRegName( HW_ESI );
    HW_TurnOn( state->parm.used, eax->r.reg );
    HW_TurnOn( state->parm.used, ecx->r.reg );
    HW_TurnOn( state->parm.used, esi->r.reg );
    ins = MakeMove( AllocS32Const( parm_size ), ecx, WD );
    AddIns( ins );
    ins = MakeUnary( OP_LA, parmlist, esi, WD );
    AddIns( ins );
    if( ins->head.opcode == OP_CALL ) {
        ins = MakeUnary( OP_LA, call->name->u.name, eax, WD );
    } else {
        ins = MakeMove( GenIns( call->name ), eax, WD );
        call_ins->head.opcode = OP_CALL;
    }
    call_ins->num_operands = 2;
    AddIns( ins );
    if( call_ins->type_class == XX ) {
        if( state->attr & ROUTINE_ALLOCS_RETURN ) {
            thunk_rtn = RT_Far16Cdecl;
        } else {
            thunk_rtn = RT_Far16Pascal;
        }
    } else {
        thunk_rtn = RT_Far16Func;
    }
    lbl = RTLabel( thunk_rtn - BEG_RTNS );
    call->name->u.name = AllocMemory( lbl, 0, CG_LBL, WD );
    call_ins->flags.call_flags |= CALL_FAR16 | CALL_POPS_PARMS;
    call_ins->operands[CALL_OP_USED] = AllocRegName( state->parm.used );
    call_ins->operands[CALL_OP_POPS] = AllocS32Const( 0 );
    call_ins->zap = &call_ins->operands[CALL_OP_USED]->r;
}
#endif


extern  an      BGCall( cn call, bool use_return, bool in_line ) {
/****************************************************************/

    instruction         *call_ins;
    call_state          *state;
    name                *ret_ptr = NULL;
    name                *result;
    name                *temp;
    name                *reg_name;
    instruction         *ret_ins = NULL;
    hw_reg_set          return_reg;
    hw_reg_set          zap_reg;

    if( call->name->tipe == TypeProcParm ) {
        SaveDisplay( OP_PUSH );
    }

    state = call->state;
    result = BGNewTemp( call->tipe );
    call_ins = call->ins;

/*   If we have a return value that won't fit in a register*/
/*   pass a pointer to result as the first parm*/

    if( call_ins->type_class == XX ) {
        if( _RoutineIsFar16( state->attr ) ) {
            if( state->attr & ROUTINE_ALLOCS_RETURN ) {
                HW_CAsgn( state->return_reg, HW_EAX );
            } else {
                HW_CAsgn( state->return_reg, HW_EBX );
            }
        }
        if( ( state->attr & ROUTINE_ALLOCS_RETURN ) == 0 ) {
            if( HW_CEqual( state->return_reg, HW_EMPTY ) ) {
                ret_ptr = AllocTemp( WD );
            } else {
                ret_ptr = AllocRegName( state->return_reg );
            }
            ret_ins = MakeUnary( OP_LA, result, ret_ptr, WD );
            HW_TurnOn( state->parm.used, state->return_reg );
            call_ins->flags.call_flags |= CALL_RETURNS_STRUCT;
        }
    }
    if( _IsTargetModel(FLOATING_DS) && (state->attr&ROUTINE_NEEDS_DS_LOADED) ) {
        HW_CTurnOn( state->parm.used, HW_DS );
    }
    if( _RoutineIsFar16( state->attr ) ) {
        #if _TARGET & _TARG_80386
            Far16Parms( call );
        #endif
    } else {
        if( AssgnParms( call, in_line ) ) {
            if( state->attr & ROUTINE_REMOVES_PARMS ) {
                call_ins->flags.call_flags |= CALL_POPS_PARMS;
            }
        }
    }

    if( state->attr & (ROUTINE_MODIFIES_NO_MEMORY | ROUTINE_NEVER_RETURNS) ) {
        /* a routine that never returns can not write any memory as far
            as this routine is concerned */
        call_ins->flags.call_flags |= CALL_WRITES_NO_MEMORY;
    }
    if( state->attr & ROUTINE_READS_NO_MEMORY ) {
        call_ins->flags.call_flags |= CALL_READS_NO_MEMORY;
    }
    if( state->attr & ROUTINE_NEVER_RETURNS ) {
        call_ins->flags.call_flags |= CALL_ABORTS;
    }
    if( _RoutineIsInterrupt( state->attr ) ) {
        call_ins->flags.call_flags |= CALL_INTERRUPT | CALL_POPS_PARMS;
    }
    if( use_return == FALSE ) {
        call_ins->flags.call_flags |= CALL_IGNORES_RETURN;
    }
    if( call_ins->type_class == XX ) {
        reg_name = AllocRegName( state->return_reg );

⌨️ 快捷键说明

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