addrfold.c

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

C
681
字号
static  void    AddIndex( an addr, name *index, name *addend ) {
/**************************************************************/

    instruction         *ins;
    type_class_def      class;

    class = index->n.name_class;
    if( class == XX ) class = addend->n.name_class; /* if index is a const ! */
    ins = MakeBinary( OP_ADD, index, addend, AllocTemp( class ), class );
    index = ins->result;
    AddIns( ins );
    addr->index = index;
}


extern  bool    CypAddrPlus( an l_addr, an r_addr, type_def *tipe ) {
/*******************************************************************/

    mode_action action;

    if( tipe->refno == T_HUGE_POINTER ) return( FALSE );
    CheckPointer( l_addr );
    if( l_addr->format == NF_NAME ) return( FALSE );
    CheckPointer( r_addr );
    if( r_addr->format == NF_NAME ) return( FALSE );
    action = AddTable[ Idx[ r_addr->class ] ][ Idx[ l_addr->class ] ];
    if( action == ADD_LA ) return( TRUE );
    if( action == ADD_RA ) return( TRUE );
    #if WORD_SIZE == 2
        if( action == SHRNK_R ) return( TRUE );
        if( action == SHRNK_L ) return( TRUE );
    #else
        if( action == XPAND_R ) return( TRUE );
        if( action == XPAND_L ) return( TRUE );
    #endif
    return( FALSE );
}


static        bool    AddToTypeLength( type_length x, type_length y ) {
/*********************************************************************/

    signed_32 lx,ly;

    lx = x; ly = y;
    x += y; lx += ly;
    if( lx != x ) return( FALSE );
    #if _TARGET & _TARG_370
        if( lx < 0 || lx >= 4096 ) return( FALSE );
    #endif
    return( TRUE );
}


extern  an      AddrPlus( an l_addr, an r_addr, type_def *tipe ) {
/****************************************************************/

/*       Returns NULL if code needs to be generated*/

    mode_action action;
    an          addr;

    CheckPointer( l_addr );
    CheckPointer( r_addr );
    if( !AddToTypeLength( l_addr->offset, r_addr->offset ) ) return( NULL );
    if( l_addr->format == NF_NAME ) return( NULL );
    if( r_addr->format == NF_NAME ) return( NULL );
    if( tipe->refno == T_HUGE_POINTER ) return( NULL );
    addr = NewAddrName();
    for(;;) {
        action = AddTable[ Idx[ r_addr->class ] ][ Idx[ l_addr->class ] ];
        switch( action ) {
        case UNEXPECTED:
            AddrFree( addr );
            return( NULL );
        case TEMP_L:
            LoadTempInt( l_addr );
            break;
        case TEMP_R:
            LoadTempInt( r_addr );
            break;
#if WORD_SIZE == 2
        case SHRNK_L:
            Convert( l_addr, I2 );
            l_addr->class = CL_TEMP_OFFSET;
            break;
        case SHRNK_R:
            Convert( r_addr, I2 );
            r_addr->class = CL_TEMP_OFFSET;
            break;
#endif
        case XPAND_L:
            Convert( l_addr, I4 );
            l_addr->class = CL_VALUE4;
            break;
        case XPAND_R:
            Convert( r_addr, I4 );
            r_addr->class = CL_VALUE4;
            break;
#if WORD_SIZE == 2
        case XP_LC:
            r_addr->offset += l_addr->offset;
            l_addr->offset = 0;
            Convert( l_addr, I4 );
            l_addr->class = CL_VALUE4;
            break;
        case XP_RC:
            l_addr->offset += r_addr->offset;
            r_addr->offset = 0;
            Convert( r_addr, I4 );
            r_addr->class = CL_VALUE4;
            break;
#endif
        case IL:
            MoveAddress( r_addr, addr );
            addr->index = l_addr->u.name;
            addr->offset += l_addr->offset;
            FixIndexClass( addr );
            break;
        case IR:
            MoveAddress( l_addr, addr );
            addr->index = r_addr->u.name;
            addr->offset += r_addr->offset;
            FixIndexClass( addr );
            break;
        case ADD_LA:
            MoveAddress( l_addr, addr );
            addr->offset += r_addr->offset;
            break;
        case ADD_RA:
            MoveAddress( r_addr, addr );
            addr->offset += l_addr->offset;
            break;
        case ADD_LI:
            if( PointLess( l_addr, r_addr ) ) {
                AddrFree( addr );
                return( NULL );
            }
            MoveAddress( l_addr, addr );
            addr->offset += r_addr->offset;
            AddIndex( addr, l_addr->index, r_addr->u.name );
            break;
        case ADD_RI:
            if( PointLess( l_addr, r_addr ) ) {
                AddrFree( addr );
                return( NULL );
            }
            MoveAddress( r_addr, addr );
            addr->offset += l_addr->offset;
            AddIndex( addr, r_addr->index, l_addr->u.name );
            break;
        case ADD_I:
            if( PointLess( l_addr, r_addr ) ) {
                AddrFree( addr );
                return( NULL );
            }
            addr->offset = l_addr->offset + r_addr->offset;
            addr->class = CL_TEMP_OFFSET;
            AddIndex( addr, l_addr->u.name, r_addr->u.name );
            addr->u.name = addr->index;
            addr->index = NULL;
            break;
        case CODE:
            AddrFree( addr );
            return( NULL );
        }
        if( _HaveMode( action ) ) break;
    }
    BGDone( l_addr );
    BGDone( r_addr );
    addr->tipe = tipe;
    return( addr );
}


