expand.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 400 行
C
400 行
/****************************************************************************
*
* 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: Expand instructions so that machine code can be generated.
*
****************************************************************************/
#include "standard.h"
#include "coderep.h"
#include "pattern.h"
#include "regset.h"
#include "opcodes.h"
#include "vergen.h"
#include "memcheck.h"
#include "hostsys.h"
#include "zoiks.h"
extern void EXBlip(void);
extern instruction *Reduce(instruction*);
extern name *AllocRegName(hw_reg_set);
extern int NumOperands(instruction*);
extern instruction *NeedIndex(instruction*);
extern opcode_entry *CodeTable(instruction*);
extern bool DoVerify(vertype,instruction*);
extern void MarkPossible(instruction*,name*,reg_set_index);
extern void MarkCallI(instruction);
extern reg_set_index SpecialPossible(instruction*);
extern reg_set_index CallIPossible(instruction*);
extern bool VolatileIns(instruction*);
extern block *HeadBlock;
extern op_regs RegList[];
extern reg_list *RegSets[];
static instruction *DoReduce( instruction *ins, opcode_entry *try,
bool has_index )
/*********************************************************************/
{
hw_reg_set *zap;
hw_reg_set zap_all;
if( try == NULL ) return( ins );
if( try->generate == G_NO ) return( ins );
if( try->generate >= FIRST_REDUCT ) return( Reduce( ins ) );
zap = RegSets[ RegList[ try->reg_set ].zap ];
zap_all = ins->zap->reg;
while( !HW_CEqual( *zap, HW_EMPTY ) ) {
HW_TurnOn( zap_all, *zap );
++zap;
}
ins->zap = (register_name *) AllocRegName( zap_all );
if( has_index || ins->num_operands > NumOperands( ins ) ) {
ins = NeedIndex( ins );
} else {
ins->t.index_needs = RL_;
}
return( ins );
}
static bool VerifyRegs( instruction *ins, operand_types ops )
/***************************************************************/
{
#define _Any( ops, mul ) ( ( ops & (ANY*mul) ) == (ANY*mul) )
opcode_entry *try;
hw_reg_set *possible;
name *name;
op_regs *need;
hw_reg_set regs;
reg_set_index left_index;
reg_set_index right_index;
reg_set_index result_index;
reg_set_index special_index;
try = ins->u.gen_table;
need = &RegList[ try->reg_set ];
result_index = RL_;
name = ins->result;
if( ( ops & R_R ) == 0 ) {
if( ops & U_R ) {
result_index = need->result;
}
} else if( need->result != RL_ ) {
if( name->n.class != N_REGISTER ) {
result_index = need->result;
} else if( !_Any( try->op_type, RESULT_MUL ) ) {
regs = name->r.reg;
possible = RegSets[ need->result ];
for(;;) {
if( HW_CEqual( *possible, HW_EMPTY ) ) return( FALSE );
if( HW_Equal( *possible, regs ) ) break;
++ possible;
}
}
}
left_index = RL_;
if( ( ops & R_1 ) == 0 ) {
if( ops & U_1 ) {
left_index = need->left;
}
} else if( need->left != RL_ ) {
name = ins->operands[ 0 ];
if( name->n.class != N_REGISTER ) {
left_index = need->left;
} else if( !_Any( try->op_type, OP1_MUL ) ) {
regs = name->r.reg;
possible = RegSets[ need->left ];
for(;;) {
if( HW_CEqual( *possible, HW_EMPTY ) ) return( FALSE );
if( HW_Equal( *possible, regs ) ) break;
++ possible;
}
}
}
right_index = RL_;
if( ( ops & R_2 ) == 0 ) {
if( ops & U_2 ) {
right_index = need->right;
}
} else if( need->right != RL_ ) {
name = ins->operands[ 1 ];
if( name->n.class != N_REGISTER ) {
right_index = need->right;
} else if( !_Any( try->op_type, OP2_MUL ) ) {
regs = name->r.reg;
possible = RegSets[ need->right ];
for(;;) {
if( HW_CEqual( *possible, HW_EMPTY ) ) return( FALSE );
if( HW_Equal( *possible, regs ) ) break;
++ possible;
}
}
}
if( try->generate < FIRST_REDUCT ) {
special_index = SpecialPossible( ins );
if( special_index != RL_ ) {
MarkPossible( ins, ins->result, special_index );
} else if( result_index != RL_ ) {
MarkPossible( ins, ins->result, result_index );
}
if( left_index != RL_ ) {
MarkPossible( ins, ins->operands[ 0 ], left_index );
}
if( right_index != RL_ ) {
MarkPossible( ins, ins->operands[ 1 ], right_index );
}
}
return( TRUE );
}
static operand_types ClassifyOps( instruction *ins, bool *has_index )
/**********************************************************************/
{
name *name;
operand_types ops;
int num_operands;
num_operands = NumOperands( ins );
*has_index = FALSE;
ops = NONE;
name = ins->result;
if( name != NULL && num_operands != 0 ) {
if( ins->operands[ 0 ] == name ) {
ops &= EQ_R1;
}
if( num_operands != 1 ) {
if( ins->operands[ 1 ] == name ) {
ops &= EQ_R2;
}
}
}
if( name != NULL ) {
switch( name->n.class ) {
case N_REGISTER:
ops |= R_R;
break;
case N_INDEXED:
*has_index = TRUE;
ops |= M_R;
break;
case N_MEMORY:
case N_TEMP:
if( name->v.conflict == NULL ) {
ops |= M_R;
} else if( name->v.usage & USE_MEMORY ) {
ops |= M_R;
} else {
ops |= U_R;
ins->head.state = OPERANDS_NEED_WORK;
}
break;
}
}
if( num_operands != 0 ) {
name = ins->operands[ 0 ];
switch( name->n.class ) {
case N_CONSTANT:
ops |= C_1;
break;
case N_REGISTER:
ops |= R_1;
break;
case N_INDEXED:
*has_index = TRUE;
ops |= M_1;
break;
case N_MEMORY:
case N_TEMP:
if( name->v.conflict == NULL ) {
ops |= M_1;
} else if( name->v.usage & USE_MEMORY ) {
ops |= M_1;
} else {
ops |= U_1;
ins->head.state = OPERANDS_NEED_WORK;
}
break;
}
}
if( num_operands > 1 ) {
name = ins->operands[ 1 ];
switch( name->n.class ) {
case N_CONSTANT:
ops |= C_2;
break;
case N_REGISTER:
ops |= R_2;
break;
case N_INDEXED:
*has_index = TRUE;
ops |= M_2;
break;
case N_MEMORY:
case N_TEMP:
if( name->v.conflict == NULL ) {
ops |= M_2;
} else if( name->v.usage & USE_MEMORY ) {
ops |= M_2;
} else {
ops |= U_2;
ins->head.state = OPERANDS_NEED_WORK;
}
break;
}
if( num_operands > 2 ) {
name = ins->operands[ 2 ];
if( name->n.class == N_INDEXED ) {
*has_index = TRUE;
}
if( ins->head.opcode == OP_CALL_INDIRECT ) {
switch( name->n.class ) {
case N_MEMORY:
case N_TEMP:
if( name->v.conflict != NULL && !( name->v.usage & USE_MEMORY ) ) {
ins->head.state = OPERANDS_NEED_WORK;
}
}
}
}
}
return( ops );
}
extern opcode_entry *FindGenEntry( instruction *ins, bool *has_index )
/************************************************************************/
{
opcode_entry *try;
operand_types ops;
unsigned verify;
ins->head.state = INS_READY;
try = ins->table;
if( try == NULL ) {
try = CodeTable( ins );
ins->table = try;
}
if( try == NULL ) return( try );
ops = ClassifyOps( ins, has_index );
for( ;; ++ try ) {
if( ( ops & try->op_type ) != ops ) continue;
verify = try->verify;
if( verify != V_NO ) {
if( !DoVerify( verify & ~NOT_VOLATILE, ins ) ) continue;
if( (verify & NOT_VOLATILE) && VolatileIns( ins ) ) continue;
}
ins->u.gen_table = try;
if( try->reg_set != RG_ ) {
if( VerifyRegs( ins, ops ) == FALSE ) continue;
}
if( ins->head.opcode == OP_CALL_INDIRECT ) {
MarkPossible(ins, ins->operands[CALL_OP_ADDR], CallIPossible(ins));
}
break;
}
return( try );
}
extern void FixGenEntry( instruction *ins )
/*********************************************/
{
/* update the instruction to reflect new instruction needs*/
opcode_entry *old;
bool dummy;
old = ins->u.gen_table;
FindGenEntry( ins, &dummy );
if( ins->u.gen_table->generate >= FIRST_REDUCT ) {
ins->u.gen_table = old;
}
ins->head.state = INS_NEEDS_WORK;
}
extern instruction *PostExpandIns( instruction *ins )
/********************************************************/
{
opcode_entry *try;
bool has_index;
try = FindGenEntry( ins, &has_index );
if( try == NULL ) return( ins );
if( try->generate == G_NO ) return( ins );
if( try->generate >= FIRST_REDUCT ) return( Reduce( ins ) );
return( ins );
}
extern instruction *ExpandIns( instruction *ins )
/****************************************************/
{
opcode_entry *try;
bool has_index;
try = FindGenEntry( ins, &has_index );
return( DoReduce( ins, try, has_index ) );
}
extern int ExpandOps( bool keep_on_truckin )
/***********************************************/
{
block *blk;
instruction *ins;
int unknowns;
unknowns = 0;
blk = HeadBlock;
while( blk != NULL ) {
EXBlip();
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
if( keep_on_truckin == FALSE && _MemLow ) {
unknowns = -1;
break;
}
ins = ExpandIns( ins );
if( ins->head.state == INS_NEEDS_WORK ) {
ins = ExpandIns( ins );
} else {
if( ins->head.state == OPERANDS_NEED_WORK ) {
++ unknowns;
}
ins = ins->head.next;
}
}
if( unknowns == -1 ) break;
blk = blk->next_block;
}
return( unknowns );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?