varusage.c

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

C
486
字号
        if( HasTrueBase( op ) ) {
            TransferOneMemBlockUsage( op->i.base );
        }
    } else if ( op->n.class == N_MEMORY ) {
        TransferBlockUsage( op );
    }
}


static  void    TransferMemBlockUsage( block *blk )
/**************************************************
    Like TransferTempBlockUsage.
*/
{
    instruction *ins;
    int         i;

    ins = blk->ins.hd.next;
    while( ins->head.opcode != OP_BLOCK ) {
        i = ins->num_operands;
        while( --i >= 0 ) {
            TransferOneMemBlockUsage( ins->operands[ i ] );
        }
        if( ins->result != NULL ) {
            TransferOneMemBlockUsage( ins->result );
        }
        ins = ins->head.next;
    }
}


static void TransferOneTempFlag( name *t )
/****************************************/
{
    name        *alias;
    var_usage   usage;

    if( t->n.class == N_TEMP ) {
        t = DeAlias( t );
        alias = t;
        usage = EMPTY;
        do {
            usage |= alias->v.usage;
            alias = alias->t.alias;
        } while( alias != t );
        alias = t;
        do {
            alias->v.usage |= usage;
            alias = alias->t.alias;
        } while( alias != t );
    } else if( t->n.class == N_INDEXED ) {
        TransferOneTempFlag( t->i.index );
        if( HasTrueBase( t ) ) {
            TransferOneTempFlag( t->i.base );
        }
    }
}


extern  void    TransferTempFlags( void )
/****************************************
    Run through the program and for each variable reference, transfer
    the usage flags from each variable to all of its aliases.  (if we
    use the address of T1, we're effectively using the address of T1+1
    as well, etc).  We could traverse Names[N_TEMP] but it could be much
    longer than the block list.
*/
{
    block       *blk;
    instruction *ins;
    int         i;

    blk = HeadBlock;
    while( blk != NULL ) {
        ins = blk->ins.hd.next;
        while( ins->head.opcode != OP_BLOCK ) {
            i = ins->num_operands;
            while( --i >= 0 ) {
                TransferOneTempFlag( ins->operands[ i ] );
            }
            if( ins->result != NULL ) {
                TransferOneTempFlag( ins->result );
            }
            ins = ins->head.next;
        }
        blk = blk->next_block;
    }
    blk = HeadBlock;
    while( blk != NULL ) {
        TransferTempBlockUsage( blk );
        blk = blk->next_block;
    }
}


static  void    TransferMemoryFlags( void )
/******************************************
    If we use the address of FOOBAR, we're effectively using the address
    of FOOBAR+1 as well
*/
{
    name        *m;
    name        *same_sym;
    var_usage   usage;

    m = Names[  N_MEMORY  ];
    while( m != NULL ) {
        m->m.memory_flags = MF_EMPTY;
        m = m->n.next_name;
    }

    m = Names[  N_MEMORY  ];
    while( m != NULL ) {
        if( ( m->m.memory_flags & MF_VISITED ) == 0 ) {
            if( m->m.same_sym != NULL ) {
                // union together mem flags from all symbols that
                // are same and set all v.usage's to this union
                usage = m->v.usage;
                same_sym = m->m.same_sym;
                while( same_sym != m ) {
                    usage |= same_sym->v.usage;
                    same_sym = same_sym->m.same_sym;
                }
                m->v.usage = usage;
                same_sym = m->m.same_sym;
                while( same_sym != m ) {
                    same_sym->v.usage |= usage;
                    same_sym = same_sym->m.same_sym;
                    same_sym->m.memory_flags |= MF_VISITED;
                }
            }
            m->m.memory_flags |= MF_VISITED;
        }
        m = m->n.next_name;
    }
}


static  void    SearchDefUse( void )
/***********************************
    see FindReferences ^
*/
{
    block       *blk;
    instruction *ins;
    name        *name;
    int         i;
    bool        touched_non_op;

    blk = HeadBlock;
    for( ;; ) {
        touched_non_op = FALSE;
        ins = blk->ins.hd.next;
        while( ins->head.opcode != OP_BLOCK ) {
            if( ( ins->head.opcode == OP_CALL
               || ins->head.opcode == OP_CALL_INDIRECT )
             && ( ( ins->flags.call_flags & CALL_READS_NO_MEMORY ) == 0
/*21-nov-90*/  || ( ins->flags.call_flags & CALL_WRITES_NO_MEMORY ) == 0 ) ) {
                UseDefGlobals( blk );
                touched_non_op = TRUE;
            }
            i = ins->num_operands;
            while( -- i >= 0 ) {
                name = ins->operands[ i ];
                if( name->n.class == N_INDEXED ) {
                    Use( name->i.index, blk, EMPTY );
                    if( HasTrueBase( name ) ) {
                        Use( name->i.base, blk, USE_ADDRESS );
                    }
                } else {
                    if( ins->head.opcode == OP_LA && i == 0 ) {
                        Use( name, blk, USE_ADDRESS );
                    } else {
                        Use( name, blk, EMPTY );
                    }
                }
            }
            name = ins->result;
            if( name != NULL ) {
                if( name->n.class == N_INDEXED ) {
                    Use( name->i.index, blk, EMPTY );
                    if( HasTrueBase( name ) ) {
                        Use( name->i.base, blk, USE_ADDRESS );
                    }
                } else if( name->n.class == N_MEMORY ) {

                    /*   Any static data defined can be used in another block*/

                    name->v.usage |= USE_IN_ANOTHER_BLOCK;
                    Define( name, blk );
                } else if( name->n.class == N_TEMP ) {
                    Define( name, blk );
                }
            }
            ins = ins->head.next;
        }
        /* in/out/def/use ignored if BlockByBlock so don't worry about it */
        if( touched_non_op && !BlockByBlock ) {
            TransferAllMemBlockUsage();
        } else {
            TransferMemBlockUsage( blk );
        }
        TransferTempBlockUsage( blk );
        blk = blk->next_block;
        if( blk == NULL ) break;
    }
    TransferTempFlags();
    TransferMemoryFlags();
}


extern  void    FindReferences( void )
/*************************************
    Traverse the blocks an allocate a data_flow_def for each one if it
    is needed.  Then calculate which variables are USE_WITHIN_BLOCK,
    USE_IN_OTHER_BLOCK, DEF_IN_BLOCK and turn on their bits in the
    dataflo->def and dataflo->use sets.  Note that USE_WITHIN_BLOCK
    means that a variable is used before it is defined.
    DEF_WITHIN_BLOCK means that the entire variable is redefined by the
    block, so that no definitition of it in a previous block could flow
    through this block and be used in a subsequent block.  USE_IN_ANOTHER
    block means that a variable is used in more than one block.
*/
{
    block       *curr;

    curr = HeadBlock;
    while( curr != NULL ) {
        if( curr->dataflow == NULL ) {
            _Alloc( curr->dataflow, sizeof( data_flow_def ) );
        }
        _GBitInit( curr->dataflow->def         , EMPTY );
        _GBitInit( curr->dataflow->use         , EMPTY );
        _GBitInit( curr->dataflow->in          , EMPTY );
        _GBitInit( curr->dataflow->out         , EMPTY );
        _GBitInit( curr->dataflow->call_exempt , EMPTY );
        _GBitInit( curr->dataflow->need_load   , EMPTY );
        _GBitInit( curr->dataflow->need_store  , EMPTY );
        curr = curr->next_block;
    }
    SearchDefUse();
}

⌨️ 快捷键说明

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