static  bool    ShiftConst( an r_addr ) {
/***************************************/

    if( r_addr->format != NF_CONS ) return( FALSE );
    if( r_addr->class != CL_CONS2 ) return( FALSE );
    #if WORD_SIZE == 2
        if( r_addr->offset < 0 || r_addr->offset > 16 ) return( FALSE );
        if( _IsTargetModel( BIG_DATA ) && _IsntTargetModel( CHEAP_POINTER ) ) return( FALSE );
    #else
        if( r_addr->offset < 0 || r_addr->offset > 8 ) return( FALSE );
    #endif
    return( TRUE );
}


extern  bool    CypAddrShift( an l_addr, an r_addr, type_def *tipe ) {
/********************************************************************/

    tipe = tipe;
    CheckPointer( l_addr );
    if( l_addr->format == NF_NAME ) return( FALSE );
    if( l_addr->class != CL_TEMP_OFFSET ) return( FALSE );
    if( l_addr->offset == 0 ) return( FALSE );
    if( !ShiftConst( r_addr ) ) return( FALSE );
    return( TRUE );
}


static        bool    ShiftToTypeLength( type_length x, unsigned_16 y ) {
/**********************************************/

    signed_32 lx;

    lx = x;
    x <<= y; lx <<= y;
    if( lx != x ) return( FALSE );
    #if _TARGET & _TARG_370
        if( lx < 0 || lx >= 4096 ) return( FALSE );
    #endif
    return( TRUE );
}


extern  an      AddrShift( an l_addr, an r_addr, type_def *tipe ) {
/*****************************************************************/

/*       Returns NULL if code needs to be generated*/

    instruction         *ins;
    signed_16           rv;
    an                  addr;
    type_class_def      class;

    addr = NULL;
    if( !ShiftConst( r_addr ) ) return( NULL );
    CheckPointer( l_addr );
    if( l_addr->format == NF_NAME ) return( NULL );
    if( l_addr->class != CL_TEMP_OFFSET ) return( NULL );
    if( l_addr->offset == 0 ) return( NULL );
    rv = r_addr->offset;
    if( !ShiftToTypeLength( l_addr->offset, rv ) ) return( NULL );
    addr = NewAddrName();
    addr->offset = l_addr->offset << rv;  /* new constant after shift*/
    class = TypeClass( tipe );
    ins = MakeBinary( OP_LSHIFT, l_addr->u.name,
            AllocIntConst( rv ), AllocTemp( class ), class );
    addr->u.name = ins->result;
    AddIns( ins );
    addr->class = CL_TEMP_OFFSET;
    BGDone( l_addr );
    BGDone( r_addr );
    addr->tipe = tipe;
    return( addr );
}


extern  name    *GetValue( an addr, name *suggest ) {
/***************************************************/

    name        *op;
    instruction *ins;

    InsToAddr( addr );
    if( addr->format == NF_CONS || addr->format == NF_NAME ) {
        op = addr->u.name;
    } else if( addr->format == NF_ADDR ) {
        switch( addr->class ) {
        case CL_VALUE2:
        case CL_VALUE4:
            op = addr->u.name;
            break;
        case CL_TEMP_OFFSET:
            if( addr->offset != 0 ) {
                op = MaybeTemp( suggest, addr->u.name->n.name_class );
                ins = MakeBinary( OP_ADD, addr->u.name,
                                    AllocS32Const( addr->offset ),
                                    op, TypeClass( addr->tipe ) );
                if( addr->flags & ADDR_DEMOTED ) ins->ins_flags |= INS_DEMOTED;
                AddIns( ins );
            } else {
                op = addr->u.name;
            }
            break;
        case CL_ADDR_GLOBAL:
            op = AllocMemory( addr->u.name->v.symbol,
                     addr->offset, addr->u.name->m.memory_type, XX );
            op = LoadAddress( op, suggest, addr->tipe );
            break;
        case CL_ADDR_TEMP:
            op = TempOffset( addr->u.name, addr->offset, XX );
            op = LoadAddress( op, suggest, addr->tipe );
            break;
        case CL_GLOBAL_INDEX:
        case CL_TEMP_INDEX:
            op = AllocIndex( addr->index, addr->u.name,
                                addr->offset, XX );
            op = LoadAddress( op, suggest, addr->tipe );
            break;
        case CL_POINTER:
            op = AllocIndex( addr->index, addr->u.name,
                                addr->offset, XX );
            op = LoadAddress( op, suggest, addr->tipe );
            break;
        default:
            break;
        }
    } else if( addr->format == NF_BOOL ) {
        _Zoiks( ZOIKS_025 );
    }
    if( op->n.class == N_TEMP
     && op->v.symbol == NULL
     && ( addr->flags & STACKABLE )
     && !( addr->flags & NEVER_STACK ) ) {
        FPSetStack( op );
    }
    return( op );
}


extern  name    *AddrToName( an addr ) {
/**************************************/

    name        *op;

    op = NULL;
    if( addr->format == NF_CONS || addr->format == NF_NAME ) {
        op = addr->u.name;
    } else if( addr->format == NF_ADDR ) {
        switch( addr->class ) {
        case CL_VALUE2:
        case CL_VALUE4:
            op = addr->u.name;
            break;
        case CL_TEMP_OFFSET:
            if( addr->offset == 0 ) {
                op = addr->u.name;
            }
            break;
        default:
            break;
        }
    }
    return( op );
}

⌨️ 快捷键说明

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