예제 #1
0
static void *CLIAlloc( size_t size ) {

    void        *p;

    p = CGAlloc( size );
    return( p );
}
예제 #2
0
void    *SafeRecurseCG( func_sr rtn, void *arg )
/**********************************************/
/* This code assumes NO parameters on the stack! */
{
    #define SAVE_SIZE   512     /* this must be smaller than the stack */

    void                *savearea;
    void                *retval;
    mem_out_action      old_action;

    if( stackavail() < 0x2000 ) { /* stack getting low! */
        old_action = SetMemOut( MO_OK );
        savearea = CGAlloc( SAVE_SIZE );
        if( savearea == NULL ) {
            FatalError( "No memory to save stack" );
        }
        SetMemOut( old_action );
        CypCopy( bp(), savearea, SAVE_SIZE );
        CypCopy( sp(), sp() + SAVE_SIZE, bp() - sp() );
        setbp( bp() + SAVE_SIZE );
        setsp( sp() + SAVE_SIZE );
        retval = rtn( arg );
        setsp( sp() - SAVE_SIZE );
        CypCopy( sp() + SAVE_SIZE, sp(), bp() - sp() - SAVE_SIZE );
        setbp( bp() - SAVE_SIZE );
        CypCopy( savearea, bp(), SAVE_SIZE );
        CGFree( savearea );
        return( retval );
    } else {
        return( rtn( arg ) );
    }
}
예제 #3
0
extern  b       *BENewBack(sym s) {
//=================================

    b   *bk;

    Action( "BENewBack" );
    if( NewBackReturn == FAKE_NULL ) {
        bk = NULL;
    } else if( NewBackReturn != NULL ) {
        bk = NewBackReturn;
    } else {
        bk = CGAlloc( sizeof( b  ));
        bk->n = BackList;
        bk->s = s;
        bk->loc = -1;
        bk->i = ++BackId;
        bk->lp = NewLabel();
        BackList = bk;
        if( !IS_REAL_BACK( bk ) ) {
            CGError( "Internal error - odd memory" );
        }
    }
    Action( "( %s ) -> %p%n", FEName( s ), bk );
    return(bk);
}
예제 #4
0
void    CVBlkBeg( dbg_block *blk, offset lc )
/*******************************************/
{
    block_patch        *bpatch;
    dbg_patch          *dpatch;
    cv_out             out[1];
    offset             start;
    cg_sym_handle      sym;
    cs_block           *ptr;
    byte               *nm;


    bpatch = CGAlloc( sizeof( block_patch ) );
    blk->patches = bpatch;
    NewBuff( out, CVSyms );
    ptr = StartSym(  out, SG_BLOCK );
    ptr->pParent = 0;
    ptr->pEnd = 0;
    ptr->length = 0;
    ptr->offset = 0;
    ptr->segment = 0;
    nm = out->ptr;     /* mark name */
    CVPutNullStr( out );
    EndSym( out );
    dpatch = &blk->patches->patch;
    BuffPatchSet( CVSyms, dpatch );
    BuffWrite( out, &ptr->offset );
    sym = AskForLblSym( CurrProc->label );
    start = lc - CurrProc->targ.debug->blk->start;
    SymReloc( CVSyms, sym, start );
    BuffSkip( out, nm );      /* skip addr */
    buffEnd( out );
    DumpLocals( blk->locals );
}
예제 #5
0
pointer ScAlloc( size_t size )
/****************************/
{
    pointer     chunk;

    chunk = CGAlloc( size );
    return( chunk );
}
예제 #6
0
파일: display.c 프로젝트: XVilka/owp4v1copy
extern  abspatch_handle *NextFramePatch( void )
/*********************************************/
{
    frame_patch *temp;

    temp = CGAlloc( sizeof( frame_patch ) );
    temp->next = CurrProc->frame_index;
    CurrProc->frame_index = temp;
    return( &temp->patch );
}
예제 #7
0
extern  void    BGAddInlineParm( an addr ) {
/******************************************/

    inline_parm *parm;

    parm = CGAlloc( sizeof( *parm ) );
    parm->addr = addr;
    parm->next = InlineStack->parms;
    InlineStack->parms = parm;
}
예제 #8
0
static void addAutoLocn( sym s, cg_type type )
{
    AUTO_LOCN* curr;

    curr = CGAlloc( sizeof( AUTO_LOCN ) );
    curr->s = s;
    curr->offset = next_auto_offset;
    curr->next = auto_locations;
    auto_locations = curr;
    next_auto_offset += _RoundUp( BETypeLength( type ), AUTO_PACK );
}
예제 #9
0
extern  void    BGStartInline( cg_sym_handle proc_sym ) {
/*******************************************************/

    inline_stack        *stk;

    stk = CGAlloc( sizeof( *stk ) );
    stk->parms = NULL;
    stk->tipe = NULL;
    stk->addr = NULL;
    stk->proc_sym = proc_sym;
    stk->next = InlineStack;
    InlineStack = stk;
}
예제 #10
0
static  select_list *NewCase( signed_32 lo, signed_32 hi, label_handle label )
/****************************************************************************/
{
    select_list         *new_entry;

    new_entry = CGAlloc( sizeof( select_list ) );
    new_entry->low = lo;
    new_entry->high = hi;
    new_entry->count = hi - lo + 1;
    new_entry->label = label;
    new_entry->next = NULL;
    return( new_entry );
}
예제 #11
0
extern  l       *NewLabel() {
//===========================

    l   *nl;
    nl = CGAlloc( sizeof( l ) );
    nl->n = LblList;
    nl->ddef = 0;
    nl->dref = 0;
    nl->cref = NULL;
    nl->cdef = NULL;
    LblList = nl;
    nl->i = ++LabelId;
    return(nl);
}
예제 #12
0
extern  select_node     *BGSelInit( void ) {
/************************************/

    select_node         *s_node;

    s_node = CGAlloc( sizeof( select_node ) );
    s_node->num_cases = 0;
    s_node->other_wise = NULL;
    s_node->list = NULL;
#ifndef NDEBUG
    s_node->useinfo.hdltype = NO_HANDLE;
    s_node->useinfo.used = FALSE;
#endif
    return( s_node );
}
예제 #13
0
sel_handle  BGSelInit( void )
/***************************/
{
    sel_handle  s_node;

    s_node = CGAlloc( sizeof( select_node ) );
    s_node->num_cases = 0;
    s_node->other_wise = NULL;
    s_node->list = NULL;
#ifndef NDEBUG
    s_node->useinfo.hdltype = NO_HANDLE;
    s_node->useinfo.used = false;
#endif
    return( s_node );
}
예제 #14
0
static  void    InitStackLocations( void ) {
    /**************************************/

    temp_entry  *temp;
    int         i,j;

    STLocations = CGAlloc( MaxSeq * sizeof( *STLocations ) );
    for( i = 0; i < MaxSeq; ++i ) {
        for( j = VIRTUAL_0; j < VIRTUAL_NONE; ++j ) {
            RegLoc( i, j ) = ACTUAL_NONE;
        }
    }
    for( temp = TempList; temp != NULL; temp = temp->next ) {
        temp->actual_locn = ACTUAL_NONE;
    }
}
예제 #15
0
extern  void    IterBytes( offset len, byte pat )
/***********************************************/
{
    TellOptimizerByPassed();
    if( len > MAX_HACK_LEN ) {
        byte    *buff;

        buff = CGAlloc( len );
        memset( buff, pat, len );
        ObjBytes( buff, len );
        CGFree( buff );
    } else {
        memset( Buffer, pat, len );
        ObjBytes( Buffer, len );
    }
    TellByPassOver();
}
예제 #16
0
ins_entry       *NewInstr( any_oc *oc )
/*************************************/
{
    ins_entry   *instr;
    oc_length   len;

  optbegin
    len = oc->oc_header.reclen + sizeof( ins_link );
    if( len <= OCENTRY_SIZE ) {
        instr = AllocFrl( &InstrFrl, OCENTRY_SIZE );
    } else {
        instr = CGAlloc( len );
    }
    instr->ins.prev = NULL;
    instr->ins.next = NULL;
    Copy( oc, &instr->oc, oc->oc_header.reclen );
    optreturn( instr );
}
예제 #17
0
type_class_def  CallState( aux_handle aux, type_def *tipe, call_state *state )
/****************************************************************************/
{
    type_class_def      class;
    uint                i;
    hw_reg_set          parms[24];
    hw_reg_set          *parm_src;
    hw_reg_set          *parm_dst;

    state->unalterable = FixedRegs();
    HW_CAsgn( state->modify, HW_FULL );
    HW_TurnOff( state->modify, SavedRegs() );
    HW_CTurnOff( state->modify, HW_UNUSED );
    state->used = state->modify;     /* anything not saved is used*/
    state->attr = 0;
    i = 0;
    parm_src = ParmRegs();
    parm_dst = &parms[0];
    for(;;) {
        *parm_dst = *parm_src;
        if( HW_CEqual( *parm_dst, HW_EMPTY ) ) break;
        if( HW_Ovlap( *parm_dst, state->unalterable ) ) {
            FEMessage( MSG_BAD_SAVE, aux );
        }
        HW_CTurnOff( *parm_dst, HW_UNUSED );
        parm_dst++;
        parm_src++;
        i++;
    }
    i++;
    state->parm.table = CGAlloc( i*sizeof( hw_reg_set ) );
    Copy( parms, state->parm.table, i * sizeof( hw_reg_set ) );
    HW_CAsgn( state->parm.used, HW_EMPTY );
    state->parm.curr_entry = state->parm.table;
    state->parm.offset  = 0;
    InitPPCParmState( state );
    class = ReturnClass( tipe, state->attr );
    if( *(call_class *)FEAuxInfo( aux, CALL_CLASS ) & HAS_VARARGS ) {
        state->attr |= ROUTINE_HAS_VARARGS;
    }
    UpdateReturn( state, tipe, class, aux );
    return( class );
}
예제 #18
0
extern  void    Conditions( void )
/*********************************
    Traverse the basic blocks and determine if there are any compare
    instructions that we can eliminate, since the condition codes are
    already set by a subtract instruction or something.  Note that the
    internal instuctions with opcodes like OP_CMP_EQUAL generate both a
    compare and a jump.  If we "DoNothing" them, they will still
    generate the jumps, but not the compare.  In a "cc_control", we keep
    track of "left_op", "right_op" and "result_op" as well as "state".
    If "left_op" and "right_op" are set, it means that we have condition
    codes which would do for a comparison of "left_op" with "right_op"
    (subject to the signed/unsigned constraints in "state").  If
    "result_op" is set, it means we have condition codes set which would
    do for a comparison of "result_op" against zero.  On the 370, which
    has the worlds strangest set of condition codes, we use
    "state"=SIGNED_CONDITIONS_SET to mean that the condition codes are
    alright as long as we are doing a comparison of equality or
    inequality.  This is a misnomer, but I was in a hurry.
*/
{
    block       *blk;
    cc_control  *cc;

    for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
        cc = CGAlloc( sizeof( cc_control ) );
        cc->state = UNKNOWN_STATE;
        cc->left_op = NULL;
        cc->right_op = NULL;
        cc->result_op = NULL;
        cc->ins = NULL;
        cc->op_type = XX;
        blk->cc = cc;
        _MarkBlkUnVisited( blk );
    }
    FlowConditions();
    for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
        CGFree( blk->cc );
    }
}
예제 #19
0
static  temp_entry      *AddTempEntry( name *op ) {
    /********************************************/

    temp_entry  *temp;

    temp = LookupTempEntry( op );
    if( temp == NULL ) {
        temp = CGAlloc( sizeof( *temp ) );
        temp->next = TempList;
        TempList = temp;
        temp->actual_op = op;
        if( op->n.class == N_TEMP ) op = DeAlias( op );
        temp->op = op;
        temp->first = NULL;
        temp->last = NULL;
        temp->savings = 0;
        temp->actual_locn = ACTUAL_NONE;
        temp->savings = 0;
        temp->cached = FALSE;
        temp->defined = FALSE;
        temp->killed = FALSE;
        temp->global = FALSE;
        temp->whole_block = FALSE;
    }
예제 #20
0
static  void    FixFarLocalRefs( type_length size ) {
/****************************************************
    Turn far local references into indexed references so that we
    can address all of our auto variables and parms.
*/

    block       *blk;
    instruction *ins;
    int         i;
    int         offset_size;
    name        **offsets;

    i = size / _4K;
    offset_size = (i+1) * sizeof( name** );
    offsets = CGAlloc( offset_size );
    while( i >= 0 ) {
        offsets[ i ] = NULL;
        --i;
    }
    blk = HeadBlock;
    while( blk != NULL ) {
        ins = blk->ins.hd.next;
        while( ins->head.opcode != OP_BLOCK ) {
            i = ins->num_operands;
            while( --i >= 0 ) {
                CheckOp( offsets, ins, &ins->operands[ i ] );
            }
            if( ins->result != NULL ) {
                CheckOp( offsets, ins, &ins->result );
            }
            ins = ins->head.next;
        }
        blk = blk->next_block;
    }
    CGFree( offsets );
}
예제 #21
0
static  void            *DoSortList( void *list, unsigned next_offset,
                                  bool (*before)(void *,void *),
                                  unsigned length ) {
/**************************************************************************/

    void        **array;
    void        **parray;
    void        *list2;
    unsigned    mid;
    int         i;

    if( list == NULL ) return( NULL );
    array = CGAlloc( length * sizeof( void * ) );
    if( array == NULL ) {
        mid = length / 2;
        if( mid == 0 ) return( list ); /* FATAL ERROR! */
        list2 = list;
        for( i = mid; i > 0; --i ) {
            list2 = _NEXT( list2, next_offset );
        }
        list = DoSortList( list, next_offset, before, mid );
        list2 = DoSortList( list2, next_offset, before, length - mid );
        list = MergeList( list, list2, next_offset, before );
    } else {
        list2 = list;
        parray = array;
        for( i = length; i > 0; --i ) {
            *parray++ = list2;
            list2 = _NEXT( list2, next_offset );
        }
        ShellSort( array, length, before );
        list = BuildList( array, next_offset, length );
        CGFree( array );
    }
    return( list );
}
예제 #22
0
type_class_def  CallState( aux_handle aux, type_def *tipe, call_state *state )
/****************************************************************************/
{
    call_class          cclass;
    type_class_def      type_class;
    uint                i;
    hw_reg_set          parms[10];
    hw_reg_set          *parm_src;
    hw_reg_set          *parm_dst;
    hw_reg_set          *pregs;
    hw_reg_set          tmp;

    state->unalterable = FixedRegs();
    pregs = FEAuxInfo( aux, SAVE_REGS );
    HW_CAsgn( state->modify, HW_FULL );
    HW_TurnOff( state->modify, *pregs );
    HW_CTurnOff( state->modify, HW_UNUSED );
    state->used = state->modify;     /* anything not saved is used*/
    tmp = state->used;
    HW_TurnOff( tmp, StackReg() );
    HW_CTurnOff( tmp, HW_BP );  // should be able to call routine which modifies BP
    if( HW_Ovlap( state->unalterable, tmp ) ) {
        FEMessage( MSG_BAD_SAVE, aux );
    }
    state->attr = ROUTINE_REMOVES_PARMS;
    cclass = *(call_class *)FEAuxInfo( aux, CALL_CLASS );
    if( cclass & INTERRUPT ) {
        state->attr |= ROUTINE_INTERRUPT;
    } else if( cclass & FAR_CALL ) {
        state->attr |= ROUTINE_LONG;
    } else if( cclass & FAR16_CALL ) {
        state->attr |= ROUTINE_FAR16;
    }
    if( cclass & CALLER_POPS ) {
        state->attr &= ~ROUTINE_REMOVES_PARMS;
    }
    if( cclass & SUICIDAL ) {
        state->attr |= ROUTINE_NEVER_RETURNS;
    }
    if( cclass & ROUTINE_RETURN ) {
        state->attr |= ROUTINE_ALLOCS_RETURN;
    }
    if( cclass & NO_STRUCT_REG_RETURNS ) {
        state->attr |= ROUTINE_NO_STRUCT_REG_RETURNS;
    }
    if( cclass & NO_FLOAT_REG_RETURNS ) {
        state->attr |= ROUTINE_NO_FLOAT_REG_RETURNS;
        state->attr |= ROUTINE_NO_8087_RETURNS;
    }
    if( cclass & NO_8087_RETURNS ) {
        state->attr |= ROUTINE_NO_8087_RETURNS;
    }
    if( cclass & MODIFY_EXACT ) {
        state->attr |= ROUTINE_MODIFY_EXACT;
    }
    if( cclass & NO_MEMORY_CHANGED ) {
        state->attr |= ROUTINE_MODIFIES_NO_MEMORY;
    }
    if( cclass & NO_MEMORY_READ ) {
        state->attr |= ROUTINE_READS_NO_MEMORY;
    }
    if( cclass & LOAD_DS_ON_ENTRY ) {
        state->attr |= ROUTINE_LOADS_DS;
    }
    if( cclass & LOAD_DS_ON_CALL ) {
        state->attr |= ROUTINE_NEEDS_DS_LOADED;
    }
    if( cclass & PARMS_STACK_RESERVE ) {
        state->attr |= ROUTINE_STACK_RESERVE;
    }
    if( cclass & PARMS_PREFER_REGS ) {
        state->attr |= ROUTINE_PREFER_REGS;
    }
    if( cclass & FARSS ) {
        state->attr |= ROUTINE_FARSS;
    }
    if( state == &CurrProc->state ) {
        if( cclass & ( GENERATE_STACK_FRAME | PROLOG_HOOKS | EPILOG_HOOKS ) ) {
            CurrProc->prolog_state |= GENERATE_FAT_PROLOG;
            state->attr |= ROUTINE_NEEDS_PROLOG;
        }
        if( cclass & PROLOG_HOOKS ) {
            CurrProc->prolog_state |= GENERATE_PROLOG_HOOKS;
        }
        if( cclass & EPILOG_HOOKS ) {
            CurrProc->prolog_state |= GENERATE_EPILOG_HOOKS;
        }
        if( cclass & FAT_WINDOWS_PROLOG ) {
            CurrProc->prolog_state |= GENERATE_FAT_PROLOG;
        }
        if( cclass & EMIT_FUNCTION_NAME ) {
            CurrProc->prolog_state |= GENERATE_FUNCTION_NAME;
        }
        if( cclass & THUNK_PROLOG ) {
            CurrProc->prolog_state |= GENERATE_THUNK_PROLOG;
        }
        if( cclass & GROW_STACK ) {
            CurrProc->prolog_state |= GENERATE_GROW_STACK;
        }
        if( cclass & TOUCH_STACK ) {
            CurrProc->prolog_state |= GENERATE_TOUCH_STACK;
        }
        if( cclass & LOAD_RDOSDEV_ON_ENTRY ) {
            CurrProc->prolog_state |= GENERATE_RDOSDEV_PROLOG;
        }
    }
    type_class = ReturnClass( tipe, state->attr );
    i = 0;
    parm_dst = &parms[0];
    for( parm_src = FEAuxInfo( aux, PARM_REGS ); !HW_CEqual( *parm_src, HW_EMPTY ); ++parm_src ) {
        *parm_dst = *parm_src;
        if( HW_Ovlap( *parm_dst, state->unalterable ) ) {
            FEMessage( MSG_BAD_SAVE, aux );
        }
        HW_CTurnOff( *parm_dst, HW_UNUSED );
        parm_dst++;
        i++;
    }
    *parm_dst = *parm_src;
    i++;
    state->parm.table = CGAlloc( i*sizeof( hw_reg_set ) );
    Copy( parms, state->parm.table, i * sizeof( hw_reg_set ) );
    HW_CAsgn( state->parm.used, HW_EMPTY );
    state->parm.curr_entry = state->parm.table;
    state->parm.offset  = 0;
    if( tipe == TypeNone ) {
        HW_CAsgn( state->return_reg, HW_EMPTY );
    } else if( type_class == XX ) {
        if( cclass & SPECIAL_STRUCT_RETURN ) {
            pregs = FEAuxInfo( aux, STRETURN_REG );
            state->return_reg = *pregs;
            state->attr |= ROUTINE_HAS_SPECIAL_RETURN;
        } else {
            state->return_reg = StructReg();
        }
        if( (state->attr & ROUTINE_ALLOCS_RETURN) == 0 ) {
            tmp = ReturnReg( WD, false );
            HW_TurnOn( state->modify, tmp );
        }
    } else {
        if( cclass & SPECIAL_RETURN ) {
            pregs = FEAuxInfo( aux, RETURN_REG );
            state->return_reg = *pregs;
            state->attr |= ROUTINE_HAS_SPECIAL_RETURN;
        } else {
            state->return_reg = ReturnReg( type_class, _NPX( state->attr ) );
        }
    }
    UpdateReturn( state, tipe, type_class, aux );
    return( type_class );
}
예제 #23
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 );
}
예제 #24
0
파일: mpsreg.c 프로젝트: XVilka/owp4v1copy
extern  type_class_def CallState( aux_handle aux,
                                  type_def *tipe, call_state *state )
