insutil.c

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

C
492
字号
/****************************************************************************
*
*                            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:  Instruction data manipulation routines.
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "conflict.h"
#include "opcodes.h"
#include "pattern.h"
#include "procdef.h"
#include "sysmacro.h"
#include "zoiks.h"

typedef enum {
        CB_FOR_INS1             = 0x01,
        CB_FOR_INS2             = 0x02,
        CB_NONE                 = 0x00
} conflict_bits;

typedef struct  conflict_info {
        conflict_node   *conf;
        conflict_bits   flags;
} conflict_info;

extern    block         *HeadBlock;
extern    conflict_node *ConfList;
extern    bool          HaveLiveInfo;

extern  void            FreeIns(instruction*);
extern  void            UpdateLive(instruction*,instruction*);
extern  name            *DeAlias(name*);
extern  int             CountIns(block*);

#define MAX_CONF_INFO   (2*( MAX_OPS_PER_INS+1 )+1)
static  int             CurrInfo;
static  conflict_info   ConflictInfo[ MAX_CONF_INFO ];


static void RenumFrom( instruction *ins ) {
/*****************************************/

    block               *blk;
    instruction_id      id;

    if( ins->head.opcode == OP_BLOCK ) {
        Renumber();
    } else {
        id = ins->id;
        ins = ins->head.next;
        for( ;; ) {
            while( ins->head.opcode != OP_BLOCK ) {
                ++id;
                if( ins->id > id ) return;
                ins->id = id;
                ins = ins->head.next;
            }
            blk = _BLOCK( ins )->next_block;
            if( blk == NULL ) break;
            ins = blk->ins.hd.next;
        }
    }
}


static  conflict_info   *AddConfInfo( conflict_node *conf ) {
/***********************************************************/

    conflict_info       *info;

    if( conf->state & CONF_VISITED ) {
        info = &ConflictInfo[ 0 ];
        for( info = &ConflictInfo[ 0 ];; ++info ) {
            if( info->conf == conf ) return( info );
        }
    } else {
        info = &ConflictInfo[ CurrInfo++ ];
        info->conf = conf;
        conf->state |= CONF_VISITED;
    }
    return( info );
}


static  void    FindNameConf( name *name, instruction *ins,
                              instruction *other, conflict_bits for_which ) {
/***********************************************************************/

    conflict_node       *conf;
    conflict_info       *info;

    if( name->n.class == N_INDEXED ) {
        name = name->i.index;
    }
    if( name->n.class == N_TEMP ) {
        name = DeAlias( name );
    } else if( name->n.class != N_MEMORY ) {
        return;
    }
    conf = name->v.conflict;
    info = NULL;
    while( conf != NULL && info == NULL ) {
        if( conf->ins_range.first == ins
         || conf->ins_range.first == other
         || conf->ins_range.last == ins
         || conf->ins_range.last == other ) {
            info = AddConfInfo( conf );
            info->flags |= for_which;
        }
        conf = conf->next_for_name;
    }
}


static  void    FindAllConflicts( instruction *ins,
                                 instruction *other, conflict_bits for_which ) {
/***************************************************************************/

    int         i;

    i = ins->num_operands;
    while( --i >= 0 ) {
        FindNameConf( ins->operands[ i ], ins, other, for_which );
    }
    if( ins->result != NULL ) {
        FindNameConf( ins->result, ins, other, for_which );
    }
}


static  void    MakeConflictInfo( instruction *ins1, instruction *ins2 ) {
/************************************************************************/

    int                 i;
    conflict_info       *info;

    for( i = 0; i < MAX_CONF_INFO; ++i ) {
        ConflictInfo[ i ].conf = NULL;
        ConflictInfo[ i ].flags = CB_NONE;
    }
    CurrInfo = 0;
    FindAllConflicts( ins1, ins2, CB_FOR_INS1 );
    FindAllConflicts( ins2, ins1, CB_FOR_INS2 );
    for( info = ConflictInfo; info->conf != NULL; ++info ) {
        info->conf->state &= ~CONF_VISITED;
    }
}


extern  void    PrefixInsRenum( instruction *ins, instruction *pref, bool renum ) {
/*****************************************************************/

    conflict_info       *info;
    conflict_node       *conf;
    block               *blk;
    instruction         *next;

/*   Link the new instruction into the instruction ring*/
/*   If renum = true, assign id and renumber. renum can be false only */
/*   if you're going to call Renumber() manually. */

    _INS_NOT_BLOCK( pref );
    pref->head.prev = ins->head.prev;
    pref->head.prev->head.next = pref;
    pref->head.next = ins;
    ins->head.prev = pref;
    if( ins->head.opcode != OP_BLOCK ) {
        pref->head.line_num = ins->head.line_num;
        ins->head.line_num = 0;

        pref->stk_entry = ins->stk_entry;
        pref->stk_exit = ins->stk_entry;
        // pref->s.stk_extra = ins->s.stk_extra;
        pref->sequence = ins->sequence;

        pref->id = ins->id;
    } else {
        pref->head.line_num = 0;

        if ( renum ) {
             /*
             * Oops. There is no id in OP_BLOCK and assigned id will be invalid.
             * This condition happens sometimes in loop optimizer.
             * NOTE: this case can be a bug. It means that we're trying to add
             * last instruction to the block. But other code can expect that
             * last instruction is NOP, but it'll not.
             * Currently we'll try to find next instruction with valid id.
             */
            next = ins;
            for (;;) {
                blk = _BLOCK( next )->next_block;
                if( blk == NULL ) {
                    Zoiks( ZOIKS_141 );
                    break;
                }
                next = blk->ins.hd.next;
                if ( next->head.opcode != OP_BLOCK ) break;
            }
            pref->id = next->id;
        }
    }

    if ( renum ) {
        RenumFrom( pref );
    }

    if( HaveLiveInfo ) {

/*      move the first/last pointers of any relevant conflict nodes */

        if( ins->head.opcode != OP_BLOCK ) {
            MakeConflictInfo( pref, ins );
            for( info = ConflictInfo; info->conf != NULL; ++info ) {
                if( info->flags & CB_FOR_INS1 ) {
                    conf = info->conf;
                    if( !( info->flags & CB_FOR_INS2 ) ) {
                        if( conf->ins_range.last == ins ) {
                            conf->ins_range.last = pref;
                        }
                    }

⌨️ 快捷键说明

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