varusage.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 486 行 · 第 1/2 页
C
486 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Variable/memory usage analysis.
*
****************************************************************************/
#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "sysmacro.h"
#include "conflict.h"
#include "hwreg.h"
extern name *DeAlias(name*);
extern block *HeadBlock;
extern name *Names[];
extern conflict_node *ConfList;
extern bool BlockByBlock;
static void Use( name *op, block *blk, var_usage usage )
/***********************************************************
Mark "op" as used in "blk". assume that if it hasn't already been
defined in this block, that it must be USE_IN_ANOTHER_BLOCK. "usage"
may be set to USE_ADDRESS indicating that we are using the address
of the name.
*/
{
if( op->n.class == N_CONSTANT && op->c.const_type == CONS_TEMP_ADDR ) {
Use( (name*)op->c.value, blk, USE_ADDRESS );
return;
}
if( op->n.class == N_TEMP ) {
op = DeAlias( op );
} else if( op->n.class != N_MEMORY ) {
return;
}
if( op->v.block_usage & DEF_WITHIN_BLOCK ) {
op->v.block_usage |= USE_WITHIN_BLOCK;
} else {
op->v.block_usage |= USE_IN_ANOTHER_BLOCK;
if( op->v.conflict != NULL ) {
_GBitTurnOn( blk->dataflow->use,
op->v.conflict->id.out_of_block );
}
}
op->v.block_usage |= usage;
}
static bool CoveringDefinitions( name *op )
/**********************************************
If we are only defining a piece of "op", we check all of its aliases
to see if they have been defined in this block as well. Only if all
the definitions cause the entire name to be redefined do we mark the
master symbol table entry for the name as "DEF_WITHIN_BLOCK" and
flip on its bit in dataflo->def.
*/
{
name *alias;
int i;
uint loc;
bool covered[MAX_POSSIBLE_REG+1];
if( op->n.size > MAX_POSSIBLE_REG ) return( FALSE );
i = op->n.size;
while( --i >= 0 ) {
covered[ i ] = FALSE;
}
alias = op->t.alias;
while( alias != op ) {
if( alias->v.block_usage & DEF_WITHIN_BLOCK ) {
loc = alias->v.offset - op->v.offset;
i = alias->n.size;
while( --i >= 0 ) {
if( loc < sizeof( covered ) ) covered[ loc ] = TRUE;
++loc;
}
}
alias = alias->t.alias;
}
i = op->n.size;
while( --i >= 0 ) {
if( covered[ i ] == FALSE ) return( FALSE );
}
return( TRUE );
}
static void Define( name *op, block *blk )
/*********************************************
Mark "op" as defined within "blk".
*/
{
name *actual;
actual = op;
actual->v.block_usage |= DEF_WITHIN_BLOCK;
if( op->n.class == N_TEMP ) op = DeAlias( op );
if( op->v.block_usage & USE_IN_ANOTHER_BLOCK ) return;
if( actual != op && CoveringDefinitions( op ) == FALSE ) return;
op->v.block_usage |= DEF_WITHIN_BLOCK;
if( op->v.conflict == NULL ) return;
_GBitTurnOn( blk->dataflow->def, op->v.conflict->id.out_of_block );
}
static void UseDefGlobals( block *blk )
/******************************************
If a call instruction is encountered, all N_MEMORY names (visible
outside this procedure), could be both used and defined by the call.
*/
{
conflict_node *conf;
var_usage usage;
conf = ConfList;
while( conf != NULL ) {
if( conf->name->n.class == N_MEMORY ) {
usage = conf->name->v.block_usage;
Use( conf->name, blk, EMPTY );
Define( conf->name, blk );
_GBitTurnOn( blk->dataflow->def, conf->id.out_of_block );
if( ( usage & DEF_WITHIN_BLOCK ) == EMPTY ) {
_GBitTurnOn( blk->dataflow->use, conf->id.out_of_block );
}
}
conf = conf->next_conflict;
}
}
static void TransferBlockUsage( name *op )
/*****************************************
Never have both USE_WITHIN_BLOCK and USE_IN_ANOTHER_BLOCK set.
*/
{
op->v.usage |= op->v.block_usage;
if( op->v.usage & USE_IN_ANOTHER_BLOCK ) {
op->v.usage &= ~ USE_WITHIN_BLOCK;
}
op->v.block_usage = EMPTY;
}
static void TransferOneTempBlockUsage( name *op )
/************************************************
see TransferTempBlockUsage ^
*/
{
name *alias;
if( op->n.class == N_CONSTANT && op->c.const_type == CONS_TEMP_ADDR ) {
TransferOneTempBlockUsage( op->c.value );
} else if( op->n.class == N_INDEXED ) {
TransferOneTempBlockUsage( op->i.index );
if( HasTrueBase( op ) ) {
TransferOneTempBlockUsage( op->i.base );
}
} else if ( op->n.class == N_TEMP ) {
alias = op->t.alias;
for( ;; ) {
TransferBlockUsage( alias );
if( alias == op ) break;
alias = alias->t.alias;
}
}
}
static void TransferTempBlockUsage( block *blk )
/***********************************************
Traverse the block "blk", and for each variable referenced by an
instruction within block, Make sure that USE_WITHIN_BLOCK and
USE_IN_OTHER_BLOCK are not on simultaneously for each variable and
all of its aliases. We traverse the block rather than Names[N_TEMP]
since running down the list of temps could be very expensive (if
long). Blocks on the other hand are always reasonably short
*/
{
instruction *ins;
int i;
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
i = ins->num_operands;
while( --i >= 0 ) {
TransferOneTempBlockUsage( ins->operands[ i ] );
}
if( ins->result != NULL ) {
TransferOneTempBlockUsage( ins->result );
}
ins = ins->head.next;
}
}
static void TransferAllMemBlockUsage( void )
/***********************************************
Like TransferTempBlockUsage.
*/
{
name *mem;
for( mem = Names[N_MEMORY]; mem != NULL; mem = mem->n.next_name ) {
TransferBlockUsage( mem );
}
}
static void TransferOneMemBlockUsage( name *op )
/***********************************************
see TransferMemBlockUsage ^
*/
{
if( op->n.class == N_INDEXED ) {
TransferOneMemBlockUsage( op->i.index );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?