/*******************************************************************/
{
    type_class_def      class;
    uint                i;
    hw_reg_set          parms[20];
    hw_reg_set          *parm_src;
    hw_reg_set          *parm_dst;
    hw_reg_set          *pregs;
    call_class          cclass;
    call_class          *pcclass;
    risc_byte_seq       *code;
    bool                have_aux_code = FALSE;

    state->unalterable = FixedRegs();
    if( FEAttr( AskForLblSym( CurrProc->label ) ) & FE_VARARGS ) {
        HW_TurnOn( state->unalterable, VarargsHomePtr() );
    }

    // For code bursts only, query the #pragma aux instead of using
    // hardcoded calling convention. If it ever turns out that we need
    // to support more than a single calling convention, this will need
    // to change to work more like x86
    if( !AskIfRTLabel( CurrProc->label ) ) {
        code = FEAuxInfo( aux, CALL_BYTES );
        if( code != NULL ) {
            have_aux_code = TRUE;
        }
    }

    pregs = FEAuxInfo( aux, SAVE_REGS );
    HW_CAsgn( state->modify, HW_FULL );
    if( have_aux_code ) {
        HW_TurnOff( state->modify, *pregs );
    } else {
        HW_TurnOff( state->modify, SavedRegs() );
    }
    HW_CTurnOff( state->modify, HW_UNUSED );
    state->used = state->modify;    /* anything not saved is used */
    state->attr = 0;
    pcclass = FEAuxInfo( aux, CALL_CLASS );
    cclass = *pcclass;
    if( cclass & SETJMP_KLUGE ) {
        state->attr |= ROUTINE_IS_SETJMP;
    }
    if( cclass & SUICIDAL ) {
        state->attr |= ROUTINE_NEVER_RETURNS;
    }
    if( cclass & NO_MEMORY_CHANGED ) {
        state->attr |= ROUTINE_MODIFIES_NO_MEMORY;
    }
    if( cclass & NO_MEMORY_READ ) {
        state->attr |= ROUTINE_READS_NO_MEMORY;
    }
    i = 0;
    if( have_aux_code ) {
        parm_src = FEAuxInfo( aux, PARM_REGS );
    } else {
        parm_src = ParmRegs();
    }

    parm_dst = &parms[0];

    for( ;; ) {
        *parm_dst = *parm_src;
        if( HW_CEqual( *parm_dst, HW_EMPTY ) ) break;
        if( HW_Ovlap( *parm_dst, state->unalterable ) ) {
            FEMessage( MSG_BAD_SAVE, aux );
        }
        HW_CTurnOff( *parm_dst, HW_UNUSED );
        parm_dst++;
        parm_src++;
        i++;
    }
    i++;
    state->parm.table = CGAlloc( i * sizeof( hw_reg_set ) );
    Copy( parms, state->parm.table, i * sizeof( hw_reg_set ) );
    HW_CAsgn( state->parm.used, HW_EMPTY );
    state->parm.curr_entry = state->parm.table;
    state->parm.offset  = 0;
    class = ReturnClass( tipe, state->attr );
    UpdateReturn( state, tipe, class, aux );
    return( class );
}
예제 #25
0
extern  bool            CreateBreak( void )
/*****************************************/
{
    block       *blk;
    block       *break_blk;
    block       *back_break_blk;
    block       *exit_blk;
    block_edge  *edge;
    block_edge  *next_edge;
    block_num   targets;
    int         pending;
    edge_list   *exit_edge;

    if( HeadBlock == NULL ) {
        return( false );
    }
    if( _IsntModel( FORTRAN_ALIASING ) ) {
        return( false );
    }
    if( !FixReturns() ) {
        return( false );
    }
    FixEdges();

/*
    Run through the blocks and find a place (break_blk) where no previous
    blocks are branched to from later blocks. IE: there are no backward branches
    around break_blk.
*/
    _MarkBlkAllUnVisited();
    break_blk = NULL;
    back_break_blk = NULL;
    pending = 0;
    BranchOuts = NULL;
    for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
        if( AskIfReachedLabel( blk->label ) && blk != HeadBlock )
            break;
        if( (blk->edge[0].flags & BLOCK_LABEL_DIES) == 0 && blk != HeadBlock ) {
            _MarkBlkVisited( blk );
            ++pending;
        } else if( pending == 0 ) {
            break_blk = blk;
        }
        edge = &blk->edge[0];
        for( targets = blk->targets; targets > 0; --targets ) {
            if( edge->flags & DEST_IS_BLOCK ) {
                if( edge->flags & DEST_LABEL_DIES ) {
                    if( _IsBlkVisited( edge->destination.u.blk ) ) {
                        _MarkBlkUnVisited( edge->destination.u.blk );
                        if( --pending == 0 ) {
                            back_break_blk = blk->next_block;
                        }
                    }
                }
            }
            ++edge;
        }
    }
    /* clean up the BLOCK_VISITED flags */
    _MarkBlkAllUnVisited();
    if( back_break_blk != NULL ) {
        break_blk = back_break_blk; /* always better to break on a back edge */
    }
    if( break_blk == NULL ) {
        break_blk = HeadBlock;
    }
    if( break_blk == HeadBlock ) {
        break_blk = break_blk->next_block;
    }
    if( break_blk == NULL ) {
        UnFixEdges();
        return( false );
    }

