i86proc.c

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

C
1,286
字号
        return;
    if( SymIsExported( sym ) ) {
        CurrProc->prolog_state |= GENERATE_EXPORT;
    }
}


extern void RTCall( rt_class rtn, oc_class pop_bit ) {
/****************************************************/

    DoCall( RTLabel( rtn - BEG_RTNS ), TRUE, _IsTargetModel( BIG_CODE ), pop_bit );
}


static  bool    NeedStackCheck( void )
/******************************/
{
    return( FEStackChk( AskForLblSym( CurrProc->label ) ) );
}


static void DoStackCheck( void ) {
/**************************/

    if( CurrProc->prolog_state & GENERATE_THUNK_PROLOG )
        return;
    #if _TARGET & _TARG_80386
    if( CurrProc->prolog_state & GENERATE_GROW_STACK ) {
        if( BlockByBlock || CurrProc->locals.size >= 4*1024 ) {
            GenUnkPush( &CurrProc->targ.stack_check );
            RTCall( RT_GROW, ATTR_POP );
        }
        return;
    }
    #endif
    if( NeedStackCheck() ) {
    #if _TARGET & _TARG_80386
        GenUnkPush( &CurrProc->targ.stack_check );
        RTCall( RT_CHK, ATTR_POP );
    #else
        if( HW_COvlap( CurrProc->state.parm.used, HW_AX ) ) {
            QuickSave( HW_STACK_CHECK, OP_PUSH );
        }
        GenUnkMov( HW_STACK_CHECK, &CurrProc->targ.stack_check );
        RTCall( RT_CHK, EMPTY );
        if( HW_COvlap( CurrProc->state.parm.used, HW_AX ) ) {
            QuickSave( HW_STACK_CHECK, OP_POP );
        }
    #endif
    }
}


static  void    EmitNameInCode( void ) {
/********************************/

    sym_handle      sym;
    char        *name;
    char        *endname;
    char        b[128];
    label_handle    lbl;

    sym = AskForLblSym( CurrProc->label );
    if( sym == NULL )
        return;
    name = FEName( sym );
    endname = CopyStr( name, b );
    name = b;
    *endname = endname - name;
    lbl = AskForNewLabel();
    TellKeepLabel( lbl );
    CodeLabel( lbl, 0 );
    GenKillLabel( lbl );
    EyeCatchBytes( name, *endname+1 );
}


static  int ProEpiDataSize( void )
/***************************
*/
{

    return( ( (int)(pointer)FEAuxInfo( NULL, PROEPI_DATA_SIZE )
        + (WORD_SIZE-1) ) & ~(WORD_SIZE-1) );
}


static  void    PrologHook( void )
/***************************
*/
{
    int      size;

    if( !( CurrProc->prolog_state & GENERATE_PROLOG_HOOKS ) )
        return;
    size = ProEpiDataSize();
    if( size != 0 ) {
        GenRegSub( HW_SP, size );
        CurrProc->targ.base_adjust += size;
    }
    #if _TARGET & _TARG_80386
//        GenPushC( CurrProc->parms.size );
        RTCall( RT_PROHOOK, EMPTY );
    #else
        RTCall( RT_PROHOOK, EMPTY );
    #endif
}


static  void    EpilogHook( void )
/***************************
*/
{
    int      size;

    if( ( CurrProc->prolog_state & GENERATE_EPILOG_HOOKS ) ) {
        RTCall( RT_EPIHOOK, EMPTY );
    }
    size = ProEpiDataSize();
    if( size != 0 )
        GenRegAdd( HW_SP, size );
}


static  void    DoLoadDS( void )
{
    #if _TARGET & _TARG_80386
    if( _IsntTargetModel( LOAD_DS_DIRECTLY ) ) {
        RTCall( RT_GETDS, EMPTY );
    } else
    #endif
    {
        if( HW_COvlap( CurrProc->state.parm.used, HW_AX ) ) {
            QuickSave( HW_STACK_CHECK, OP_PUSH );
        }
        GenLoadDS();
        if( HW_COvlap( CurrProc->state.parm.used, HW_AX ) ) {
            QuickSave( HW_STACK_CHECK, OP_POP );
        }
    }
}


static  int LoadDS( void )
/**********************/
{
    int     size;

    size = 0;
    if( CurrProc->state.attr & ROUTINE_LOADS_DS ) {
        if( HW_COvlap( CurrProc->state.unalterable, HW_DS ) ) {
            QuickSave( HW_DS, OP_PUSH );
            size = WORD_SIZE;
            DoLoadDS();
        }
    }
    return( size );
}


