cgbkscop.c

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

C
1,225
字号
/****************************************************************************
*
*                            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 "cgback.h"
#include "errdefns.h"
#include "codegen.h"
#include "cgbackut.h"
#include "ring.h"
#include "carve.h"
#include "vstk.h"
#include "callgrph.h"
#include "cdopt.h"
#include "reposit.h"
#include "scoperes.h"

//typedef struct unr_usage        UNR_USAGE;          // unresolved usage
typedef struct scope_res        SCOPE_RES;          // unresolved scope
typedef struct res_act          RES_ACT;            // resolution actions

#define USAGE_DEFS                  /* unresolved usages                */ \
                                    /* - function usages:               */ \
 USAGE_DEF( FNUSE_CALL           )  /* - - call in a scope              */ \
,USAGE_DEF( FNUSE_CALL_TEMP      )  /* - - call in statement scope      */ \
,USAGE_DEF( FNUSE_CALL_SCOPE     )  /* - - call in block scope          */ \
,USAGE_DEF( FNUSE_CALL_CTOR      )  /* - - ctor call in statement scope */ \
,USAGE_DEF( FNUSE_SCOPE          )  /* - - scope resolution req'd       */ \
                                    /* - scope usages:                  */ \
,USAGE_DEF( SCUSE_DTOR_BLK       )  /* - - dtor: block                  */ \
,USAGE_DEF( SCUSE_DTOR_TEMP      )  /* - - dtor: temporary              */ \
,USAGE_DEF( SCUSE_DTOR_COMPONENT )  /* - - dtor: component              */

#define RES_DEFS        /* type of resolution                           */ \
 RES_DEF( RES_FN_TH )   /* - function resolved to be SF_LONGJUMP        */ \
,RES_DEF( RES_FN_NT )   /* - function resolved to be SF_NO_LONGJUMP     */ \
,RES_DEF( RES_SC_SG )   /* - scope resolved as STAB_GEN                 */ \
,RES_DEF( RES_SC_NG )   /* - scope resolved as ~ STAB_GEN               */

typedef enum {                  // UNR_USE -- unresolved usage
    #define USAGE_DEF(a) a
    USAGE_DEFS
    #undef USAGE_DEF
,   MAX_USAGE_DEF
} UNR_USE;

typedef enum {                  // RES_TYPE -- type of resolution
    #define RES_DEF(a) a
    RES_DEFS
    #undef RES_DEF
,   MAX_RES_DEF
} RES_TYPE;

struct unr_usage                // UNR_USAGE -- unresolved usage
{   UNR_USAGE* next;            // - next in ring
    SCOPE scope;                // - scope referenced
    union                     { // - one of:
        CALLNODE* node;         // - - CALLNODE for function used
        SYMBOL fun;             // - - SYMBOL for function used
        SCOPE_RES* res_scope;   // - - scope to be resolved
        void* unresolved;     };// - - general entry
    UNR_USE type;               // - type of usage
    unsigned :0;                // - alignment
};

struct scope_res                // SCOPE_RES -- unresolved scope
{   SCOPE_RES* next;            // - next scope resolution
    SCOPE_RES* enclosing;       // - enclosing scope
    SCOPE scope;                // - the scope in question
    UNR_USAGE* unresolved;      // - ring of unresolved
    int toresolve;              // - # items to be resolved
    CALLNODE* func;             // - function containing scope
    DT_METHOD dtm;              // - function dtor method
    unsigned : 0;               // - alignment
    unsigned dtorables;         // - # dtorable items in scope
    unsigned statement : 1;     // - TRUE ==> is statement scope
    unsigned dtor_ct : 1;       // - TRUE ==> has can-throw dtorable
    unsigned call_ct : 1;       // - TRUE ==> has can-throw call
    unsigned scanning : 1;      // - TRUE ==> is being scanned now
    unsigned gen_stab : 1;      // - TRUE ==> scan detected state-table req'd
    unsigned scope_throw : 1;   // - TRUE ==> IC_SCOPE_THROW in scope
    unsigned : 0;               // - alignment
};

struct res_act                  // RES_ACT -- resolution action
{   RES_TYPE type;              // - type of resolution
    unsigned :0;                // - alignment
    union                       // - one of:
    {   CALLNODE* node;         // - - unresolved function
        SCOPE_RES* scope;       // - - unresolved scope
    };
};