/*
    create a new block and link it after break_blk. Point Break to the rest
    of the blocks and unhook them from the block list.
*/
    Break = break_blk;
    Curr = CurrBlock;
    Tail = BlockList;
    exit_blk = NewBlock( NULL, false );
    exit_blk->gen_id = BlockList->gen_id + 1;
    exit_blk->id = BlockList->id + 1;
    exit_blk->ins.hd.line_num = 0;
    BlockList = exit_blk;
    exit_blk->prev_block = break_blk->prev_block;
    exit_blk->next_block = NULL;
    _SetBlkAttr( exit_blk, BLK_UNKNOWN_DESTINATION );
    break_blk->prev_block->next_block = exit_blk;
    break_blk->prev_block = NULL;

/*
    run throuch all the blocks before break_blk, and create a 'BranchOut' for
    and edge that goes to a block after break_blk
*/
    for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
        edge = &blk->edge[0];
        for( targets = blk->targets; targets > 0; --targets ) {
            if( (edge->flags & DEST_IS_BLOCK) == 0 || edge->destination.u.blk->gen_id >= break_blk->gen_id ) {
                exit_edge = CGAlloc( sizeof( edge_list ) );
                exit_edge->edge = edge;
                exit_edge->next = BranchOuts;
                exit_edge->gen_id = blk->gen_id;
                BranchOuts = exit_edge;
            }
            ++edge;
        }
    }

