fixindex.c

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

C
442
字号

extern  void    NoMemIndex( instruction *ins ) {
/***********************************************
    Make sure that we aren't using an N_MEMORY operand as the index
    of an N_INDEXED operand in "ins". If we are, call IndexToTemp.
*/

    int         i;
    name        *bad_index;

    for( ;; ) {
        i = ins->num_operands;
        bad_index = NULL;
        while( --i >= 0 ) {
            if( ins->operands[ i ]->n.class == N_INDEXED
             && ins->operands[ i ]->i.index->n.class == N_MEMORY ) {
                bad_index = ins->operands[ i ];
            }
        }
        if( ins->result != NULL ) {
            if( ins->result->n.class == N_INDEXED
             && ins->result->i.index->n.class == N_MEMORY ) {
                bad_index = ins->result;
            }
        }
        if( bad_index == NULL ) break;
        (void)IndexToTemp( ins, bad_index );
    }
}


static  name    *OpTemp( instruction *ins, uint i, uint j ) {
/************************************************************
    Used by OneMemRef to split an operand out into a temporary
*/

    name                *temp;
    type_class_def      class;
    instruction         *new_ins;

    class = FPInsClass( ins );
    if( class == XX ) {
        if( ins->operands[ i ]->n.name_class == XX ) {
            class = ins->type_class;
        } else {
            class = ins->operands[ i ]->n.name_class;
        }
    }
#if _TARGET & _TARG_AXP
    if( i == 0 && ins->head.opcode == OP_CONVERT ) {
        class = ins->base_type_class;
    }
#endif
    temp = AllocTemp( class );
    FPSetStack( temp );
    new_ins = MakeMove( ins->operands[ i ], temp, class );
    ins->operands[ i ] = temp;
    ins->operands[ j ] = temp;
    PrefixIns( ins, new_ins );
    return( temp );
}


static  instruction     *Split3( instruction *ins ) {
/****************************************************
    Used by OneMemRef to split an instruction containing 3 memory references.
*/

    name        *temp;
    instruction *new_ins;

    if( ins->operands[ 0 ]->n.class == N_INDEXED
     || ins->operands[ 0 ]->n.class == N_MEMORY ) {
        temp = OpTemp( ins, 0, 0 );
        if( temp->n.name_class != ins->result->n.name_class
          || FPIsStack( temp ) ) {
            temp = AllocTemp( ins->result->n.name_class );
            FPSetStack( temp );
        }
        new_ins = MakeMove( temp, ins->result, temp->n.name_class );
        ins->result = temp;
        SuffixIns( ins, new_ins );
        ins = new_ins;
    } else {
        OpTemp( ins, 1, 1 );
    }
    return( ins );
}


static  instruction     *ResTemp( instruction *ins ) {
/*****************************************************
    Used by OneMemRef to move the result of an instruction to an N_TEMP
    before moving it to the real result.
*/

    name        *temp;
    instruction *new_ins;

    temp = AllocTemp( ins->result->n.name_class );
    FPSetStack( temp );
    new_ins = MakeMove( temp, ins->result, temp->n.name_class );
    ins->result = temp;
    SuffixIns( ins, new_ins );
    return( new_ins );
}


extern  instruction     *OneMemRef( instruction *ins ) {
/*******************************************************
    see FixIndex
*/

    name        *op1;
    name        *op2;
    name        *res;

    FixFPConsts( ins );
    if( ins->num_operands == 2 ) {
        if( ins->result != NULL ) { /* the tough case*/
            op1 = ins->operands[ 0 ];
            if( op1->n.class != N_INDEXED && op1->n.class != N_MEMORY ) {
                op1 = NULL;
            }
            op2 = ins->operands[ 1 ];
            if( op2->n.class != N_INDEXED && op2->n.class != N_MEMORY ) {
                op2 = NULL;
            }
            res = ins->result;
            if( res->n.class != N_INDEXED && res->n.class != N_MEMORY ) {
                res = NULL;
            }
            if( op1 != NULL && op2 != NULL && res != NULL ) {
                /* three memory references*/
                if( RTLeaveOp2( ins ) ) {
                    OpTemp( ins, 0, 0 );
                    ins = ResTemp( ins );
                } else if( op1 == op2 ) {
                    OpTemp( ins, 0, 1 );
                } else if( op1 == res ) {
                    OpTemp( ins, 1, 1 );
                } else if( op2 == res ) {
                    OpTemp( ins, 0, 0 );
                } else {
                    ins = Split3( ins );
                }
            } else if( op1 == NULL && op2 == NULL ) {
                /* one memory reference*/
            } else if( op1 == NULL && res == NULL ) {
                /* one memory reference*/
            } else if( op2 == NULL && res == NULL ) {
                /* one memory reference*/
            } else if( op1 != res && op2 != res && op1 != op2 ) {
               /* two memory references*/
                if( RTLeaveOp2( ins ) ) {
                    OpTemp( ins, 0, 0 );
                    ins = ResTemp( ins );
                } else {
                    ins = Split3( ins );
                }
            }
        } else {
            op1 = ins->operands[ 0 ];
            op2 = ins->operands[ 1 ];
            if( op1->n.class != N_INDEXED && op1->n.class != N_MEMORY ) {
                return( ins );
            }
            if( op2->n.class != N_INDEXED && op2->n.class != N_MEMORY ) {
                return( ins );
            }
            if( op1 == op2 ) return( ins );
            OpTemp( ins, 0, 0 );
        }
    } else if( ins->num_operands == 1 && ins->result != NULL ) {
        op1 = ins->operands[ 0 ];
        res = ins->result;
        if( op1->n.class != N_INDEXED && op1->n.class != N_MEMORY ) {
            return( ins );
        }
        if( res->n.class != N_INDEXED && res->n.class != N_MEMORY ) {
            return( ins );
        }
        if( op1 == res ) return( ins );
        if( ins->type_class == XX ) return( ins );
        if( _IsConvert( ins ) && ins->type_class > ins->base_type_class ) {
            ResTemp( ins ); /* 90-Nov-29 */
        } else {
            OpTemp( ins, 0, 0 );
        }
    }
    return( ins );
}


extern  void    FixIndex() {
/***************************
    Make sure that there is only one memory reference per instruction.
    This is so that a segment override can tag along on the instruction
    and be unambiguous as to what it is supposed to affect.  It is also
    so that the register allocator only has to deal with an instruction
    needing at most one index register.
*/

    block       *blk;
    instruction *ins;

    blk = HeadBlock;
    while( blk != NULL ) {
        ins = blk->ins.hd.next;
        while( ins->head.opcode != OP_BLOCK ) {
            if( ins->type_class != XX
             && ins->head.opcode != OP_LA
             && ins->head.opcode != OP_CAREFUL_LA ) {
                ins = OneMemRef( ins );
            }
            ins = ins->head.next;
        }
        blk = blk->next_block;
    }
}

⌨️ 快捷键说明

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