generate.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 852 行 · 第 1/2 页
C
852 行
/****************************************************************************
*
* 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: High level code generation routines. Lots of action here.
*
****************************************************************************/
#include "standard.h"
#include "model.h"
#include "coderep.h"
#include "procdef.h"
#include "conflict.h"
#include "sysmacro.h"
#include "memcheck.h"
#include "opcodes.h"
#include "typedef.h"
#include "ptrint.h"
#include "feprotos.h"
#include "addrcnst.h"
extern void FreeAName( name * );
extern instruction* MakeNop( void );
extern void AddAnIns( block *, instruction * );
extern void UnFixEdges( void );
extern void AssignTemps( void );
extern void AssgnMoreTemps( block_num );
extern void FixEdges( void );
extern bool CommonSex( bool );
extern bool SetOnCondition( void );
extern bool BlockTrim( void );
extern bool DeadBlocks( void );
extern void MakeFlowGraph( void );
extern void InitRegTbl( void );
extern bool LoopInvariant( void );
extern bool LoopEnregister( void );
extern bool CommonInvariant( void );
extern bool TransLoops( bool );
extern bool IndVars( void );
extern void BlowAwayFreeLists( void );
extern bool BlkTooBig( void );
extern void FindReferences( void );
extern void FreeConflicts( void );
extern bool SplitConflicts( void );
extern void NullConflicts( var_usage );
extern void FreeAConflict( conflict_node * );
extern conflict_node *InMemory( conflict_node * );
extern void FreeProc( void );
extern void GenProlog( void );
extern void GenObject( void );
extern void SortBlocks( void );
extern void InitNames( void );
extern void InitMakeAddr( void );
extern void RegTreeInit( void );
extern void InitConflict( void );
extern void InitRT( void );
extern void InitIns( void );
extern void InitSegment( void );
extern void FiniSegment( void );
extern void PushPostOps( void );
extern void DeadTemps( void );
extern void AxeDeadCode( void );
extern bool InsDead( void );
extern void OptSegs( void );
extern void OptCloseMoves( void );
extern void Conditions( void );
extern void MakeConflicts( void );
extern void MakeLiveInfo( void );
extern void LiveInfoUpdate( void );
extern int ExpandOps( bool );
extern void FPRegAlloc( void );
extern void FixIndex( void );
extern void FixSegments( void );
extern void FixMemRefs( void );
extern bool RegAlloc( bool );
extern void LoopRegInvariant( void );
extern void Score( void );
extern void MergeIndex( void );
extern void FPExpand( void );
extern void FPOptimize( void );
extern void FPParms( void );
extern void ScoreInit( void );
extern void ScoreFini( void );
extern type_class_def TypeClass( type_def * );
extern void TypeInit( void );
extern void TypeFini( void );
extern void ObjInit( void );
extern void InitFP( void );
extern void ObjFini( void );
extern void AbortObj( void );
extern void FlushOpt( void );
extern hw_reg_set AllCacheRegs( void );
extern void AllocALocal( name * );
extern void ParmPropagate( void );
extern void InitStackMap( void );
extern void FiniStackMap( void );
extern void ProcMessage( msg_class );
extern sym_handle AskForLblSym( label_handle );
extern void InitQueue( void );
extern void FiniQueue( void );
extern void AbortQueue( void );
extern void TellFreeAllLabels( void );
extern bool FixReturns( void );
extern instruction_id Renumber( void );
extern void GenEpilog( void );
extern void SplitVars( void );
extern name *DeAlias( name * );
extern void AssignOtherLocals( void );
extern void BuildIndex( void );
extern bool CreateBreak( void );
extern void FixBreak( void );
extern void RemoveBreak( void );
extern instruction *NeedIndex( instruction * );
extern bool ConstFold( block * );
extern void DeadInstructions( void );
extern void Schedule( void );
extern bool CharsAndShortsToInts( void );
extern void LNBlip( source_line_number );
extern void SetInOut( block * );
extern bool LdStAlloc( void );
extern void LdStCompress( void );
extern void MemtoBaseTemp( void );
extern void FixMemBases( void );
extern bool BGInInline( void );
extern void AddCacheRegs( void );
extern void MulToShiftAdd( void );
extern bool TailRecursion( void );
extern bool PeepOpt( block *, block *(*)(block *,void *), block *, bool );
extern void PropNullInfo( void );
extern void ReConstFold( void );
extern void FlushQueue( void );
extern bool CalcDominatorInfo( void );
extern proc_def *CurrProc;
extern block *HeadBlock;
extern block *BlockList;
extern block *CurrBlock;
extern conflict_node *ConfList;
extern int InsId;
extern type_class_def ClassPointer;
extern pointer TypePtr;
extern name *Names[];
extern name *LastTemp;
extern bool BlockByBlock;
extern int InOptimizer;
extern bool HaveLiveInfo;
extern bool HaveDominatorInfo;
extern pointer_int FrlSize;
extern source_line_number SrcLine;
static bool abortCG;
extern void InitCG( void )
/****************************/
{
InOptimizer = 0;
InsId = 0;
CurrProc = NULL;
CurrBlock = NULL;
BlockList = NULL;
HeadBlock = NULL;
BlockByBlock = FALSE;
abortCG = FALSE;
InitFP();/* must be before InitRegTbl */
InitRegTbl();
ScoreInit();
InitQueue();
InitMakeAddr();
RegTreeInit();
InitIns();
InitConflict();
InitRT();
InitNames();
ObjInit();
ClassPointer = TypeClass( TypePtr );
InitSegment();
}
extern void AbortCG( void )
/*****************************/
{
abortCG = TRUE;
}
extern void FiniCG( void )
/****************************/
{
FiniQueue();
FiniSegment();
if( abortCG ) {
AbortObj();
}
ObjFini();
TellFreeAllLabels();
BlowAwayFreeLists();
ScoreFini();
}
static void AddANop( void )
/*****************************/
{
AddAnIns( BlockList, MakeNop() );
}
static void PreOptimize( void )
/*****************************************/
{
bool change;
if( _IsntModel( NO_OPTIMIZATION ) ) {
// CharsAndShortsToInts();
MakeMovAddrConsts();
PushPostOps();
DeadTemps();
InsDead();
MakeFlowGraph();
BlockTrim();
CommonSex( _IsModel( LOOP_OPTIMIZATION ) );
SetOnCondition();
BlockTrim();
AddANop();
if( _IsModel( LOOP_OPTIMIZATION ) ) {
change = FALSE;
if( TransLoops( FALSE ) ) {
change = TRUE;
}
if( LoopInvariant() ) {
change = TRUE;
}
if( change ) {
CommonSex(TRUE);
InsDead();
CommonInvariant();
}
if( IndVars() ) {
CommonSex(FALSE);
InsDead();
change = TRUE;
}
BlockTrim();
if( TransLoops( TRUE ) ) {
BlockTrim();
CommonSex( FALSE );
change = TRUE;
}
if( change ) {
ReConstFold();
}
LoopEnregister();
if( change ) {
BlockTrim();
}
}
MulToShiftAdd();
KillMovAddrConsts();
FindReferences();
} else {
MakeFlowGraph();
AddANop();
FindReferences();
}
}
static block *NextBlock( block *blk, void *parm )
/**********************************************************/
{
parm = parm;
return( blk->next_block );
}
static void PostOptimize( void )
/******************************************/
{
if( _IsntModel( NO_OPTIMIZATION ) ) {
// Run peephole optimizer again. Important: It is critical that the
// new instructions can be directly generated because RegAlloc is
// done by now. PeepOpt() is responsible for verifying that.
if( PeepOpt( HeadBlock, NextBlock, NULL, TRUE ) ) {
LiveInfoUpdate();
}
// this is important as BuildIndex cannot handle instructions with no operands
DeadInstructions();
BuildIndex();
DeadInstructions();
}
MergeIndex();
if( _IsntModel( NO_OPTIMIZATION ) ) {
#if !(_TARGET & _TARG_RISC)
//
// Calling Conditions() at this point has nice optimization effect,
// but doesn't working correctly right now. It optimizes conditions
// making them dependent from previous conditions codes, but riscifier
// generates XOR's which will trash cond. codes. Either Conditions()
// either riscifier must be fixed to handle this situation.
//
#if 0
// Get rid of unused conditions on variables level
// to decrease number of referenced vars in LdStAlloc() and Score()
if( _IsntTargetModel( STATEMENT_COUNTING ) ) {
Conditions();
DeadInstructions(); // cleanup junk after Conditions()
}
#endif
#endif
// OptCloseMoves(); // todo: merge constant moves before riscifier
LdStAlloc();
Score();
DeadInstructions(); // cleanup junk after Score()
// deRISCify before LoopRegInvariant() or Shedule() are run:
// they're moving RISCified pair.
LdStCompress();
// Reuse registers freed by deriscifier
// Score();
// DeadInstructions(); // cleanup junk after Score()
if( !BlockByBlock ) LoopRegInvariant();
#if !(_TARGET & _TARG_RISC)
// Get rid of remaining unused conditions on register level.
if( _IsntTargetModel( STATEMENT_COUNTING ) ) {
Conditions();
}
#endif
}
FPExpand();
if( _IsntModel( NO_OPTIMIZATION ) ) {
DeadInstructions(); // cleanup junk after Conditions()
// Run scheduler last, when all instructions are stable
if( _IsModel( INS_SCHEDULING ) ) {
HaveLiveInfo = FALSE;
Schedule(); /* NOTE: Schedule messes up live information */
LiveInfoUpdate();
HaveLiveInfo = TRUE;
}
// run this again in case Scheduler messed around with indices
if( PeepOpt( HeadBlock, NextBlock, NULL, TRUE ) ) {
LiveInfoUpdate();
}
}
FPOptimize();
}
static void FreeExtraTemps( name *last, block_num id )
/********************************************************/
{
name **owner;
name *temp;
owner = &Names[ N_TEMP ];
for( ;; ) {
temp = *owner;
if( temp == last ) break;
if( ( temp->v.usage & USE_IN_ANOTHER_BLOCK ) == 0
&& !_FrontEndTmp( temp )
&& temp->t.u.block_id == id ) {
*owner = temp->n.next_name;
FreeAName( temp );
} else {
owner = &temp->n.next_name;
}
}
}
static void ForceTempsMemory( void )
/**************************************/
{
name *op;
name *next;
ParmPropagate();
op = Names[ N_TEMP ];
while( op != LastTemp ) {
next = op->n.next_name;
if( ( op->v.usage & USE_IN_ANOTHER_BLOCK ) || _FrontEndTmp( op ) ) {
op = DeAlias( op );
op->v.usage |= NEEDS_MEMORY | USE_MEMORY;
while( op->v.conflict != NULL ) {
FreeAConflict( op->v.conflict );
}
}
op = next;
}
AssignOtherLocals();
op = Names[ N_MEMORY ];
while( op != NULL ) {
op->v.usage |= USE_IN_ANOTHER_BLOCK | USE_MEMORY;
if( op->v.conflict != NULL ) {
FreeAConflict( op->v.conflict );
op->v.conflict = NULL;
}
op = op->n.next_name;
}
LastTemp = Names[ N_TEMP ];
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?