s37sel.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 372 行

C
372
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "standard.h"
#include "cgdefs.h"
#include "coderep.h"
#include "opcodes.h"
#include "sysmacro.h"
#include "addrname.h"
#include "tree.h"
#include "offset.h"
#include "seldef.h"

#include "s37sel.def"

extern  void            HWIntGen(offset,int);
extern  void            HWLTblGen(void *);
extern  void            HWLblDisp(void *);
extern  char           *AskLblRefName(label_handle);
extern  name           *GenIns(an);
extern  name           *AllocMemory(pointer,type_length,cg_class,type_class_def);
extern  name           *AllocIndex(name*,name*,type_length,type_class_def);
extern  name           *AllocTemp(type_class_def);
extern  cg_name         CGInteger(signed_32,cg_type);
extern  cg_type         SelType(unsigned_32);
extern  cg_name         CGBinary(cg_op,cg_name,cg_name,cg_type);
extern  an              TreeGen(tn);
extern  an              BGDuplicate(an);
extern  label_handle    AskForNewLabel(void);
extern  void           *AskForHWLabel( label_handle lbl );
extern  type_def       *TypeAddress(cg_type);
extern  signed_32       NumValues(select_list*,signed_32);
extern  void            BGDone(an);
extern  tn              TGLeaf(an);
extern  void            CodeLabel(label_handle,unsigned);
extern  unsigned        DepthAlign(unsigned);
extern  seg_id          AskBackSeg(void);
extern  seg_id          SetOP(seg_id);
extern  type_def        *TypeAddress(cg_type);
extern  name            *LoadTemp(name*,type_class_def);
extern  int             SelCompare(signed_32,signed_32);
extern  instruction     *NewIns(int);
extern  instruction     *MakeConvert(name*,name*,type_class_def,type_class_def);
extern  void            AddIns(instruction*);

extern  char            OptForSize;

#define MAX_JUMPS       1000
#define MIN_JUMPS       4            /* to make it worth while for jum*/
#define MAX_VALUES      1000

#define MAX_COST        0x7FFF

/*
   There are some magic numbers in this file in the calls to Balance(). they
   were found by looking at code and counting
   bytes, and cycles (RX = 2, Branch = 2, RR = 1)
*/

static  void    TableStart( label_handle lbl ) {
/**********************************************/

    HWLTblGen( AskForHWLabel( lbl ) );
}


static  void    TableEntry( label_handle lbl ) {
/**********************************************/

    HWLblDisp( AskForHWLabel( lbl ) );
}


static  int     Balance( signed_32 size, signed_32 time ) {
/*********************************************************/

    signed_32   balance;
    byte        opt_size;

    opt_size = OptForSize;
    if( opt_size < 25 ) {
        opt_size = 25;
    }
    balance = ( size * opt_size + time * ( 100 - opt_size ) ) / 100;
    if( balance > MAX_COST ) {
        balance = MAX_COST;
    }
    return( balance );
}


extern  int     ScanCost( select_node *s_node ) {
/***********************************************/

    select_list *list;
    signed_32   hi;
    signed_32   lo;
    signed_32   values;
    int         cost;
    int         type_length;
    cg_type     tipe;

    list = s_node->list;
    hi = s_node->upper;
    lo = s_node->lower;
    values = 0;
    while( list != NULL ) {
        if( SelCompare( list->low, hi ) > 0 ) break;
        values += list->high - list->low + 1;
        list = list->next;
    }
    tipe = SelType( hi - lo );
    if( values > MAX_VALUES ) {
        cost = MAX_COST;
    } else {
        type_length = TypeAddress( tipe )->length;
        cost = Balance( 38 + values * ( WORD_SIZE + type_length ),
                        27 + 8 * ( values / 2 ) );
    }
    return( cost );
}


extern  int     JumpCost( select_node *s_node ) {
/***********************************************/

    unsigned_32 in_range;
    int cost;

    in_range = s_node->upper - s_node->lower + 1;
    if( s_node->num_cases < MIN_JUMPS ) {
        cost = MAX_COST;
//  } else if( in_range > MAX_JUMPS || in_range < MIN_JUMPS ) {
    } else if(  in_range < MIN_JUMPS ) {
        cost = MAX_COST;
    } else {
        cost = Balance( 30 + 2 * in_range, 17 );
    }
    return( cost );
}


extern  int     IfCost( select_node *s_node, int entries ) {
/**********************************************************/

    signed_32   hi;
    signed_32   lo;
    signed_32   cost;
    signed_32   size;
    int         tipe_length;
    int         log_entries;

    hi = s_node->upper;
    lo = s_node->lower;
    tipe_length = TypeAddress( SelType( hi - lo ) )->length;
    size = tipe_length == 1 ? 8*entries : 12*entries;
    log_entries = 0;
    while( entries != 0 ) {
        log_entries++;
        entries = (unsigned_32)entries >> 2;
    }
    cost = Balance( size, 5*log_entries );
    if( cost >= MAX_COST ) {
        cost = MAX_COST - 1;
    }
    return( cost );
}