static VSTK_CTL actions;        // actions pending
static carve_t carveUsage;      // carver: scope uses
static carve_t carveScRes;      // carver: unresolved scopes
static VSTK_CTL open_scopes;    // open scopes
static SCOPE_RES* scopes;       // unresolved scopes


#ifndef NDEBUG

#include "dbg.h"
#include "pragdefn.h"

static char const * usage_names[] = {
    #define USAGE_DEF(a) # a
    USAGE_DEFS
    #undef USAGE_DEF
};

static char const * res_names[] = {
    #define RES_DEF(a) # a
    RES_DEFS
    #undef RES_DEF
};

#define strcase( v ) case v: name = #v; break;

static void _print( char const * msg )
{
    if( PragDbgToggle.callgraph_scan ) {
        printf( msg );
    }
}

static char const* _res_type( RES_TYPE type )
{
    return ( type < MAX_RES_DEF ) ? res_names[ type ] : "BAD RES_TYPE";
}

static char const* _unr_use( UNR_USE type )
{
    return ( type < MAX_USAGE_DEF ) ? usage_names[ type ] : "BAD UNR_USE";
}

static void _printAction( RES_ACT const * ra, char const * msg )
{
    if( PragDbgToggle.callgraph_scan
     && ra != NULL ) {
        printf( "RES_ACT[%x] %s %x %s\n"
              , ra
              , _res_type( ra->type )
              , ra->node
              , msg );
    }
}

static void _printScopeRes( SCOPE_RES const *sr, char const * msg )
{
    if( PragDbgToggle.callgraph_scan ) {
        printf( "SCOPE_RES[%x] %s\n"
                "  next[%x] enclosing[%x] scope[%x] unresolved[%x]\n"
                "  toresolve[%d] func[%x] dtm[%x]\n"
                "  statement-%d dtor_ct-%d call_ct-%d scanning-%d gen_stab-%d"
                " scope_throw-%d\n"
              , sr
              , msg
              , sr->next
              , sr->enclosing
              , sr->scope
              , sr->unresolved
              , sr->toresolve
              , sr->func
              , sr->dtm
              , sr->statement
              , sr->dtor_ct
              , sr->call_ct
              , sr->scanning
              , sr->gen_stab
              , sr->scope_throw );
    }
}


static void _printUnrUsage( UNR_USAGE const *fu, char const * msg )
{
    if( PragDbgToggle.callgraph_scan ) {
        printf( "UNR_USAGE[%x] %s %x %s\n"
              , fu
              , _unr_use( fu->type )
              , fu->node
              , msg );
    }
}


static void _printScopeResAll( SCOPE_RES const *sr, char const * msg )
{
    UNR_USAGE* su;
    if( PragDbgToggle.callgraph_scan ) {
        _printScopeRes( sr, msg );
        RingIterBeg( sr->unresolved, su ) {
            _printUnrUsage( su, msg );
        } RingIterEnd( su );
    }
}

static void _printFunction( SYMBOL fun, char const * msg )
{
    if( PragDbgToggle.callgraph_scan ) {
        printf( "%s [%x] %s\n"
              , msg
              , fun
              , DbgSymNameFull( fun ) );
    }
}

static boolean _printCallNode
    ( CALLGRAPH* ctl
    , CALLNODE* node )
{
    UNR_USAGE *fu;
    ctl = ctl;
    if( PragDbgToggle.callgraph_scan ) {
        printf( "CALLNODE[%x] unresolved[%x] %s\n"
              , node
              , node->unresolved
              , DbgSymNameFull( node->base.object ) );
        RingIterBeg( node->unresolved, fu ) {
            _printUnrUsage( fu, "" );
        } RingIterEnd( fu );
    }
    return FALSE;
}

#else

#define _print(a)
#define _res_type(a)
#define _unr_use(a)
#define _printAction(a,b)
#define _printScopeRes(a,b)
#define _printScopeResAll(a,b)
#define _printFnUsage(a,b)
#define _printScUsage(a,b)
#define _printFunction(a,b)
#define _printCallNode(a,b)
#define _printUnrUsage(a,b)

#endif


