s37temps.c

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

C
471
字号

    name        *temp;
    name        *base;
    name        *alias;
    type_length place;

    NoseIn = NULL;
    for( temp = Names[ N_TEMP ]; temp != NULL; temp = temp->n.next_name ) {
        if( temp->t.temp_flags & ALIAS ) continue;
        if( !( temp->t.temp_flags & STACK_PARM ) ) continue;
        base = DeAlias( temp );
        place = base->t.location + ( temp->v.offset - base->v.offset );
        alias = temp;
        do {
            alias->t.temp_flags |= FAR_LOCAL;
            alias = alias->t.alias;
        } while( alias != temp );
    }
}


static  void    OnTheEdge() {
/****************************
    Well, we have marked a bunch of temporaries as VISITED (meaning they
    need an expensive reference). We can change our mind now and let
    one of these stick its nose into the 4K area so it can be cheaply
    addressed. (NoseIn). Figure out which one is most worthy (saves most
    references) and remember it
*/

    name        *temp;

    for( temp = Names[ N_TEMP ]; temp != NULL; temp = temp->n.next_name ) {
        if( temp->t.temp_flags & VISITED ) {
            if( temp->t.u.ref_count > NoseIn->t.u.ref_count ) {
                NoseIn = DeAlias( temp );
            }
        }
    }
    temp = NoseIn;
    do {
        temp->t.temp_flags &= ~VISITED;
        temp = temp->t.alias;
    } while( temp != NoseIn );
}


static  void    AllocFarLocals() {
/*********************************
    Allocate stack space to all far locals, relatave to 0 being the
    first "far" local. These locations will be adjusted later by
    AdjustFarLocals.
*/

    name        *temp;

    for( temp = Names[ N_TEMP ]; temp != NULL; temp = temp->n.next_name ) {
        if( !( temp->t.temp_flags & VISITED ) ) continue;
        temp->t.temp_flags &= ~VISITED;
        temp->t.temp_flags |= FAR_LOCAL;
        if( temp->t.temp_flags & ALIAS ) continue;
        temp->t.location = CurrProc->targ.far_local_size;
        CurrProc->targ.far_local_size += temp->n.size;
        temp->v.usage |= HAS_MEMORY+USE_MEMORY;
        PropLocal( temp );
    }
    NoseIn->v.usage |= HAS_MEMORY+USE_MEMORY;
    NoseIn->t.location = 0;
    PropLocal( NoseIn );
}


static  void    CheckOp( name **offsets, instruction *ins, name **pop ) {
/************************************************************************
    used by FixFarLocalRefs to change one far local reference to
    an index, using the appropriate multiple of 4K constant to get
    at the temporary. The constant values are adjusted after the
    prolog is generated.
*/

    name        *op;
    name        *base;
    name        *temp;
    unsigned_32 place;
    int         i;
    instruction *new_ins;

    op = *pop;
    if( op->n.class == N_INDEXED ) {
        temp = op->i.index;
        if( temp->n.class != N_TEMP ) return;
        if( !( temp->t.temp_flags & FAR_LOCAL ) ) return;
        new_ins = MakeMove( temp, AllocTemp( temp->n.name_class ), temp->n.name_class );
        *pop = ScaleIndex( new_ins->result, op->i.base,
                          op->i.constant, op->n.class, op->n.size,
                          op->i.scale, op->i.index_flags );
        PrefixIns( ins, new_ins );
        CheckOp( offsets, new_ins, &new_ins->operands[ 0 ] );
    }
    if( op->n.class != N_TEMP ) return;
    if( !( op->t.temp_flags & FAR_LOCAL ) ) return;
    base = DeAlias( op );
    place = base->t.location + ( op->v.offset - base->v.offset );
    i = place/_4K;
    if( offsets[ i ] == NULL ) {
        /*set the symbol field in the AddrConst to non-NULL for score-boarder*/
        new_ins = MakeMove( AllocAddrConst( (name *)&CurrProc, i,
                                            CONS_OFFSET, WD ),
                        AllocTemp( WD ), WD );
        offsets[ i ] = new_ins->result;
        PrefixIns( HeadBlock->ins.hd.next, new_ins );
    }
    temp = AllocTemp( WD ),
    new_ins = MakeMove( offsets[ i ], temp, WD );
    PrefixIns( ins, new_ins );
    new_ins = MakeBinary( OP_ADD, temp, AllocRegName( DisplayReg() ), temp, WD);
    PrefixIns( ins, new_ins );
    *pop = ScaleIndex( temp, op, place%_4K,
                        op->n.name_class, op->n.size, 0, X_FAKE_BASE );
}


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** );
    _Alloc( offsets, 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;
    }
    _Free( offsets, offset_size );
}


extern  void    TempStrategy() {
/*******************************
    Figure out whether we will have any auto variables, parms
    which aren't within 4K of the AR register, and turn references
    to these temporaries into indexed references.
    Look only for autos that have complicated lives.
*/

    name        *temp;
    type_length temp_size;

    temp_size = 0;
    NoseInAdded = FALSE;
    NoseIn = NULL;
    if( CurrProc->state.attr & ROUTINE_OS ) {
        CurrProc->parms.size = 0;
    } else {
        CurrProc->parms.size = CurrProc->state.parm.offset;
    }
    FindReferences();
    for( temp = Names[ N_TEMP ]; temp != NULL; temp = temp->n.next_name ) {
        if( temp->t.temp_flags & ALIAS ) continue;
        if( temp->t.temp_flags & STACK_PARM ) continue;
        if( temp->v.usage & USE_IN_ANOTHER_BLOCK ) {
            temp_size += temp->n.size;
        }
    }
    if( temp_size + CurrProc->parms.size <= SAFE ) {
        /* don't worry, be happy */
    } else {
        if( temp_size <= SAFE || CurrProc->parms.size > 100 ) {
            CurrProc->state.attr |= ROUTINE_ALTERNATE_AR;
            ThrowOutParms();
            FixFarLocalRefs( CurrProc->parms.size );
            AdjustConsts( -CurrProc->parms.size );
        }
        if( temp_size > SAFE ) {
            SortTemps();
            ThrowOutBigTemps( temp_size );
            CountTempRefs();
            AddAliasRefs();
            OnTheEdge();
            AllocFarLocals();
            FixFarLocalRefs( CurrProc->targ.far_local_size );
        }
    }
}

extern  void    EatParmConv( void ) {
/****************************************************
    Eat any converts of parms that stayed in stack.
*/

    block       *blk;
    instruction *ins;
    name        *result;
    name        *parmin;

    blk = HeadBlock;
    if( blk != NULL ) {
        ins = blk->ins.hd.next;
        while( ins->head.opcode != OP_BLOCK ) {
            if( ins->head.opcode == OP_CONVERT
             && ins->ins_flags|INS_PARAMETER ){
                result = ins->result;
                parmin = ins->operands[0];
                if( parmin->n.class == N_TEMP && result->n.class == N_TEMP ) {
                    DoNothing( ins );
                }
            }
            ins = ins->head.next;
        }
    }
}

⌨️ 快捷键说明

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