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 + -
显示快捷键?