cdopt.c

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

C
1,978
字号
/****************************************************************************
*
*                            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 "plusplus.h"
#include "cgfront.h"
#include "cdopt.h"
#include "cgswitch.h"
#include "errdefns.h"
#include "fnovload.h"
#include "ring.h"
#include "vstk.h"
#include "initdefs.h"
#include "pcheader.h"
#include "rtngen.h"
#include "context.h"
#include "stats.h"
#ifndef NDEBUG
#include "pragdefn.h"
#endif

#define TIS_DEFS                /* types in input stack     */ \
  TIS_DEF( DT_INPUT  )          /* - dtor, unprocessed      */ \
, TIS_DEF( DT_STR    )          /* - dtor, stretching       */ \
, TIS_DEF( DT_NO_OPT )          /* - dtor, no optimization  */ \
, TIS_DEF( DT_OPT    )          /* - dtor, optimized ok     */


#define CDOPT_DEFS              /* types of optimization    */ \
  CDO_DEF( CDOPT_DTOR  )        /* - dtor                   */ \
, CDO_DEF( CDOPT_CTOR  )        /* - default ctor           */ \
, CDO_DEF( CDOPT_OPREQ )        /* - operator =             */

typedef enum {                  // CDOPT_TYPE -- type of optimization
    #define CDO_DEF(a) a
    CDOPT_DEFS
    #undef CDO_DEF
,   MAX_CDOPT_TYPE
} CDOPT_TYPE;

typedef enum {                  // TIS -- types in input stack
    #define DT_DEF(a) a
    DT_DEFS
    #undef DT_DEF
,   MAX_TIS_TYPE
} TIS;


struct cdopt_cache              // CDOPT_CACHE -- cache from CLASSINFO
{   CD_DESCR* cdopt_ctor;       // - NULL or descriptor for default ctor
    CD_DESCR* cdopt_dtor;       // - NULL or descriptor for dctor
    CD_DESCR* cdopt_opeq;       // - NULL or descriptor for operator =
};


typedef struct memb_vfuns       MEMB_VFUNS;
typedef struct cl_elem          CL_ELEM;
typedef struct acc_fun          ACC_FUN;


struct acc_fun                  // ACC_SYM -- function accessed directly
{   ACC_FUN* next;              // - next symbol
    SYMBOL fun;                 // - function accessed
};

struct cd_descr                 // CD_DESCR -- ctor/dtor description
{   CD_DESCR*       next;       // - next in cache ring
    const MEMB_VFUNS* mfuns;    // - member functions
    TYPE        orig_type;      // - originating class type
    CL_ELEM*    elements;       // - significant elements
    ACC_FUN*    accessed;       // - functions accessed
    CDOPT_TYPE  opt;            // - type of optimization
    unsigned    err_occurred:1; // - TRUE ==> error detected during lookup
    unsigned    has_vbt     :1; // - TRUE ==> has virtual base table
    unsigned    has_vft     :1; // - TRUE ==> has virtual function table
    unsigned    has_acc     :1; // - TRUE ==> has functions accessed
    unsigned    chk_acc     :1; // - TRUE ==> accesses have been checked
    PAD_UNSIGNED
};

struct cl_elem                  // CL_ELEM -- significant class element
{   CL_ELEM* next;              // - next in ring
    TYPE cltype;                // - class/array type
    SYMBOL cdtor;               // - CTOR,DTOR,OP=
    SYMBOL sym;                 // - symbol, when data element
    CD_DESCR* descr;            // - description of class for element
    target_offset_t offset;     // - offset
    TOB otype;                  // - type of object
    unsigned    elim_intermed:1;// - intermediate function can be eliminated
    unsigned    cannot_define:1;// - function could not be defined
    unsigned    must_call:1;    // - item must be ctored,dtored,assigned
    PAD_UNSIGNED
};

typedef struct stkin STKIN;
struct stkin                    // STKIN -- stack (input) entry
{   CD_DESCR* info;             // - information for class being expanded
    CL_ELEM* elem;              // - element being expanded
};

