📄 object.c
字号:
/****************************************************************************
*
* 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: Generate object code from symbolic instructions.
*
****************************************************************************/
#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "model.h"
#include "procdef.h"
#include "sysmacro.h"
#include "cgaux.h"
#include "zoiks.h"
#include "feprotos.h"
extern seg_id AskCodeSeg( void );
extern seg_id SetOP(seg_id);
extern void CodeLabel(label_handle,unsigned);
extern void GenObjCode(instruction*);
extern void GenJumpLabel(pointer);
extern void GenEpilog( void );
extern void GenCallLabel(pointer);
extern void GenLabelReturn( void );
extern void TellCondemnedLabel(label_handle);
extern void FreeBlock( void );
extern void CodeLineNum(cg_linenum,bool);
extern void InitZeroPage( void );
extern void FiniZeroPage( void );
extern void TellReachedLabel(label_handle);
extern unsigned DepthAlign( unsigned );
extern void InitStackDepth(block*);
extern block *FindBlockWithLbl( label_handle label );
extern void Zoiks( int );
extern void ClearBlockBits( block_class );
extern bool ReDefinedBy( instruction *, name * );
extern pointer AskForLblSym(pointer);
extern pointer FindAuxInfo( name *, aux_class );
extern void StartBlockProfiling( block *blk );
extern void EndBlockProfiling( void );
extern void *EdgeStackInit( void );
extern void EdgeStackFini( void * );
extern bool EdgeStackEmpty( void * );
extern void EdgeStackPush( void *, block_edge * );
extern block_edge *EdgeStackPop( void * );
extern block *HeadBlock;
extern block *CurrBlock;
extern block *BlockList;
extern proc_def *CurrProc;
extern bool BlocksUnTrimmed;
extern bool BlockByBlock;
extern byte OptForSize;
static source_line_number DumpLineNum( source_line_number n,
source_line_number last,
bool label_line ) {
/*************************************************************************/
if( _IsModel( NUMBERS ) ) {
if( n > 0 && n != last ) {
last = n;
CodeLineNum( n, label_line );
}
}
return( last );
}
extern void GenObject( void )
/*******************************/
{
block *blk;
block *next_blk;
instruction *ins;
source_line_number last_line;
int targets;
int i;
seg_id old;
label_handle lbl;
unsigned align;
fe_attr attr;
old = SetOP( AskCodeSeg() );
InitZeroPage();
last_line = 0;
attr = FEAttr( AskForLblSym( CurrProc->label ) );
blk = HeadBlock;
while( blk != NULL ) {
if( blk->label != CurrProc->label && blk->label != NULL ) {
last_line = DumpLineNum( blk->ins.hd.line_num, last_line, TRUE );
if( ( blk->class & ITERATIONS_KNOWN ) && blk->iterations >= 10 ) {
align = DepthAlign( DEEP_LOOP_ALIGN );
} else {
align = DepthAlign( blk->depth );
}
CodeLabel( blk->label, align );
if( ( blk->edge[ 0 ].flags & BLOCK_LABEL_DIES ) != 0
&& BlocksUnTrimmed ) {
TellCondemnedLabel( blk->label );
}
}
StartBlockProfiling( blk );
InitStackDepth( blk );
ins = blk->ins.hd.next;
next_blk = blk->next_block;
while( ins->head.opcode != OP_BLOCK ) {
if( ins->head.opcode == OP_NOP
&&( (ins->flags.nop_flags & NOP_SOURCE_QUEUE )
||(ins->flags.nop_flags == NOP_DBGINFO ))) // an end block
{
last_line = DumpLineNum(ins->head.line_num, last_line, TRUE);
} else {
last_line = DumpLineNum(ins->head.line_num, last_line, FALSE);
}
if( attr & FE_NAKED ) {
// don't want to generate anything except calls to pragma's for
// naked functions
if( ins->head.opcode == OP_CALL ) {
if( FindAuxInfo( ins->operands[ CALL_OP_ADDR ], CALL_BYTES ) != NULL ) {
GenObjCode( ins );
}
}
} else {
GenObjCode( ins );
}
ins = ins->head.next;
}
EndBlockProfiling();
if( blk->class & ( JUMP | BIG_JUMP ) ) {
if( BlockByBlock
|| next_blk == NULL
|| blk->edge[ 0 ].destination != next_blk->label ) {
// watch out for orphan blocks (no inputs/targets)
if( blk->targets > 0 ) {
GenJumpLabel( blk->edge[ 0 ].destination );
}
}
} else if( blk->class & RETURN ) {
FiniZeroPage();
GenEpilog();
} else if( blk->class & CALL_LABEL ) {
GenCallLabel( blk->edge[ 0 ].destination );
if( BlockByBlock ) {
if( next_blk == NULL ) {
GenJumpLabel( blk->v.next->label );
} else {
GenJumpLabel( next_blk->label );
}
}
} else if( blk->class & LABEL_RETURN ) {
GenLabelReturn();
}
if( !( blk->class & LABEL_RETURN ) ) { /* maybe pointer to dead label */
targets = blk->targets;
while( --targets >= 0 ) {
lbl = blk->edge[ targets ].destination;
TellReachedLabel( lbl );
if( ( blk->edge[ targets ].flags & DEST_LABEL_DIES ) != 0
&& BlocksUnTrimmed ) {
TellCondemnedLabel( lbl );
i = targets;
while( --i >= 0 ) {
if( blk->edge[ i ].destination == lbl ) {
blk->edge[ i ].flags &= ~DEST_LABEL_DIES;
}
}
}
}
}
if( BlocksUnTrimmed == FALSE
&& blk->label != CurrProc->label && blk->label != NULL ) {
TellCondemnedLabel( blk->label );
}
CurrBlock = blk;
FreeBlock();
blk = next_blk;
}
HeadBlock = blk;
BlockList = blk;
SetOP( old );
}
static bool GenId( block *blk, block *next ) {
/************************************************/
return( blk->gen_id > next->gen_id );
}
extern void BlocksSortedBy( bool (*bigger)( block *, block * ) ) {
/********************************************************************/
block *blk;
block *next;
bool change;
for(;;) {
blk = HeadBlock->next_block;
if( blk == NULL ) break;
change = FALSE;
for(;;) {
next = blk->next_block;
if( next == NULL ) break;
if( bigger( blk, next ) ) {
blk->prev_block->next_block = next;
if( next->next_block != NULL ) {
next->next_block->prev_block = blk;
}
blk->next_block = next->next_block;
if( blk->prev_block == HeadBlock ) {
HeadBlock->next_block = next;
}
next->prev_block = blk->prev_block;
blk->prev_block = next;
next->next_block = blk;
if( BlockList == next ) {
BlockList = blk;
}
change = TRUE;
}
blk = next;
}
if( change == FALSE ) break;
}
}
typedef struct {
block *first;
block *last;
} block_queue;
static void BQInit( block_queue *q ) {
/****************************************/
q->first = NULL;
q->last = NULL;
}
static bool BQEmpty( block_queue *q ) {
/********************************************/
return( q->first == NULL );
}
static void BQAdd( block_queue *q, block *element ) {
/*******************************************************/
if( BQEmpty( q ) ) {
element->next_block = NULL;
element->prev_block = NULL;
q->first = element;
q->last = element;
} else {
element->prev_block = q->last;
element->next_block = NULL;
q->last->next_block = element;
q->last = element;
}
}
static block *BQFirst( block_queue *q ) {
/******************************************/
return( q->first );
}
static block *BQNext( block_queue *q, block *curr ) {
/******************************************************/
return( curr->next_block );
}
static block *BQRemove( block_queue *q, block *blk ) {
/*******************************************************/
if( blk == NULL ) blk = q->first;
if( blk->prev_block ) blk->prev_block->next_block = blk->next_block;
if( blk->next_block ) blk->next_block->prev_block = blk->prev_block;
if( q->first == blk ) q->first = blk->next_block;
if( q->last == blk ) q->last = blk->prev_block;
return( blk );
}
static block_edge *FindLoopBackEdge( block *blk ) {
/**************************************************/
block_edge *edge;
block_num i;
for( i = 0; i < blk->targets; i++ ) {
edge = &blk->edge[ i ];
if( edge->destination == blk->loop_head ) return( edge );
if( edge->destination == blk ) return( edge );
}
return( NULL );
}
static instruction *FindCondition( block *blk ) {
/****************************************************/
instruction *cond;
cond = blk->ins.hd.prev;
while( !_OpIsCondition( cond->head.opcode ) ) {
if( cond->head.opcode == OP_BLOCK ) {
// _Zoiks( ZOIKS_XXX );
return( NULL );
}
cond = cond->head.prev;
}
return( cond );
}
#define NOT_TAKEN -1
#define DNA 0
#define TAKEN 1
static int PointerHeuristic( block *blk, instruction *cond ) {
/*****************************************************************/
int prediction;
blk = blk;
prediction = DNA;
if( _IsPointer( cond->type_class ) ) {
switch( cond->head.opcode ) {
case OP_CMP_EQUAL:
prediction = NOT_TAKEN;
break;
case OP_CMP_NOT_EQUAL:
prediction = TAKEN;
break;
}
}
return( prediction );
}
static int OpcodeHeuristic( block *blk, instruction *cond ) {
/****************************************************************/
int prediction;
name *op1;
name *op2;
blk = blk;
prediction = DNA;
op1 = cond->operands[ 0 ];
op2 = cond->operands[ 1 ];
switch( cond->head.opcode ) {
case OP_CMP_NOT_EQUAL:
if( _IsFloating( cond->type_class ) ) {
prediction = TAKEN;
}
break;
case OP_CMP_EQUAL:
if( _IsFloating( cond->type_class ) ) {
prediction = NOT_TAKEN;
}
break;
case OP_CMP_LESS:
case OP_CMP_LESS_EQUAL:
if( op2->n.class == N_CONSTANT ) {
if( op2->c.const_type == CONS_ABSOLUTE ) {
if( op2->c.int_value == 0 ) {
prediction = NOT_TAKEN;
}
}
}
break;
case OP_CMP_GREATER:
case OP_CMP_GREATER_EQUAL:
if( op2->n.class == N_CONSTANT ) {
if( op2->c.const_type == CONS_ABSOLUTE ) {
if( op2->c.int_value == 0 ) {
prediction = TAKEN;
}
}
}
break;
default:
prediction = DNA;
}
return( prediction );
}
static int Want( instruction *cond, int index ) {
/*****************************************************
We know which block we want, or rather its index in the
list of edges of the basic block, so this tells us
if the conditional will be TAKEN or NOT_TAKEN to get
to that block.
*/
int prediction;
prediction = TAKEN;
if( _TrueIndex( cond ) == 0 ) {
if( index == 1 ) {
prediction = NOT_TAKEN;
}
} else {
if( index == 0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -