⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 object.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*
*                            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:  Generate object code from symbolic instructions.
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "model.h"
#include "procdef.h"
#include "sysmacro.h"
#include "cgaux.h"
#include "zoiks.h"
#include "feprotos.h"

extern  seg_id          AskCodeSeg( void );
extern  seg_id          SetOP(seg_id);
extern  void            CodeLabel(label_handle,unsigned);
extern  void            GenObjCode(instruction*);
extern  void            GenJumpLabel(pointer);
extern  void            GenEpilog( void );
extern  void            GenCallLabel(pointer);
extern  void            GenLabelReturn( void );
extern  void            TellCondemnedLabel(label_handle);
extern  void            FreeBlock( void );
extern  void            CodeLineNum(cg_linenum,bool);
extern  void            InitZeroPage( void );
extern  void            FiniZeroPage( void );
extern  void            TellReachedLabel(label_handle);
extern  unsigned        DepthAlign( unsigned );
extern  void            InitStackDepth(block*);
extern  block           *FindBlockWithLbl( label_handle label );
extern  void            Zoiks( int );
extern  void            ClearBlockBits( block_class );
extern  bool            ReDefinedBy( instruction *, name * );
extern  pointer         AskForLblSym(pointer);
extern  pointer         FindAuxInfo( name *, aux_class );
extern  void            StartBlockProfiling( block *blk );
extern  void            EndBlockProfiling( void );

extern  void            *EdgeStackInit( void );
extern  void            EdgeStackFini( void * );
extern  bool            EdgeStackEmpty( void * );
extern  void            EdgeStackPush( void *, block_edge * );
extern  block_edge      *EdgeStackPop( void * );

extern    block         *HeadBlock;
extern    block         *CurrBlock;
extern    block         *BlockList;
extern    proc_def      *CurrProc;
extern    bool          BlocksUnTrimmed;
extern    bool          BlockByBlock;
extern    byte          OptForSize;

static  source_line_number      DumpLineNum( source_line_number n,
                                             source_line_number last,
                                             bool label_line ) {
/*************************************************************************/

    if( _IsModel( NUMBERS ) ) {
        if( n > 0 && n != last ) {
            last = n;
            CodeLineNum( n, label_line );
        }
    }
    return( last );
}