typedef struct                  // CDOPT_DEFN : defines CDOPT type
{   MEMB_VFUNS const* vfuns;    // - virtual functions
    CDOPT_TYPE otype;           // - type of CDOPT
    unsigned :0;                // alignment
} CDOPT_DEFN;

typedef struct                  // CL_EXPAND -- expansion information
{   CD_DESCR* info;             // - class description
    STKIN* source;              // - source item
} CL_EXPAND;

struct memb_vfuns               // VFT for CD_DESCR
{   boolean (*basePushable)     // - base class pushable ?
        ( BASE_CLASS* );        // - - base class
    boolean (*membPushable)     // - member pushable ?
        ( SYMBOL );             // - - symbol for member
    SYMBOL (*find)              // - find symbol for type
        ( CL_ELEM* );           // - - type
    boolean (*optimizable)      // - optimizable function ?
        ( CL_ELEM* );           // - - class entry
    boolean (*include)          // - include function after expansion ?
        ( CL_ELEM* );           // - - class entry
    SYMBOL (*array_cdtor)       // - get array cdtor
        ( SYMBOL );             // - - array member symbol
    void (*schedule_acc_chk)    // - schedule access check
        ( TYPE );               // - - type for function
    SYMBOL (*array_acc)         // - get symbol for array access
        ( TYPE );               // - - array symbol
#ifdef XTRA_RPT
    void (*rpt_desc)            // - report: descriptor defined
        ( void );
    void (*elem_proc)           // - report: element processed
        ( void );
    void (*elem_kept)           // - report: element kept
        ( void );
#endif
};

typedef struct                  // CL_ITER: iteration info. per class
{   CD_DESCR    *info;          // - class information
    CL_ELEM     *elem;          // - current element
    TOB comp_otype;             // - TOB for component being expanded
} CL_ITER;

struct cdopt_iter               // CDOPT_ITER: iterator for traversals
{   CD_DESCR    *info;          // - original class information
    VSTK_CTL    stack;          // - stack of elements
    BASE_CLASS  *vbase;         // - NULL or virtual base
    target_offset_t off_comp;   // - offset of component being expanded
    target_offset_t off_elem;   // - offset of element (exact)
    target_offset_t off_vbase;  // - offset of virtual base
    TITER       orig_otype;     // - object type of original component
    unsigned    gened_comp  :1; // - TRUE ==> gen'ed component element
    unsigned    at_end      :1; // - TRUE ==> processing TITER_NONE at end
    PAD_UNSIGNED
};

static carve_t carveCD_DESCR;       // carving control: descriptors
static carve_t carveCL_ELEM;        // carving control: elements
static carve_t carveCDOPT_ITER;     // carving control: iterators
static carve_t carveACC_FUN;        // carving control: functions accessed
static carve_t carveCDOPT_CACHE;    // carving control: caching

static CDOPT_CACHE allDescriptors;  // all allocated descriptors
static VSTK_CTL stackSTKIN;         // stack of elements

ExtraRptCtr( ctr_ctor_desc );   // # ctor descriptors
ExtraRptCtr( ctr_ctor_elem );   // # ctor elements processed
ExtraRptCtr( ctr_ctor_kept );   // # ctor elements kept
ExtraRptCtr( ctr_dtor_desc );   // # dtor descriptors
ExtraRptCtr( ctr_dtor_elem );   // # dtor elements processed
ExtraRptCtr( ctr_dtor_kept );   // # dtor elements kept
ExtraRptCtr( ctr_opeq_desc );   // # opeq descriptors
ExtraRptCtr( ctr_opeq_elem );   // # opeq elements processed
ExtraRptCtr( ctr_opeq_kept );   // # opeq elements kept
ExtraRptCtr( ctr_caches    );   // # caches

#ifndef NDEBUG

#include <stdio.h>
#include "dbg.h"
#include "toggle.h"


static char* tob_names[] = {
    #define TOB_DEF(a) # a
    TOB_DEFS
    #undef TOB_DEF
};


static char* cdopt_names[] = {
    #define CDO_DEF(a) # a
    CDOPT_DEFS
    #undef CDO_DEF
};


static char* tis_names[] = {
    #define TIS_DEF(a) # a
    TIS_DEFS
    #undef TIS_DEF
};


static char* titer_names[] = {
    #define TITER_DEF(a) # a
    TITER_DEFS
    #undef TITER_DEF
};


char* __fmt_TOB( TOB tob )      // FORMAT TOB
{
    return ( tob >= MAX_TOB_DEF ) ? "*** BAD TOB ***" : tob_names[ tob ];
}


char* __fmt_CDOPT_TYPE( CDOPT_TYPE cdot )
{
    return ( cdot >= MAX_CDOPT_TYPE )
           ? "*** BAD CDOPT ***"
           : cdopt_names[ cdot ];
}


char* __fmt_TIS( TIS tis )
{
    return ( tis >= MAX_TIS_TYPE ) ? "*** BAD TIS ***" : tis_names[ tis ];
}


char* __fmt_TITER( TITER val )
{
    return ( val >= MAX_TITER_DEF )
           ? "*** BAD TITER ***"
           : titer_names[ val ];
}


void DumpCdoptIter(             // DUMP ITERATOR
    CDOPT_ITER* iter,           // - iterator
    const char* text1,          // - and some text
    const char* text2 )         // - and some text
{
    if( PragDbgToggle.cdopt ) {
        printf( "CDOPT_ITER[%x] info(%x) orig_otype(%s) %s %s\n"
                "    offsets: comp(%x) elem(%x) vbase(%x) gened_comp(%x) at_end(%x)\n"
              , iter
              , iter->info
              , __fmt_TITER( iter->orig_otype )
              , text1
              , text2
              , iter->off_comp
              , iter->off_elem
              , iter->vbase
              , iter->gened_comp
              , iter->at_end
              );
    }
}


void DumpCdoptClElem(           // DUMP A CLASS ELEMENT
    CL_ELEM* elem )             // - the element
{
    if( elem != NULL ) {
        printf( "  CL_ELEM[%x]: next(%x) type(%x) offset(%x) type(%s)\n"
                "       descr(%x) cdtor(%s) sym(%s)\n"
                "       elim_intermed(%d) cannot_define(%d) must_call(%d)\n"
              , elem
              , elem->next
              , elem->cltype
              , elem->offset
              , __fmt_TOB( elem->otype )
              , elem->descr
              , DbgSymNameFull( elem->cdtor )
              , DbgSymNameFull( elem->sym )
              , elem->elim_intermed
              , elem->cannot_define
              , elem->must_call
              );
    }
}


void DumpCdoptInfo(             // DUMP CD_DESCR
    CD_DESCR *info )            // - control information
{
    CL_ELEM* elem;              // - current element
    ACC_FUN* af;                // - current function access

    if( PragDbgToggle.cdopt ) {
        printf( "CD_DESCR[%x]: type(%x) opt(%s) elements(%x)\n"
                "              accessed(%x) vft(%d) vbt(%d)\n"
              , info
              , info->orig_type
              , __fmt_CDOPT_TYPE( info->opt )
              , info->elements
              , info->accessed
              , info->has_vft
              , info->has_vbt );
        DumpFullType( info->orig_type );
        RingIterBeg( info->elements, elem ) {
            DumpCdoptClElem( elem );
        } RingIterEnd( elem )
        RingIterBeg( info->accessed, af ) {
            printf( "       Accessed: %s\n", DbgSymNameFull( af->fun ) );
        } RingIterEnd( af )
    }
}

void DumpCdoptIn(               // DUMP INPUT STACK ENTRY
    STKIN *inp,                 // - input stack
    const char* text )          // - descriptive text
{
    if( PragDbgToggle.cdopt ) {
        printf( "STKIN[%x]: info(%x) elem(%x) %s\n"
              , inp
              , inp->info
              , inp->elem
              , text );
        DumpCdoptClElem( inp->elem );
    }
}


