temps.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 714 行 · 第 1/2 页
C
714 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "procdef.h"
#include "sysmacro.h"
#include "cgaux.h"
#include "feprotos.h"
#include "zoiks.h"
typedef struct stack_temp {
struct stack_temp *others;
instruction_id first;
instruction_id last;
} stack_temp;
typedef struct stack_entry {
struct stack_temp temp;
struct stack_entry *link;
type_length location;
type_length size;
} stack_entry;
extern name *DeAlias(name*);
extern bool SideEffect(instruction*);
extern void *SortList(void*,unsigned int,bool(*)(void*,void*));
extern void DoNothing(instruction*);
extern void TransferTempFlags(void);
extern void PushLocals(void);
extern void SetTempLocation(name*,type_length);
extern type_length TempLocation( name * );
extern bool TempAllocBefore( void *, void * );
extern name *Names[];
extern proc_def *CurrProc;
extern bool BlockByBlock;
extern block *HeadBlock;
extern name *LastTemp;
static stack_entry *StackMap;
/* borrow some bits for FindOnlyIns stuff */
#define USED_NEVER EMPTY
#define USED_ONCE USE_WITHIN_BLOCK
#define USED_TWICE USE_IN_ANOTHER_BLOCK
static void StackEntry( stack_temp *st_temp, name *temp )
/***********************************************************/
{
stack_entry *new;
_Alloc( new, sizeof( stack_entry ) );
new->link = StackMap;
new->size = temp->n.size;
new->location = temp->t.location;
new->temp.first = st_temp->first;
new->temp.last = st_temp->last;
new->temp.others = NULL;
StackMap = new;
}
extern void InitStackMap( void )
/**********************************/
{
StackMap = NULL;
}
static void ReInitStackMap( void )
/************************************/
/* we are flushing blocks so make all stack locations from block flushed*/
/* reusable in the next block to be flushed*/
{
stack_entry *stack;
stack_temp *other;
stack = StackMap;
while( stack != NULL ) {
while( stack->temp.others != NULL ) {
other = stack->temp.others;
stack->temp.others = stack->temp.others->others;
_Free( other, sizeof( stack_temp ) );
}
stack->temp.first = LAST_INS_ID;
stack->temp.last = FIRST_INS_ID;
stack = stack->link;
}
}
static void TellTempLocs( void )
/***********************************
C++ front end wants to know where all the temps are in memory
for exception handling. They really only care about the relative
displacements between the temps, so we don't have to worry about
things like SP relative offsets being different at different spots
in the code.
When we do the TEMP_LOC_NAME request, the front end can either respond
with a TEMP_LOC_YES, for us to tell them the location, or a TEMP_LOC_NO,
if they don't care about the location for this name, or a TEMP_LOC_QUIT
which means they don't want to know about any other temporaries.
Correction: They now want actual offsets on the Alpha and PPC, so we
just add in CurrProc->locals.size. This doesn't affect them on the
Intel as the relative values are still the same.
*/
{
name *temp;
int ans;
for( temp = Names[ N_TEMP ]; temp != NULL; temp = temp->n.next_name ) {
if( temp->v.symbol != NULL && !(temp->t.temp_flags & ALIAS) ) {
ans = (int)FEAuxInfo( temp->v.symbol, TEMP_LOC_NAME );
if( ans == TEMP_LOC_QUIT ) break;
if( temp->t.location == NO_LOCATION ) continue;
if( ans == TEMP_LOC_YES ) {
FEAuxInfo( (pointer)TempLocation( temp ), TEMP_LOC_TELL );
}
}
}
}
static stack_entry *ReUsableStack(stack_temp *st_temp,name *temp)
/********************************************************************/
{
type_length size;
stack_entry *stack;
stack_temp *others;
stack = StackMap;
size = temp->n.size;
while( stack != NULL ) {
others = &stack->temp;
if( size <= stack->size ) {
for( ;; ) {
if( others->first <= st_temp->last
&& others->last >= st_temp->first ) break;
others = others->others;
if( others == NULL ) return( stack );
}
}
stack = stack->link;
}
return( stack );
}
static bool SetLastUse( name *op, name *temp,
stack_temp *new, instruction *ins )
/*********************************************************/
{
if( op->n.class == N_INDEXED && op->i.base != NULL ) {
op = op->i.base;
}
if( op->n.class == N_TEMP ) {
if( DeAlias( op ) == temp ) {
_INS_NOT_BLOCK ( ins );
new->last = ins->id;
return( TRUE );
}
}
return( FALSE );
}
static void ScanForLastUse( block *blk, stack_temp *new, name *temp )
/***********************************************************************/
{
instruction *ins;
int i;
ins = blk->ins.hd.prev;
for( ;; ) {
if( ins->head.opcode == OP_BLOCK ) {
new->last = new->first;
return;
}
if( ins->result != NULL && ins->result->n.class == N_TEMP
&& DeAlias( ins->result ) == temp ) {
if( SideEffect( ins ) ) {
new->last = new->first + 1;
return;
} else {
DoNothing( ins );
}
} else {
i = ins->num_operands;
while( --i >= 0 ) {
if( SetLastUse( ins->operands[i], temp, new, ins ) ) return;
}
if( ins->result != NULL ) {
if( SetLastUse( ins->result, temp, new, ins ) ) return;
}
}
ins = ins->head.prev;
}
}
static void ScanForFirstDefn( block *blk, stack_temp *new, name *temp )
/*************************************************************************/
{
instruction *ins;
int i;
ins = blk->ins.hd.next;
for(;;) {
if( ins->head.opcode == OP_BLOCK ) {
new->first = FIRST_INS_ID;
return;
}
if( ins->result != NULL ) {
if( ins->result->n.class == N_TEMP ) {
if( DeAlias( ins->result ) == temp ) {
new->first = ins->id;
return;
}
}
}
i = ins->num_operands;
while( --i >= 0 ) {
if( ins->operands[i]->n.class == N_TEMP ) {
if( DeAlias( ins->operands[ i ] ) == temp ) {
new->first = ins->id;
return;
}
}
}
ins = ins->head.next;
}
}
static void CalcRange( stack_temp *new, name *temp )
/******************************************************/
{
block *blk;
blk = HeadBlock;
while( blk->id != temp->t.u.block_id ) {
blk = blk->next_block;
}
ScanForFirstDefn( blk, new, temp );
ScanForLastUse( blk, new, temp );
}
static bool In( name *op, name *name )
/****************************************/
{
if( op->n.class == N_INDEXED ) {
if( In( op->i.index, name ) ) return( TRUE );
if( op->i.base != NULL && !( op->i.index_flags & X_FAKE_BASE ) ) {
return( In( op->i.base, name ) );
}
} else if( op->n.class == N_TEMP ) {
if( DeAlias( op ) == name ) return( TRUE );
}
return( FALSE );
}
static bool UsedByLA( instruction *ins, name *temp )
/******************************************************/
{
if( ins->head.opcode == OP_LA || ins->head.opcode == OP_CAREFUL_LA ) {
if( ins->operands[ 0 ] == temp ) return( TRUE );
}
return( FALSE );
}
static instruction *FindOnlyIns( name *name, bool *any_references )
/**********************************************************************/
{
block *blk;
instruction *ins;
instruction *onlyins;
int i;
if( name->v.block_usage == USED_NEVER ) {
*any_references = FALSE;
return( NULL );
}
if( name->v.block_usage == USED_TWICE ) {
*any_references = TRUE;
return( NULL );
}
*any_references = TRUE;
blk = HeadBlock;
onlyins = NULL;
while( blk != NULL ) {
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
i = ins->num_operands;
while( --i >= 0 ) {
if( In( ins->operands[ i ], name ) ) {
if( onlyins != NULL ) return( NULL );
onlyins = ins;
}
}
if( ins->result != NULL ) {
if( In( ins->result, name ) ) {
if( onlyins != NULL ) return( NULL );
onlyins = ins;
}
}
ins = ins->head.next;
}
blk = blk->next_block;
}
if( onlyins == NULL ) {
*any_references = FALSE;
}
return( onlyins );
}
extern void PropLocal( name *temp )
/*************************************/
{
name *scan;
scan = temp->t.alias;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?