/*
    now, point all 'BranchOuts' at the new 'exit' block, saving their original
    labels in the 'lbl' field of the exit_list
*/

    for( exit_edge = BranchOuts; exit_edge != NULL; exit_edge = exit_edge->next ) {
        edge = exit_edge->edge;
        if( edge->flags & DEST_IS_BLOCK ) {
            exit_edge->lbl = edge->destination.u.blk->label;
            RemoveInputEdge( edge );
        } else {
            exit_edge->lbl = edge->destination.u.lbl;
        }
        edge->destination.u.blk = exit_blk;
        edge->flags |= DEST_IS_BLOCK;
        edge->next_source = exit_blk->input_edges;
        exit_blk->input_edges = edge;
        exit_blk->inputs++;
    }

    if( exit_blk->inputs == 0 ) {
        BlockList = exit_blk->prev_block;
        BlockList->next_block = NULL;
        exit_blk->prev_block = NULL;
        FreeABlock( exit_blk );
    }

    _MarkBlkAttr( HeadBlock, BLK_BIG_LABEL );
    HaveBreak = true;
/*
    change any branches to HeadBlock from a block after break_blk into
    a label (~DEST_IS_BLOCK) branch.
*/
    for( edge = HeadBlock->input_edges; edge != NULL; edge = next_edge ) {
        next_edge = edge->next_source;
        if( edge->source->gen_id >= break_blk->gen_id ) {
            RemoveInputEdge( edge );
            edge->destination.u.lbl = edge->destination.u.blk->label;
            edge->flags &= ~DEST_IS_BLOCK;
        }
    }