extern  void    GenObject( void )
/*******************************/
{
    block               *blk;
    block               *next_blk;
    instruction         *ins;
    source_line_number  last_line;
    int                 targets;
    int                 i;
    seg_id              old;
    label_handle        lbl;
    unsigned            align;
    fe_attr             attr;

    old = SetOP( AskCodeSeg() );
    InitZeroPage();
    last_line = 0;
    attr = FEAttr( AskForLblSym( CurrProc->label ) );
    blk = HeadBlock;
    while( blk != NULL ) {
        if( blk->label != CurrProc->label && blk->label != NULL ) {
            last_line = DumpLineNum( blk->ins.hd.line_num, last_line, TRUE );
            if( ( blk->class & ITERATIONS_KNOWN ) && blk->iterations >= 10 ) {
                align = DepthAlign( DEEP_LOOP_ALIGN );
            } else {
                align = DepthAlign( blk->depth );
            }
            CodeLabel( blk->label, align );
            if( ( blk->edge[ 0 ].flags & BLOCK_LABEL_DIES ) != 0
              && BlocksUnTrimmed ) {
                TellCondemnedLabel( blk->label );
            }
        }
        StartBlockProfiling( blk );
        InitStackDepth( blk );
        ins = blk->ins.hd.next;
        next_blk = blk->next_block;
        while( ins->head.opcode != OP_BLOCK ) {
            if( ins->head.opcode == OP_NOP
              &&( (ins->flags.nop_flags & NOP_SOURCE_QUEUE )
                ||(ins->flags.nop_flags == NOP_DBGINFO   ))) // an end block
            {
                last_line = DumpLineNum(ins->head.line_num, last_line, TRUE);
            } else {
                last_line = DumpLineNum(ins->head.line_num, last_line, FALSE);
            }
            if( attr & FE_NAKED ) {
                // don't want to generate anything except calls to pragma's for
                // naked functions
                if( ins->head.opcode == OP_CALL ) {
                    if( FindAuxInfo( ins->operands[ CALL_OP_ADDR ], CALL_BYTES ) != NULL ) {
                        GenObjCode( ins );
                    }
                }
            } else {
                GenObjCode( ins );
            }
            ins = ins->head.next;
        }
        EndBlockProfiling();
        if( blk->class & ( JUMP | BIG_JUMP ) ) {
            if( BlockByBlock
             || next_blk == NULL
             || blk->edge[ 0 ].destination != next_blk->label ) {
                // watch out for orphan blocks (no inputs/targets)
                if( blk->targets > 0 ) {
                    GenJumpLabel( blk->edge[ 0 ].destination );
                }
            }
        } else if( blk->class & RETURN ) {
            FiniZeroPage();
            GenEpilog();
        } else if( blk->class & CALL_LABEL ) {
            GenCallLabel( blk->edge[ 0 ].destination );
            if( BlockByBlock ) {
                if( next_blk == NULL ) {
                    GenJumpLabel( blk->v.next->label );
                } else {
                    GenJumpLabel( next_blk->label );
                }
            }
        } else if( blk->class & LABEL_RETURN ) {
            GenLabelReturn();
        }
        if( !( blk->class & LABEL_RETURN ) ) { /* maybe pointer to dead label */
            targets = blk->targets;
            while( --targets >= 0 ) {
                lbl = blk->edge[ targets ].destination;
                TellReachedLabel( lbl );
                if( ( blk->edge[ targets ].flags & DEST_LABEL_DIES ) != 0
                  && BlocksUnTrimmed ) {
                    TellCondemnedLabel( lbl );
                    i = targets;
                    while( --i >= 0 ) {
                        if( blk->edge[ i ].destination == lbl ) {
                            blk->edge[ i ].flags &= ~DEST_LABEL_DIES;
                        }
                    }
                }
            }
        }
        if( BlocksUnTrimmed == FALSE
         && blk->label != CurrProc->label && blk->label != NULL ) {
            TellCondemnedLabel( blk->label );
        }
        CurrBlock = blk;
        FreeBlock();
        blk = next_blk;
    }
    HeadBlock = blk;
    BlockList = blk;
    SetOP( old );
}


static  bool    GenId( block *blk, block *next ) {
/************************************************/

    return( blk->gen_id > next->gen_id );
}


extern  void    BlocksSortedBy( bool (*bigger)( block *, block * ) ) {
/********************************************************************/
    block       *blk;
    block       *next;
    bool        change;

    for(;;) {
        blk = HeadBlock->next_block;
        if( blk == NULL ) break;
        change = FALSE;
        for(;;) {
            next = blk->next_block;
            if( next == NULL ) break;
            if( bigger( blk, next ) ) {
                blk->prev_block->next_block = next;
                if( next->next_block != NULL ) {
                    next->next_block->prev_block = blk;
                }
                blk->next_block = next->next_block;
                if( blk->prev_block == HeadBlock ) {
                    HeadBlock->next_block = next;
                }
                next->prev_block = blk->prev_block;
                blk->prev_block = next;
                next->next_block = blk;
                if( BlockList == next ) {
                    BlockList = blk;
                }
                change = TRUE;
            }
            blk = next;
        }
        if( change == FALSE ) break;
    }
}


typedef struct {
    block       *first;
    block       *last;
} block_queue;

static  void    BQInit( block_queue *q ) {
/****************************************/
    q->first = NULL;
    q->last = NULL;
}

static  bool    BQEmpty( block_queue *q ) {
/********************************************/
    return( q->first == NULL );
}

static  void    BQAdd( block_queue *q, block *element ) {
/*******************************************************/
    if( BQEmpty( q ) ) {
        element->next_block = NULL;
        element->prev_block = NULL;
        q->first = element;
        q->last = element;
    } else {
        element->prev_block = q->last;
        element->next_block = NULL;
        q->last->next_block = element;
        q->last = element;
    }
}