void DumpClIter(                // DUMP STACK ENTRY
    CL_ITER* exp,               // - stack entry
    const char* text )          // - and some text
{
    if( PragDbgToggle.cdopt ) {
        printf( "CL_ITER[%x]: info(%x) elem(%x) comp_otype(%s) %s\n"
              , exp
              , exp->info
              , exp->elem
              , __fmt_TOB( exp->comp_otype )
              , text
              );
        DumpCdoptClElem( exp->elem );
    }
}


static void dumpRing(           // DUMP A RING
    CD_DESCR* cache )           // - ring to be dumped
{
    CD_DESCR* dump;             // - current descriptor

    RingIterBeg( cache, dump ) {
        DumpCdoptInfo( dump );
    } RingIterEnd( dump )
}


void DumpCdoptCaches(           // DUMP CDOPT CACHES
    void )
{
    int saved = PragDbgToggle.cdopt;

    PragDbgToggle.cdopt = 1;
    dumpRing( allDescriptors.cdopt_ctor );
    dumpRing( allDescriptors.cdopt_dtor );
    dumpRing( allDescriptors.cdopt_opeq );
    PragDbgToggle.cdopt = saved;
}




#else

#define DumpCdoptInfo(a)
#define DumpCdoptIter(a,b,c)
#define DumpCdoptClElem(a)
#define DumpCdoptIn(a,b)
#define DumpClIter(a,b)

#endif

//--------------------------------------------------------------------
// ACC_FUN support
//--------------------------------------------------------------------

static void addAccFun(          // ADD A FUNCTION ACCESS
    CD_DESCR* descr,            // - descriptor
    SYMBOL fun )                // - the function
{
    ACC_FUN* curr;              // - current access
    ACC_FUN* af;                // - access for function

    if( fun != NULL ) {
        if( ArrayType( fun->sym_type ) != NULL ) {
            fun = (*descr->mfuns->array_acc)
                    ( ArrayBaseType( fun->sym_type ) );
        }
    }
    if( fun != NULL ) {
        af = NULL;
        RingIterBeg( descr->accessed, curr ) {
            if( fun == curr->fun ) {
                af = curr;
                break;
            }
        } RingIterEnd( curr )
        if( af == NULL ) {
            af = RingCarveAlloc( carveACC_FUN, &descr->accessed );
            af->fun = fun;
            descr->has_acc = TRUE;
        }
    }
}


void CDoptNoAccFun(             // INDICATE FUNCTIONS ACCESSED FOR CLASS
    CD_DESCR* descr )           // - descriptor for a class
{
    descr->chk_acc = TRUE;
}


void CDoptChkAccFun(            // CHECK FUNCTIONS ACCESS FOR CLASS
    CD_DESCR* descr )           // - descriptor for a class
{
    SCOPE old;                  // - old scope
    ACC_FUN* af;                // - accessed function
    char* name;                 // - name of function
    SEARCH_RESULT* result;      // - search result for function

    if( ! descr->chk_acc ) {
        descr->chk_acc = TRUE;
        if( NULL != descr->accessed ) {
            old = GetCurrScope();
            SetCurrScope(TypeScope( descr->orig_type ));
            RingIterBeg( descr->accessed, af ) {
                name = af->fun->name->name;
                result = ScopeFindBaseMember( SymScope( af->fun ), name );
                ScopeCheckSymbol( result, af->fun );
                ScopeFreeResult( result );
            } RingIterEnd( af )
            SetCurrScope(old);
        }
    }
}


static void cdoptChkAccFunGen(  // CHECK ACCESS FOR CLASS FUNCTION
    SYMBOL fun,                 // - the class function
    CD_DESCR* descr )           // - descriptor for a class
{
    CtxFunction( fun );
    CDoptChkAccFun( descr );
}



//--------------------------------------------------------------------
// Traversals
//--------------------------------------------------------------------


static
CL_ELEM* activeElement          // GET ACTIVE ELEMENT
    ( CDOPT_ITER *iter )        // - iterator
{
    CL_ITER* exp;               // - expansion information
    CL_ELEM* elem;              // - class information

⌨️ 快捷键说明

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