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