blktrim.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 513 行 · 第 1/2 页

C
513
字号
/****************************************************************************
*
*                            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:  Clean up basic blocks in a routine.
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "sysmacro.h"
#include "procdef.h"

extern    block         *HeadBlock;
extern    block         *BlockList;
extern    bool          BlocksUnTrimmed;
extern    proc_def      *CurrProc;


extern  void            TellScrapLabel( label_handle );
extern  void            FreeIns( instruction * );
extern  void            FreeABlock( block * );
extern  instruction_id  Renumber( void );
extern  void            RemoveEdge( block_edge * );

/* forward declarations */
extern  void    RemoveInputEdge( block_edge *edge );
extern  bool    BlockTrim( void );

static  instruction     *FindOneCond( block *blk )
/************************************************/
{
    instruction *ins;
    instruction *cond;

    cond = NULL;
    for( ins = blk->ins.hd.next;
         ins->head.opcode != OP_BLOCK; ins = ins->head.next ) {
         if( _OpIsCondition( ins->head.opcode ) ) {
             if( cond != NULL ) return( NULL );
             cond = ins;
         }
    }
    return( cond );
}


static  void    UnMarkBlocks( void )
/**********************************/
{
    block       *blk;

    blk = HeadBlock;
    while( blk != NULL ) {
        blk->class &= ~BLOCK_VISITED;
        blk = blk->next_block;
    }
}


static  void    MarkReachableBlocks( void )
/*****************************************/
/* Written NON-Recursively for a very good reason. (stack blew up)*/
{
    block       *blk;
    block       *son;
    bool        change;
    int         i;

    for( ;; ) {
        change = FALSE;
        blk = HeadBlock;
        while( blk != NULL ) {
            if( blk->class & ( BIG_LABEL | BLOCK_VISITED | SELECT ) ) {
                blk->class |= BLOCK_VISITED;
                i = blk->targets;
                while( --i >= 0 ) {
                    son = blk->edge[ i ].destination;
                    if( ( son->class & BLOCK_VISITED ) == EMPTY ) {
                        son->class |= BLOCK_VISITED;
                        change = TRUE;
                    }
                }
            }
            blk = blk->next_block;
        }
        if( change == FALSE ) break;
    }
}


extern  int     CountIns( block *blk )
/************************************/
{
    int         num_instrs;
    instruction *ins;

    num_instrs = 0;
    ins = blk->ins.hd.next;
    while( ins->head.opcode != OP_BLOCK ) {
        num_instrs++;
        ins = ins->head.next;
    }
    return( num_instrs );
}


static  bool    FindBlock( block *target )
/****************************************/
{
    block       *blk;

    blk = HeadBlock;
    while( blk != NULL ) {
        if( blk == target ) return( TRUE );
        blk = blk->next_block;
    }
    return( FALSE );
}


extern  void    RemoveBlock( block *blk )
/***************************************/
{
    int         i;
    unsigned    last_line;
    block       *chk;
    block       *next;
    instruction *next_ins;

    if( blk->prev_block != NULL ) {
        blk->prev_block->next_block = blk->next_block;
    }
    if( blk->next_block != NULL ) {
        blk->next_block->prev_block = blk->prev_block;
    }
    i = 0;
    while( i < blk->targets ) {
        /* block may have already been removed by dead code removal*/
        if( FindBlock( blk->edge[ i ].destination ) ) {
            RemoveInputEdge( & blk->edge[ i ] );
        }
        ++ i;
    }
    last_line = blk->ins.hd.line_num;
    for( ;; ) {
        next_ins = blk->ins.hd.next;
        if( next_ins == (instruction *)&blk->ins ) break;
        if( next_ins->head.line_num != 0 ) {
            last_line = next_ins->head.line_num;
        }
        FreeIns( next_ins );
    }
    /*
        Move the last line number from the block being deleted to the head
        of the next block in source order, if that block doesn't already
        have a line number on it.
    */
    if( blk->next_block != NULL && blk->next_block->gen_id == (blk->gen_id + 1) ) {
        /* quick check to see if following block is next one in src order */
        next = blk->next_block;
    } else {
        next = NULL;
        for( chk = HeadBlock; chk != NULL; chk = chk->next_block ) {
            if( (chk != blk)
                && (chk->gen_id > blk->gen_id)
                && (next == NULL || next->gen_id > chk->gen_id) ) {
                next = chk;
            }
        }
    }
    if( next != NULL && next->ins.hd.line_num == 0 ) {
        next->ins.hd.line_num = last_line;
    }
    if( HeadBlock == blk ) {
        HeadBlock = blk->next_block;
    }
    if( BlockList == blk ) {
        BlockList = blk->prev_block;
        if( BlockList == NULL ) {
            BlockList = HeadBlock;
        }
    }
    TellScrapLabel( blk->label );
    if( blk->dataflow != NULL ) {
        _Free( blk->dataflow, sizeof( data_flow_def ) );
    }
    FreeABlock( blk );
}


extern  void    RemoveInputEdge( block_edge *edge )
/*************************************************/
{
    block       *dest;
    block_edge  *prev;

    if( ( edge->flags & DEST_IS_BLOCK ) == EMPTY ) return;
    dest = edge->destination;
    dest->inputs --;
    prev = dest->input_edges;
    if( prev == edge ) {
        dest->input_edges = edge->next_source;
    } else {
        while( prev->next_source != edge ) {
            prev = prev->next_source;
        }
        prev->next_source = edge->next_source;
    }
}


extern  void    MoveHead( block *old, block *new )
/*************************************************

    We're eliminating a loop header, so move it the the new
    block and point all loop_head pointers to the new block.
*/
{
    block       *blk;

    if( !( old->class & LOOP_HEADER ) ) return;
    for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
        if( blk->loop_head == old ) {
            blk->loop_head = new;
        }
    }
    new->class |= old->class & (LOOP_HEADER|ITERATIONS_KNOWN);
    old->class &= ~( LOOP_HEADER | ITERATIONS_KNOWN );
    new->iterations = old->iterations;
    new->loop_head = old->loop_head;
    old->loop_head = new;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?