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 + -
显示快捷键?