extern  tbl_control     *MakeScanTab( select_list *list, signed_32 hi,
                                      label_handle other, cg_type tipe,
                                      cg_type real_tipe ) {
/*****************************************************************/

    tbl_control         *table;
    label_handle        *tab_ptr;
    unsigned_32         cases;
    signed_32           lo;
    signed_32           to_sub;
    seg_id              old;
    select_list         *scan;
    signed_32           curr;

    cases = NumValues( list, hi );
    lo = list->low;
    _Alloc( table, sizeof( tbl_control ) + (cases-1) * sizeof( label_handle ) );
    table->size = cases;
    old = SetOP( AskBackSeg() );
    table->value_lbl = AskForNewLabel();
    CodeLabel( table->value_lbl, DepthAlign( 1 ) );
    table->lbl = AskForNewLabel();
    if( tipe != real_tipe ) {
        to_sub = lo;
    } else {
        to_sub = 0;
    }
    if( other == NULL ) {
        other = table->cases[ 0 ];  /* no otherwise? he bakes!*/
    }
    GenValuesForward( list, hi, lo, to_sub, TypeAddress( tipe ) );
    TableStart( table->lbl );
    tab_ptr = &table->cases[ 0 ];
    curr = lo;
    scan = list;
    for(;;) {
        *tab_ptr = scan->label;
        TableEntry( *tab_ptr );
        ++tab_ptr;
        if( SelCompare( curr, hi ) >= 0 ) break;
        if( SelCompare( curr, scan->high ) >= 0 ) {
            scan = scan->next;
            curr = scan->low;
        } else {
            ++curr;
        }
    }
    TableEntry( other );
    SetOP( old );
    return( table );
}


static  void    GenValuesForward( select_list *list, signed_32 hi,
                                  signed_32 lo, signed_32 to_sub,
                                  type_def *tipe ) {
/****************************************************************/

    signed_32           curr;

    curr = lo;
    for(;;) {
        HWIntGen( curr - to_sub, tipe->length );
        if( SelCompare( curr, hi ) >= 0 ) break;
        if( SelCompare( curr, list->high ) >= 0 ) {
            list = list->next;
            curr = list->low;
        }else{
            curr++;
        }
    }
}


extern  tbl_control     *MakeJmpTab( select_list *list, signed_32 lo,
                                     signed_32 hi, label_handle other ) {
/*****************************************************************/

    tbl_control         *table;
    label_handle        *tab_ptr;
    unsigned_32         cases;
    seg_id              old;

    cases = hi - lo + 1;
    _Alloc( table, sizeof( tbl_control ) + (cases-1) * sizeof( label_handle ) );
    old = SetOP( AskBackSeg() );
    table->lbl = AskForNewLabel();
    table->value_lbl = NULL;
    TableStart( table->lbl );
    table->size = cases;
    tab_ptr = &table->cases[ 0 ];
    for(;;) {
        if( SelCompare( lo, list->low ) < 0 ) {
            *tab_ptr = other;
        } else {
            *tab_ptr = list->label;
        }
        TableEntry( *tab_ptr );
        ++tab_ptr;
        if( SelCompare( lo, hi ) >= 0 ) break;
        if( SelCompare( lo, list->high ) >= 0 ) {
            list = list->next;
        }
        ++lo;
    }
    SetOP( old );
    return( table );
}


extern  name_def        *SelIdx( tbl_control *table, an node ) {
/**************************************************************/

    an          idxan;
    name       *idx;
    name       *temp;
    instruction *ins;

    /* use CG routines here to get folding*/
    idxan = BGDuplicate( node );
    idx = GenIns( idxan );
    temp = AllocTemp( WD );
    ins = MakeConvert( idx, temp, WD, idx->n.name_class );
    AddIns( ins );
    BGDone( idxan );
    idx = AllocIndex( temp, AllocMemory( table, 0, CG_TBL, WD ), 0, WD );
    return( idx );
}

extern  type_def        *SelNodeType( an node, bool is_signed ) {
/************************************************************/

    cg_type     unsigned_t;
    cg_type     signed_t;

    switch( node->tipe->length ) {
    case 1:
        unsigned_t = T_UINT_1;
        signed_t = T_INT_1;
        break;
    case 2: /* no support in switch */
    case 4:
        unsigned_t = T_UINT_4;
        signed_t = T_INT_4;
        break;
    default: /* an error */
        unsigned_t = NULL;
        signed_t =  NULL;
        break;
    }
    return( TypeAddress( is_signed ? signed_t : unsigned_t ) );
}

extern  void    MkSelOp( name *idx, cg_type tipe ) {
/**************************************************/

    instruction         *ins;

    ins = NewIns( 2 );
    ins->head.opcode = OP_ADD;
    ins->type_class = WD;
    ins->operands[ 0 ] = idx->i.index;
    ins->operands[ 1 ] = idx->i.index;
    ins->result = idx->i.index;
    AddIns( ins );
    ins = NewIns( 1 );
    ins->operands[ 0 ] = idx;
    ins->result = idx->i.index;
    ins->head.opcode = OP_SELECT;
    ins->type_class = tipe;
    ins->ins_flags |= INS_CC_USED;
    AddIns( ins );
}

⌨️ 快捷键说明

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