cgbkcgrf.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,508 行 · 第 1/4 页
C
1,508 行
/****************************************************************************
*
* 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 <float.h>
#include "cgfront.h"
#include "cgback.h"
#include "memmgr.h"
#include "errdefns.h"
#include "codegen.h"
#include "cgbackut.h"
#include "cppdwarf.h"
#include "cgaux.h"
#include "cginfo.h"
#include "ring.h"
#include "stringl.h"
#include "rtfuncod.h"
#include "carve.h"
#include "label.h"
#include "vstk.h"
#include "context.h"
#include "name.h"
#include "ctexcept.h"
#include "symdbg.h"
#include "callgrph.h"
#include "cdopt.h"
#include "stats.h"
#include "reposit.h"
#include "scoperes.h"
#include "icopmask.h"
#include "pragdefn.h"
#include "rtti.h"
#ifndef NDEBUG
#include <stdio.h>
#include "dbg.h"
#include "pragdefn.h"
static void _DUMP_CGRF( char *msg, SYMBOL sym ) {
if( PragDbgToggle.callgraph ) {
printf( msg, DbgSymNameFull( sym ) );
}
}
#else
#define _DUMP_CGRF( msg, sym )
#endif
typedef struct vft_defn VFT_DEFN;
struct vft_defn { // VFT_DEFN -- definition for VFT
VFT_DEFN* next; // - next in ring
SYMBOL vft; // - symbol for vft
CGFILE* cgfile; // - virtual file containing definition
CGFILE_INS location; // - where to scan for definition
};
typedef struct scope_dtor SCOPE_DTOR;
struct scope_dtor // SCOPE_DTOR -- delayed DTORing for a scope
{ SCOPE_DTOR* next; // - next in ring
SYMBOL dtor; // - dtor
DTOR_KIND kind; // - type of dtor
unsigned :0; // - aligning
};
typedef struct // SCOPE_INFO -- scope information
{ SCOPE scope; // - scope in question
SCOPE_STATE state; // - current state
SCOPE_DTOR* dtoring; // - ring of delayed dtoring
} SCOPE_INFO;
typedef struct // DTOR_SCOPE -- dtoring in a scope
{ unsigned opcode; // - type of dtoring
SYMBOL dtor; // - dtor symbol
SCOPE scope; // - scope for dtoring
} DTOR_SCOPE;
static VFT_DEFN *vft_defs; // ring of vftable defns
static carve_t carve_vft; // carver for vft definitions
static CALLGRAPH* call_graph; // call graph information
static unsigned max_inline_depth; // maximum depth of inlining
static unsigned oe_size; // size for inlining static functions
static struct {
unsigned inline_recursion:1; // TRUE ==> inline recursion allowed
unsigned any_state_tables:1; // TRUE ==> state tables somewhere
unsigned only_once_found :1; // TRUE ==> ->once_inl fn somewhere
// unsigned not_inlined_set :1; // TRUE ==> not_inline set somewhere
} callGraphFlags;
typedef enum // TCF -- types of functions
{ TCF_MOD_INIT // - module-init function
, TCF_INLINE // - inline function
, TCF_STATIC // - static, non-member
, TCF_VFT // - virtual-function table
, TCF_OTHER_FUNC // - other function
, TCF_NOT_FUNC // - not a function
, TCF_NULL // - NULL pointer
} TCF;
typedef struct // SCAN_INFO -- scanning information
{ CALLNODE* cnode; // - current node
CGFILE *file_ctl; // - current file
unsigned has_except_spec :1;// - TRUE ==> has except spec.
SYMBOL scope_call_cmp_dtor; // - component dtor for scope-call optimization
SYMBOL scope_call_tmp_dtor; // - temporary dtor for scope-call optimization
SYMBOL scope_call_blk_dtor; // - scope dtor for scope-call optimization
SCOPE curr_scope; // - current scope
unsigned func_dtm; // - dtor method for function
} SCAN_INFO;
static void forceGeneration( // FORCE CODE FILE TO BE GENERATED
CALLNODE *node ); // - function in graph
#ifndef NDEBUG
void CallGraphDump( void )
{
CgrfDump( call_graph );
}
static void _printScanInt( const char* msg, unsigned val )
{
if( PragDbgToggle.callgraph_scan ) {
printf( msg, val );
}
}
#else
#define _printScanInt( a, b )
#endif
ExtraRptCtr( ctr_funs_scanned ); // functions scanned
ExtraRptCtr( ctr_funs_rescanned ); // functions re-scanned
ExtraRptCtr( ctr_vfts_scanned ); // VFT's scanned
ExtraRptCtr( ctr_vfts_genned ); // VFT's generated
ExtraRptCtr( ctr_nodes_visited ); // nodes visited (measure of work)
ExtraRptCtr( ctr_gened ); // functions left after processing
static SYMBOL callNodeCaller( // GET SYMBOL FOR CALLER FROM CALLNODE
CALLNODE* cnode ) // - call node
{
SYMBOL sym; // - caller symbol
sym = cnode->base.object;
return sym;
}
void CgrfMarkNodeGen( // MARK NODE AS GEN-ED, IF REQ'D
CALLNODE* cnode ) // - the node
{
switch( cnode->dtor_method ) {
case DTM_DIRECT :
break;
case DTM_DIRECT_SMALL :
{ SYMBOL func = callNodeCaller( cnode );
if( NULL == func
|| ! SymIsDtor( func ) ) break;
}
// drops thru
default :
cnode->stab_gen = TRUE;
break;
}
}
static TCF cgbackFuncType( // DETERMINE TYPE OF FUNCTION
SYMBOL sym ) // - symbol
{
TCF retn; // - type of function
if( sym == NULL ) {
retn = TCF_MOD_INIT;
} else if( ! SymIsFunction( sym ) ) {
if( SymIsVft( sym ) ) {
retn = TCF_VFT;
} else {
retn = TCF_NOT_FUNC;
}
} else if( ! SymIsInitialized( sym ) ) {
retn = TCF_OTHER_FUNC;
} else if( SymIsInline( sym ) ) {
retn = TCF_INLINE;
} else if( oe_size != 0 ) {
retn = TCF_STATIC;
} else if( SymIsRegularStaticFunc( sym ) ) {
retn = TCF_STATIC;
} else {
retn = TCF_OTHER_FUNC;
}
return retn;
}
static CGFILE* nodeCgFile( // GET CGFILE FOR NODE
CALLNODE* node ) // - the node
{
CGFILE* retn; // - the CGFILE
retn = node->cgfile;
if( retn == NULL ) {
retn = CgioLocateFile( node->base.object );
node->cgfile = retn;
}
return retn;
}
static boolean funcInlineable( // DETERMINE IF FUNCTION INLINE-ABLE
SYMBOL sym ) // - function symbol
{
AUX_INFO *pragma;
DbgAssert( sym != NULL );
if( max_inline_depth == 0 ) {
// no inlining allowed
return( FALSE );
}
if( ! SymIsInitialized( sym ) ) {
// sym has no code to inline
return( FALSE );
}
if( SymIsUninlineable( sym ) ) {
// sym has been tagged as not being inlineable
// e.g., contains _asm code that references auto vars
return( FALSE );
}
if( SymIsEllipsisFunc( sym ) ) {
// function could not access parms through <stdarg.h> if inlined
return( FALSE );
}
// used to have: if( TypeHasPragma( sym->sym_type ) ) (why? AFS)
pragma = TypeHasPragma( sym->sym_type );
if( pragma != NULL ) {
if( ! PragmaOKForInlines( pragma ) ) {
// something weird and system specific would cause a problem
return( FALSE );
}
}
return( TRUE );
}
static boolean oeInlineable( // DETERMINE IF /oe CAN INLINE THE FUNCTION
SYMBOL sym, // - symbol for node
CGFILE *cgfile ) // - code gen file for function
{
boolean retn; // - TRUE ==> CAN BE /oe inlined
if( funcInlineable( sym ) ) {
if( cgfile == NULL ) {
retn = FALSE;
} else if( cgfile->oe_inl ) {
retn = TRUE;
} else {
retn = FALSE;
}
} else {
retn = FALSE;
}
return retn;
}
static boolean canBeOeInlined( // DETERMINE IF /oe CAN INLINE THE FUNCTION
CALLNODE* node ) // - node for function
{
return oeInlineable( node->base.object, nodeCgFile( node ) );
}
static boolean shouldBeInlined( // DETERMINE IF INLINING AN INLINABLE FN IS OK
SYMBOL sym ) // - function symbol
{
FN_CTL *fctl; // - current file control
if( CgBackInlinedDepth() >= max_inline_depth ) {
return( FALSE );
}
fctl = FnCtlTop();
if( fctl == NULL || SymIsThunk( fctl->func ) ) {
return FALSE;
}
if( ! callGraphFlags.inline_recursion ) {
for( ; fctl != NULL; fctl = FnCtlPrev( fctl ) ) {
if( sym == fctl->func ) return( FALSE );
}
}
return( TRUE );
}
static CALLNODE* addNode( // ADD A CALL NODE
SYMBOL sym ) // - symbol for node
{
CALLNODE* node = CgrfAddFunction( call_graph, sym );
switch( cgbackFuncType( sym ) ) {
case TCF_VFT :
node->is_vft = TRUE;
break;
case TCF_INLINE :
node->inline_fun = TRUE;
if( funcInlineable( sym ) ) {
node->inlineable = TRUE;
sym->flag |= SF_CG_INLINEABLE;
}
break;
case TCF_OTHER_FUNC :
case TCF_STATIC :
if( funcInlineable( sym ) ) {
node->inlineable = TRUE;
if( oe_size > 0 ) {
node->inlineable_oe = canBeOeInlined( node );
if( node->inlineable_oe ) {
sym->flag |= SF_CG_INLINEABLE;
}
}
}
break;
case TCF_MOD_INIT :
break;
DbgDefault( "addNode -- bad type" );
}
return node;
}
static CALLNODE *addCallee( // ADD CALL TO CALL GRAPH
SYMBOL callee ) // - symbol called
{
CALLNODE *retn; // - node for callee
SYMBOL *pfun; // - addr[ stacked symbol ]
retn = addNode( callee );
if( ( retn->refs == 0 ) && ( retn->addrs == 0 ) ) {
switch( cgbackFuncType( callee ) ) {
case TCF_VFT :
pfun = (SYMBOL*)VstkPush( &call_graph->calls );
*pfun = callee;
break;
case TCF_INLINE :
case TCF_STATIC :
pfun = (SYMBOL*)VstkPush( &call_graph->calls );
*pfun = callee;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?