static  void    UnloadDS( void ) {
/**************************/

    if( CurrProc->state.attr & ROUTINE_LOADS_DS ) {
        if( HW_COvlap( CurrProc->state.unalterable, HW_DS ) ) {
            QuickSave( HW_DS, OP_POP );
        }
    }
}

extern  void    GenProlog( void ) {
/***************************/

    seg_id  old;
    hw_reg_set  to_push;
    unsigned    ret_size;
    pointer label;
    pointer origlabel; // Original label for generated __far16 thunks
    fe_attr attr;

    ScanInstructions();       /* Do These 2 calls before using DO_WINDOWS_CRAP! */
    FindIfExported();
    old = SetOP( AskCodeSeg() );

    if( CurrProc->prolog_state & GENERATE_FUNCTION_NAME ) {
        EmitNameInCode();
    }

    if( _IsModel( NUMBERS ) ) {
        CodeLineNum( HeadBlock->ins.hd.line_num, FALSE );
    }

    if( _IsModel( DBG_LOCALS ) ){  // d1+ or d2
        EmitRtnBeg();
    }
    if( CurrProc->state.attr & ROUTINE_WANTS_DEBUGGING ) {
        CurrProc->state.attr |= ROUTINE_NEEDS_PROLOG;
    }

    CurrProc->parms.base = 0;
    CurrProc->parms.size = CurrProc->state.parm.offset;

    origlabel = label = CurrProc->label;

    #if _TARGET & _TARG_80386
    if( _RoutineIsFar16( CurrProc->state.attr ) ) {
        label = GenFar16Thunk( CurrProc->label, CurrProc->parms.size,
                    CurrProc->state.attr & ROUTINE_REMOVES_PARMS );
        // CurrProc->label = label; - ugly mess if following are combined
    }
    #endif

    CodeLabel( label, DepthAlign( PROC_ALIGN ) );

    attr = FEAttr( AskForLblSym( origlabel ) );

    #if _TARGET & _TARG_80386
    if( ( attr & FE_NAKED ) == EMPTY ) {
        if( _IsTargetModel( NEW_P5_PROFILING|P5_PROFILING ) ) {
            GenP5ProfilingProlog( label );
        }
        if( CurrProc->prolog_state & GENERATE_THUNK_PROLOG ) {
            QuickSave( HW_SP, OP_PUSH );
            GenPushC( CurrProc->parms.size );
            GenUnkPush( &CurrProc->targ.stack_check );
        if( NeedStackCheck() ) {
            RTCall( RT_THUNK_STK, ATTR_POP );
        } else {
            RTCall( RT_THUNK, ATTR_POP );
        }
        CurrProc->parms.base += WORD_SIZE;
        }
    }
    #endif

    if( _RoutineIsInterrupt( CurrProc->state.attr ) ||
        ( CurrProc->state.attr & ROUTINE_NEVER_RETURNS ) ) {
       ret_size = 0;
    } else if( _RoutineIsLong( CurrProc->state.attr ) ) {
        ret_size = 2 * WORD_SIZE;
    } else if( _RoutineIsFar16( CurrProc->state.attr ) ) {
        ret_size = 2 * WORD_SIZE;
    } else {
        ret_size = WORD_SIZE;
    }

    CurrProc->parms.base += ret_size;
    CalcUsedRegs();

    to_push = SaveRegs();
    HW_CTurnOff( to_push, HW_FLTS );
    if( !CurrProc->targ.sp_frame || CurrProc->targ.sp_align ) {
        HW_CTurnOff( to_push, HW_BP );
    }

    if( ( attr & FE_NAKED ) != EMPTY ) {
        // don't do anything - empty prologue
    } else if( _RoutineIsInterrupt( CurrProc->state.attr ) ) {
        ret_size = -PushAll();
        CurrProc->targ.base_adjust = 0;
        MoveParms();
    } else {
        if( CHAIN_FRAME ) {
            CurrProc->targ.base_adjust = 0;
            if( NeedBPProlog() ) {
                HW_CTurnOn( CurrProc->state.used, HW_BP );
                CurrProc->parms.base += WORD_SIZE;
                if( FAR_RET_ON_STACK ) {
                    if( CHEAP_FRAME ) {
                        GenCypWindowsProlog();
                    } else {
                        #if _TARGET & _TARG_IAPX86
                        // Windows prologs zap AX, so warn idiot user if we
                        // generate one for a routine in which AX is live
                        // upon entry to routine, or unalterable.
                        if( HW_COvlap( CurrProc->state.unalterable, HW_AX ) ||
                            HW_COvlap( CurrProc->state.parm.used, HW_AX ) ) {
                            FEMessage( MSG_ERROR,
                            "exported routine with AX live on entry" );
                        }
                        #endif
                        GenWindowsProlog();
                        CurrProc->targ.base_adjust += 2; /* the extra push DS */
                    }
                } else {
                    QuickSave( HW_BP, OP_PUSH );
                    GenRegMove( HW_SP, HW_BP );
                }
                PrologHook();
            }
            DoStackCheck();
            CurrProc->targ.base_adjust += LoadDS();
            CurrProc->targ.base_adjust += Push( to_push );
            CurrProc->parms.base += CurrProc->targ.base_adjust;
            AllocStack();
            AdjustPushLocals();
        } else {
            DoStackCheck();
            CurrProc->parms.base += LoadDS();
            if( (CurrProc->state.attr & ROUTINE_NEVER_RETURNS) == 0 ) {
                CurrProc->parms.base += Push( to_push );
            }
            Enter();
            AdjustPushLocals();
            if( _IsModel( NO_OPTIMIZATION ) || CurrProc->targ.sp_frame ) {
                CurrProc->targ.base_adjust = 0;
            } else {
                CurrProc->targ.base_adjust = AdjustBase();
                if( CurrProc->targ.base_adjust != 0 ) {
                    GenRegSub( HW_BP, -CurrProc->targ.base_adjust );
                }
            }
        }
        RelocParms();
        MoveParms();
    }
    CurrProc->prolog_state |= GENERATED_PROLOG;

    if( _IsModel( DBG_LOCALS ) ){  // d1+ or d2
        DbgRetOffset( CurrProc->parms.base - CurrProc->targ.base_adjust
                - ret_size );
        EmitProEnd();
    }
    SetOP( old );

    if( CurrProc->prolog_state & GENERATE_EXPORT ) {
        OutDLLExport( ( CurrProc->parms.size+WORD_SIZE-1 ) / WORD_SIZE,
                     AskForLblSym( CurrProc->label ) );
    }
}