/*
    Now, set up a new HeadBlock, and redirect all unknowns branches to it.
    Known branches may still go to the old HeadBlock. This is so that
    HeadBlock will not be a loop header. The loop optimizer will
    screw up if it is.
*/
    blk = NewBlock( NULL, false );
    blk->input_edges = NULL;
    blk->inputs = 0;
    blk->label = HeadBlock->label;
    blk->ins.hd.line_num = HeadBlock->ins.hd.line_num;
    HeadBlock->ins.hd.line_num = 0;
    blk->gen_id = 0;
    blk->id = 0;
    HeadBlock->label = AskForNewLabel();
    blk->targets = 1;
    _SetBlkAttr( blk, BLK_BIG_LABEL | BLK_JUMP );
    _MarkBlkAttrNot( HeadBlock, BLK_BIG_LABEL );
    edge = &blk->edge[0];
    edge->flags = DEST_IS_BLOCK;
    edge->destination.u.blk = HeadBlock;
    edge->source = blk;
    edge->next_source = HeadBlock->input_edges;
    HeadBlock->input_edges = edge;
    HeadBlock->inputs++;
    HeadBlock->prev_block = blk;
    blk->prev_block = NULL;
    blk->next_block = HeadBlock;
    HeadBlock = blk;
    return( true );
}