static SYMBOL symDefaultBase(   // GET ACTUAL SYMBOL FOR A DEFAULT
    SYMBOL fun )                // - function symbol
{
    if( fun != NULL ) {
        fun = SymDefaultBase( fun );
    }
    return fun;
}


static SCOPE_RES* openScopesTop // GET TOP OF OPEN-SCOPES STACK
    ( void )
{
    SCOPE_RES** a_sr;           // - addr[ unresolved scope ]
    SCOPE_RES* sr;              // - unresolved scope

    a_sr = VstkTop( &open_scopes );
    if( a_sr == NULL ) {
        sr = NULL;
    } else {
        sr = *a_sr;
    }
    return sr;
}


static SCOPE_RES* openScopesPush // PUSH OPEN-SCOPES STACK
    ( void )
{
    SCOPE_RES** a_sr;           // - addr[ unresolved scope ]
    SCOPE_RES* sr;              // - unresolved scope
    SCOPE_RES* enclosing;       // - enclosing scope

    enclosing = openScopesTop();
    a_sr = VstkPush( &open_scopes );
    sr = CarveAlloc( carveScRes );
    *a_sr = sr;
    sr->enclosing = enclosing;
    if( NULL != enclosing ) {
        ++ enclosing->toresolve;
        sr->scope_throw = enclosing->scope_throw;
    } else {
        sr->scope_throw = FALSE;
    }
    return sr;
}


static SCOPE_RES* openScopesPop // POP OPEN-SCOPES STACK
    ( void )
{
    SCOPE_RES** a_sr;           // - addr[ unresolved scope ]
    SCOPE_RES* sr;              // - unresolved scope

    a_sr = VstkPop( &open_scopes );
    if( a_sr == NULL ) {
        sr = NULL;
    } else {
        sr = *a_sr;
    }
    return sr;
}


#define OpenScopesIterBeg( it )         \
    { SCOPE_RES** a_sr;                 \
      VstkIterBeg( &open_scopes, a_sr ) { \
        it = *a_sr;
#define OpenScopesIterEnd( it )         \
      }                                 \
    }


static RES_ACT* pushAction      // PUSH ACTION
    ( RES_TYPE type )           // - type of action
{
    RES_ACT* res = VstkPush( &actions );
    res->type = type;
    return res;
}


static RES_ACT* pushActionCaller// PUSH FUNCTION-RELATED ACTION
    ( CALLNODE* node            // - call node
    , RES_TYPE type )           // - type of action
{
    RES_ACT* res;               // - new entry

    if( NULL == node->unresolved ) {
        res = NULL;
    } else {
        res = pushAction( type );
        res->node = node;
    }
    return res;
}


static CALLNODE* makeThrowFun   // FUNCTION BECOMES A THROWING FUNCTION
    ( CALLNODE* owner )         // - owner
{
    SYMBOL fun;                 // - owner symbol
    RES_ACT* res;               // - resolution action

    fun = owner->base.object;
    fun = symDefaultBase( fun );
    DbgVerify( ! ( fun->flag & SF_NO_LONGJUMP )
             , "makeThrowFun -- has SF_NO_LONGJUMP" );
    if( ! ( fun->flag & SF_LONGJUMP ) ) {
        fun->flag |= SF_LONGJUMP;
        res = pushActionCaller( owner, RES_FN_TH );
        _printAction( res, "Function resolved: throwable" );
        CgResolve();
    }
    return owner;
}


static CALLNODE* makeNonThrowFun// FUNCTION BECOMES A NON-THROWING FUNCTION
    ( CALLNODE* owner )         // - owner
{
    SYMBOL fun;                 // - owner symbol
    RES_ACT* res;               // - resolution action

    fun = owner->base.object;
    fun = symDefaultBase( fun );
    DbgVerify( ! ( fun->flag & SF_LONGJUMP )
             , "makeNonThrowFun -- has SF_LONGJUMP" );
    if( ! ( fun->flag & SF_NO_LONGJUMP ) ) {
        fun->flag |= SF_NO_LONGJUMP;
        res = pushActionCaller( owner, RES_FN_NT );
        _printAction( res, "Function resolved: non-throwable" );
        CgResolve();
    }
    return owner;
}

⌨️ 快捷键说明

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