static block    *BQFirst( block_queue *q ) {
/******************************************/

    return( q->first );
}

static block    *BQNext( block_queue *q, block *curr ) {
/******************************************************/

    return( curr->next_block );
}

static  block   *BQRemove( block_queue *q, block *blk ) {
/*******************************************************/
    if( blk == NULL ) blk = q->first;
    if( blk->prev_block ) blk->prev_block->next_block = blk->next_block;
    if( blk->next_block ) blk->next_block->prev_block = blk->prev_block;
    if( q->first == blk ) q->first = blk->next_block;
    if( q->last  == blk ) q->last = blk->prev_block;
    return( blk );
}

static  block_edge *FindLoopBackEdge( block *blk ) {
/**************************************************/
    block_edge          *edge;
    block_num           i;

    for( i = 0; i < blk->targets; i++ ) {
        edge = &blk->edge[ i ];
        if( edge->destination == blk->loop_head ) return( edge );
        if( edge->destination == blk ) return( edge );
    }
    return( NULL );
}

static  instruction     *FindCondition( block *blk ) {
/****************************************************/

    instruction         *cond;

    cond = blk->ins.hd.prev;
    while( !_OpIsCondition( cond->head.opcode ) ) {
        if( cond->head.opcode == OP_BLOCK ) {
            // _Zoiks( ZOIKS_XXX );
            return( NULL );
        }
        cond = cond->head.prev;
    }
    return( cond );
}

#define NOT_TAKEN       -1
#define DNA             0
#define TAKEN           1

static  int     PointerHeuristic( block *blk, instruction *cond ) {
/*****************************************************************/

    int                 prediction;

    blk = blk;
    prediction = DNA;
    if( _IsPointer( cond->type_class ) ) {
        switch( cond->head.opcode ) {
        case OP_CMP_EQUAL:
            prediction = NOT_TAKEN;
            break;
        case OP_CMP_NOT_EQUAL:
            prediction = TAKEN;
            break;
        }
    }
    return( prediction );
}

static  int     OpcodeHeuristic( block *blk, instruction *cond ) {
/****************************************************************/

    int                 prediction;
    name                *op1;
    name                *op2;

    blk = blk;
    prediction = DNA;
    op1 = cond->operands[ 0 ];
    op2 = cond->operands[ 1 ];
    switch( cond->head.opcode ) {
    case OP_CMP_NOT_EQUAL:
        if( _IsFloating( cond->type_class ) ) {
            prediction = TAKEN;
        }
        break;
    case OP_CMP_EQUAL:
        if( _IsFloating( cond->type_class ) ) {
            prediction = NOT_TAKEN;
        }
        break;
    case OP_CMP_LESS:
    case OP_CMP_LESS_EQUAL:
        if( op2->n.class == N_CONSTANT ) {
            if( op2->c.const_type == CONS_ABSOLUTE ) {
                if( op2->c.int_value == 0 ) {
                    prediction = NOT_TAKEN;
                }
            }
        }
        break;
    case OP_CMP_GREATER:
    case OP_CMP_GREATER_EQUAL:
        if( op2->n.class == N_CONSTANT ) {
            if( op2->c.const_type == CONS_ABSOLUTE ) {
                if( op2->c.int_value == 0 ) {
                    prediction = TAKEN;
                }
            }
        }
        break;
    default:
        prediction = DNA;
    }
    return( prediction );
}

static  int     Want( instruction *cond, int index ) {
/*****************************************************
    We know which block we want, or rather its index in the
    list of edges of the basic block, so this tells us
    if the conditional will be TAKEN or NOT_TAKEN to get
    to that block.
*/

    int         prediction;

    prediction = TAKEN;
    if( _TrueIndex( cond ) == 0 ) {
        if( index == 1 ) {
            prediction = NOT_TAKEN;
        }
    } else {
        if( index == 0 ) {

⌨️ 快捷键说明

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