static  void    MoveParms( void ) {
/***************************/

    int     i;

    i = 0;
    while( Parm8087[ i ] != NULL ) {
        GFstpM( Parm8087[ i ] );
        ++i;
    }
}


extern  void    InitStackDepth( block *blk ) {
/********************************************/

    if( blk->edge[0].flags & DOWN_ONE_CALL ) {
        StackDepth = WORD_SIZE;
    } else {
        StackDepth = 0;
    }
    StackDepth += blk->stack_depth;
}


extern  void        AdjustStackDepth( instruction *ins ) {
/************************************************************/

    name    *op;
    type_length adjust;

    if( !DoesSomething( ins ) )
        return;
    switch( ins->head.opcode ) {
    case OP_ADD:
    case OP_SUB:
        if( ins->operands[0] != ins->result )
            return;
        if( ins->result->n.class != N_REGISTER )
            return;
        if( !HW_CEqual( ins->result->r.reg, HW_SP ) )
            return;
        op = ins->operands[1];
        if( op->n.class != N_CONSTANT ) {
            _Zoiks( ZOIKS_077 );
            return;
        }
        adjust = op->c.int_value;
        if( ins->head.opcode == OP_SUB ) {
            StackDepth += adjust;
        } else {
            StackDepth -= adjust;
        }
        break;
    case OP_PUSH:
        StackDepth += WORD_SIZE;
        break;
    case OP_POP:
        StackDepth -= WORD_SIZE;
        break;
    case OP_CALL:
    case OP_CALL_INDIRECT:
        if( ins->flags.call_flags & CALL_POPS_PARMS ) {
            op = ins->operands[ CALL_OP_POPS ];
            if( op->n.class == N_CONSTANT ) {
               StackDepth -= op->c.int_value;
            }
        }
    default:
        break;
    }
}

extern void     AdjustStackDepthDirect( int adjust ) {
/************************************************************/
    StackDepth += adjust;
}


extern  bool    BaseIsSP( name *op ) {
/************************************/

    if( !CurrProc->targ.sp_frame ) return( FALSE );
        if( CurrProc->targ.sp_align && ( op->t.temp_flags & STACK_PARM ) ) {
            return( FALSE );
        }
    return( TRUE );
}


extern  type_length NewBase( name *op ) {
/*******************************************/

    if( !BaseIsSP( op ) ) {
        return( op->t.location - CurrProc->targ.base_adjust );
    }
    return( op->t.location + CurrProc->locals.size

⌨️ 快捷键说明

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