Ejemplo n.º 1
0
static void CopyAuxInfo( void )
/*****************************/
{
    hw_reg_set      default_flt_n_seg;
    hw_reg_set      flt_n_seg;

    if( CurrEntry == NULL ) {
        // Redefining a built-in calling convention
    } else {
        CurrInfo = (struct aux_info *)CMemAlloc( sizeof( struct aux_info ) );
        *CurrInfo = *CurrAlias;
    }
    if( AuxInfo.code != NULL ) {
        CurrInfo->code = AuxInfo.code;
    }
    if( AuxInfoFlg.f_near ) {
        CurrInfo->cclass &= ~FAR;
    }
    if( AuxInfoFlg.f_routine_pops ) {
        CurrInfo->cclass &= ~CALLER_POPS;
    }
    if( AuxInfoFlg.f_caller_return ) {
        CurrInfo->cclass &= ~ROUTINE_RETURN;
    }
    if( AuxInfoFlg.f_8087_returns ) {
        CurrInfo->cclass &= ~NO_8087_RETURNS;
    }
    CurrInfo->cclass |= AuxInfo.cclass;
    CurrInfo->flags |= AuxInfo.flags;
    if( AuxInfo.objname != NULL )
        CurrInfo->objname = AuxInfo.objname;
    if( AuxInfo.cclass & SPECIAL_RETURN )
        CurrInfo->returns = AuxInfo.returns;
    if( AuxInfo.cclass & SPECIAL_STRUCT_RETURN )
        CurrInfo->streturn = AuxInfo.streturn;
    if( AuxInfo.parms != NULL )
        CurrInfo->parms = AuxInfo.parms;

    if( !HW_CEqual( AuxInfo.save, HW_EMPTY ) ) {
        HW_CTurnOn( CurrInfo->save, HW_FULL );
        if( !( AuxInfo.cclass & MODIFY_EXACT ) && !CompFlags.save_restore_segregs ) {
            HW_Asgn( default_flt_n_seg, WatcallInfo.save );
            HW_CAsgn( flt_n_seg, HW_FLTS );
            HW_CTurnOn( flt_n_seg, HW_SEGS );
            HW_TurnOff( CurrInfo->save, flt_n_seg );
            HW_OnlyOn( default_flt_n_seg, flt_n_seg );
            HW_TurnOn( CurrInfo->save, default_flt_n_seg );
        }
        HW_TurnOff( CurrInfo->save, AuxInfo.save );
    }
}
Ejemplo n.º 2
0
static void GetSaveInfo(
    void )
{
    hw_reg_set      modlist;
    hw_reg_set      default_flt_n_seg;
    hw_reg_set      flt_n_seg;

    struct {
        unsigned f_exact        : 1;
        unsigned f_nomemory     : 1;
        unsigned f_list         : 1;
    } have;

    have.f_exact    = 0;
    have.f_nomemory = 0;
    have.f_list     = 0;
    for( ;; ) {
        if( !have.f_exact && PragRecog( "exact" ) ) {
            CurrInfo->cclass |= MODIFY_EXACT;
            have.f_exact = 1;
        } else if( !have.f_nomemory && PragRecog( "nomemory" ) ) {
            CurrInfo->cclass |= NO_MEMORY_CHANGED;
            have.f_nomemory = 1;
        } else if( !have.f_list && IS_REGSET( CurToken ) ) {
            modlist = PragRegList();
            have.f_list = 1;
        } else {
            break;
        }
    }
    if( have.f_list ) {
        HW_Asgn( default_flt_n_seg, DefaultInfo.save );
        HW_CTurnOn( CurrInfo->save, HW_FULL );
        if( !have.f_exact && !CompFlags.save_restore_segregs ) {
            HW_CAsgn( flt_n_seg, HW_FLTS );
            HW_CTurnOn( flt_n_seg, HW_SEGS );
            HW_TurnOff( CurrInfo->save, flt_n_seg );
            HW_OnlyOn( default_flt_n_seg, flt_n_seg );
            HW_TurnOn( CurrInfo->save, default_flt_n_seg );
        }
        HW_TurnOff( CurrInfo->save, modlist );
    }
}
Ejemplo n.º 3
0
void FlowSave( hw_reg_set *preg )
/*******************************/
{
    int                 score;
    int                 i, j;
    int                 best;
    int                 num_blocks;
    int                 num_regs;
    int                 curr_reg;
    hw_reg_set          *curr_push;
    reg_flow_info       *reg_info;
    block               *save;
    block               *restore;
    instruction         *ins;
    type_class_def      reg_type;

    HW_CAsgn( flowedRegs, HW_EMPTY );
    if( _IsntModel( FLOW_REG_SAVES ) ) return;
    if( !HaveDominatorInfo ) return;
    // we can't do this if we have push's which are 'live' at the end of a block
    // - this flag is set when we see a push being generated for a call in a different
    //   block
#if _TARGET & _TARG_INTEL
    if( CurrProc->targ.never_sp_frame ) return;
#endif
    num_regs = CountRegs( *preg );
    if( num_regs == 0 ) return;
    reg_info = CGAlloc( num_regs * sizeof( reg_flow_info ) );
    num_blocks = CountBlocks();
    InitBlockArray();
    curr_push = PushRegs;
    for( curr_reg = 0; curr_reg < num_regs; curr_reg++ ) {
        while( !HW_Ovlap( *curr_push, *preg ) ) curr_push++;
        HW_Asgn( reg_info[curr_reg].reg, *curr_push );
        reg_info[curr_reg].save = NULL;
        reg_info[curr_reg].restore = NULL;
    #if _TARGET & _TARG_INTEL
        if( HW_COvlap( *curr_push, HW_BP ) ) continue;  // don't mess with BP - it's magical
    #endif
        GetRegUsage( &reg_info[curr_reg] );
        best = 0;
        for( i = 0; i < num_blocks; i++ ) {
            for( j = 0; j < num_blocks; j++ ) {
                if( PairOk( blockArray[i], blockArray[j], &reg_info[0], curr_reg ) ) {
                    // we use the number of blocks dominated by the save block plus
                    // the number of blocks post-dominated by the restore block as a
                    // rough metric for determining how much we like a given (valid)
                    // pair of blocks - the more blocks dominated, the further 'in'
                    // we have pushed the save, which should be good
                    score =  CountDomBits( &blockArray[i]->dom.dominator );
                    score += CountDomBits( &blockArray[j]->dom.post_dominator );
                    if( score > best ) {
                        best = score;
                        reg_info[curr_reg].save    = blockArray[i];
                        reg_info[curr_reg].restore = blockArray[j];
                    }
                }
            }
        }
        // so now we know where we are going to save and restore the register
        // emit the instructions to do so, and remove reg from the set to push
        // in the normal prolog sequence
        save = reg_info[curr_reg].save;
        restore = reg_info[curr_reg].restore;
        if( ( save != NULL && save != HeadBlock ) && ( restore != NULL && !_IsBlkAttr( restore, BLK_RETURN ) ) ) {
            reg_type = WD;
        #if _TARGET & _TARG_INTEL
            if( IsSegReg( reg_info[curr_reg].reg ) ) {
                reg_type = U2;
            }
        #endif
            ins = MakeUnary( OP_PUSH, AllocRegName( reg_info[curr_reg].reg ), NULL, reg_type );
            ResetGenEntry( ins );
            PrefixIns( save->ins.hd.next, ins );
            ins = MakeUnary( OP_POP, NULL, AllocRegName( reg_info[curr_reg].reg ), reg_type );
            ins->num_operands = 0;
            ResetGenEntry( ins );
            SuffixIns( restore->ins.hd.prev, ins );
            HW_TurnOff( *preg, reg_info[curr_reg].reg );
            HW_TurnOn( flowedRegs, reg_info[curr_reg].reg );
            FixStackDepth( save, restore );
        }
        curr_push++;
    }
    CGFree( reg_info );
}