cgbkcgrf.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,508 行 · 第 1/4 页
C
1,508 行
{
CGFILE *cgfile; // - code gen file
SYMBOL func; // - the function
func = node->base.object;
cgfile = nodeCgFile( node );
if( node->inline_fun ) {
#ifndef NDEBUG
if( PragDbgToggle.dump_emit_ic || PragDbgToggle.callgraph ) {
printf( "Removed inline code file: %s\n"
, DbgSymNameFull( func ) );
}
#endif
CgioFreeFile( cgfile );
// inlines that aren't going to be generated aren't really referenced
func->flag &= ~SF_REFERENCED;
} else if ( SymIsRegularStaticFunc( func ) ) {
#ifndef NDEBUG
if( PragDbgToggle.dump_emit_ic || PragDbgToggle.callgraph ) {
printf( "Removed static code file: %s\n"
, DbgSymNameFull( func ) );
}
#endif
CgioFreeFile( cgfile );
#ifndef NDEBUG
} else {
CFatal( "cgbkcgrf: removeCodeFile function not removable" );
#endif
}
}
static boolean procFunction( // POST-PROCESS FUNCTION IN CALL GRAPH
CALLGRAPH *ctl, // - control information
CALLNODE *node ) // - function in graph
{
SYMBOL func; // - function
CGFILE* cgfile; // - for function
ctl = ctl;
ExtraRptIncrementCtr( ctr_nodes_visited );
if( node->state_table ) {
callGraphFlags.any_state_tables = TRUE;
}
func = node->base.object;
if( node->addrs > 0 ) {
if( func != NULL ) {
func->flag |= SF_ADDR_TAKEN;
}
markAsGen( node );
} else if( ! CompFlags.inline_functions ) {
markAsGen( node );
} else {
genFunction( node );
}
cgfile = nodeCgFile( node );
if( cgfile != NULL ) {
cgfile->state_table = node->state_table;
cgfile->stab_gen = node->stab_gen;
cgfile->cond_flags = node->cond_flags;
if( cgfile->oe_inl ) {
func->flag |= SF_CG_INLINEABLE;
}
if( cgfile->not_inline ) {
func->flag &= ~SF_CG_INLINEABLE;
}
}
return FALSE;
}
static boolean pruneFunction( // PRUNE UNREFERENCED FUNCTION
CALLGRAPH *ctl, // - control information
CALLNODE *node ) // - function in graph
{
SYMBOL sym; // - symbol for node
ExtraRptIncrementCtr( ctr_nodes_visited );
sym = node->base.object;
switch( cgbackFuncType( sym ) ) {
case TCF_STATIC :
if( ! SymIsRegularStaticFunc( sym ) ) break;
case TCF_INLINE :
if( ( node->refs == 0 ) && ( node->addrs == 0 ) ) {
_DUMP_CGRF( "pruned unreferenced function: %s\n", sym );
removeCodeFile( node );
CgrfPruneFunction( ctl, node );
}
break;
}
return FALSE;
}
static boolean procStabEdge( // PROCESS INLINE-CALL EDGE FROM NODE
CALLGRAPH *ctl, // - control information
CALLEDGE *edge ) // - call to inline/static
{
CALLNODE *target; // - node for caller
ExtraRptIncrementCtr( ctr_nodes_visited );
target = (CALLNODE*)edge->base.target;
if( ! target->is_vft ) {
if( target->inlineable || target->inlineable_oe ) {
if( ! recursiveExpand( ctl, target ) ) {
pushCaller( ctl, target );
}
}
}
return FALSE;
}
static boolean setFunctionStab( // SET STATE-TABLE INFO. FOR FUNCTION
CALLGRAPH *ctl, // - control information
CALLNODE *node ) // - function in graph
{
CGFILE *cgfile; // - code gen file
INLINEE *inl; // - stacked inline
unsigned depth; // - current depth
unsigned cond_flags; // - # conditional flags
unsigned max_cond_flags; // - maximum # conditional flags
boolean state_table; // - TRUE ==> requires state table
boolean stab_gen; // - TRUE ==> state table to be genned
ExtraRptIncrementCtr( ctr_nodes_visited );
if( ! node->is_vft ) {
cgfile = nodeCgFile( node );
if( cgfile != NULL ) {
state_table = node->state_table;
stab_gen = node->stab_gen;
cond_flags = 0;
max_cond_flags = 0;
pushCaller( ctl, node );
for( depth = 0; ; ) {
inl = VstkTop( &ctl->calls );
if( inl == NULL ) break;
if( inl->expanded ) {
inl = VstkPop( &ctl->calls );
-- depth;
node = inl->callee;
cond_flags -= node->cond_flags;
} else {
inl->expanded = TRUE;
node = inl->callee;
if( node->state_table ) {
state_table = TRUE;
cond_flags += node->cond_flags;
if( cond_flags > max_cond_flags ) {
max_cond_flags = cond_flags;
}
if( node->stab_gen ) {
stab_gen = TRUE;
}
}
++ depth;
if( depth <= max_inline_depth ) {
ctl->depth = depth;
CgrfWalkCalls( ctl, node, &procStabEdge );
}
}
}
cgfile->state_table = state_table;
cgfile->stab_gen = stab_gen;
cgfile->cond_flags = max_cond_flags;
#ifndef NDEBUG
if( PragDbgToggle.dump_emit_ic ||
PragDbgToggle.callgraph ||
PragDbgToggle.dump_stab ) {
SYMBOL func = cgfile->symbol;
if( state_table ) {
printf( "%s has state table: flags = %d gen=%d\n"
, DbgSymNameFull( func )
, max_cond_flags
, stab_gen );
} else {
printf( "%s has no state table\n"
, DbgSymNameFull( func ) );
}
}
#endif
}
}
return FALSE;
}
void MarkFuncsToGen( // DETERMINE FUNCTIONS TO BE GENERATED
unsigned bounding_depth ) // - maximum inline depth
{
CALLGRAPH ctl; // - control information
SYMBOL *pfunc; // - ptr[ stacked inline ]
CGFILE *vfcg; // - current VFTDefn CGFILE
#ifndef NDEBUG
unsigned int dbg_dump_exec = PragDbgToggle.dump_exec_ic;
PragDbgToggle.dump_exec_ic = 0;
if( PragDbgToggle.callgraph_scan ) {
PragDbgToggle.callgraph = 1;
}
#endif
vft_defs = NULL;
DbgCgioEndFront();
carve_vft = CarveCreate( sizeof( VFT_DEFN ), 16 );
SegmentCodeCgInit();
callGraphFlags.any_state_tables = FALSE;
callGraphFlags.only_once_found = FALSE;
// callGraphFlags.not_inlined_set = FALSE;
if( ! CompFlags.inline_functions ) {
max_inline_depth = 0;
ctl.scope_call_opt = FALSE;
} else {
max_inline_depth = bounding_depth;
if( ! CompFlags.dt_method_pragma
&& ( CompInfo.dt_method_speced == DTM_DIRECT
|| CompInfo.dt_method_speced == DTM_DIRECT_SMALL
|| CompInfo.dt_method_speced == DTM_TABLE_SMALL ) ) {
ctl.scope_call_opt = FALSE;
} else {
ctl.scope_call_opt = TRUE;
}
}
call_graph = &ctl;
CgrfInit( &ctl );
ExtraRptRegisterCtr( &ctr_funs_scanned
, "# call-graph functions scanned" );
ExtraRptRegisterCtr( &ctr_funs_rescanned
, "# call-graph functions re-scanned" );
ExtraRptRegisterCtr( &ctr_nodes_visited
, "# call-graph nodes visited" );
ExtraRptRegisterCtr( &ctr_gened
, "# call-graph functions to be gen'ed" );
ExtraRptRegisterAvg( &ctr_nodes_visited
, &ctr_gened
, "average visits per function to be gen'ed" );
ExtraRptRegisterCtr( &ctr_vfts_scanned
, "# call-graph VFT's scanned" );
ExtraRptRegisterCtr( &ctr_vfts_genned
, "# call-graph VFT's generated" );
// start with functions that will be generated and expand a call graph
VstkOpen( &ctl.calls, sizeof( SYMBOL ), 32 );
if( ctl.scope_call_opt ) {
CgResInit();
}
CgioWalkFiles( &scanFunction );
vfcg = NULL;
for( ; ; ) {
for(;;) {
SYMBOL sym;
CALLNODE* node;
pfunc = VstkPop( &ctl.calls );
if( pfunc == NULL ) break;
sym = *pfunc;
node = addNode( sym );
if( TCF_VFT == cgbackFuncType( sym ) ) {
scanVftDefn( node, sym, &vfcg );
} else {
CGFILE* code_file = nodeCgFile( node );
if( code_file == NULL ) { // default was not gen'ed
CgrfPruneFunction( &ctl, node );
} else {
scanFunctionBody( node, code_file );
}
}
}
if( ctl.scope_call_opt ) {
CgrfWalkFunctions( &ctl, &CgResolveNonThrow );
}
if( NULL == VstkTop( &ctl.calls ) ) break;
}
if( vfcg != NULL ) {
CgioCloseInputFile( vfcg );
}
if( ctl.scope_call_opt ) {
CgResFini();
}
VstkClose( &ctl.calls );
// prune out internal linkage functions that are never called
// or do not have their address taken
VstkOpen( &ctl.calls, sizeof( INLINEE ), 32 );
do {
ctl.pruned = FALSE;
CgrfWalkFunctions( &ctl, &pruneFunction );
} while( ctl.pruned );
if( max_inline_depth > 0 ) {
if( oe_size > 0 ) {
CgrfWalkFunctions( &ctl, &procStaticFunction );
}
CgrfWalkFunctions( &ctl, &procInlineFunction );
CgrfWalkFunctions( &ctl, &procFunction );
if( callGraphFlags.any_state_tables ) {
CgrfWalkFunctions( &ctl, &setFunctionStab );
}
} else {
CgrfWalkFunctions( &ctl, &procFunction );
}
VstkClose( &ctl.calls );
#ifndef NDEBUG
PragDbgToggle.dump_exec_ic = dbg_dump_exec;
if( PragDbgToggle.callgraph ) {
CgrfDump( &ctl );
}
#endif
CgrfFini( &ctl );
CarveDestroy( carve_vft );
DbgCgioEndCallGr();
}
void CgBackSetOeSize( // SET SIZE FOR INLINING STATICS
unsigned value ) // - size specified with -oe
{
oe_size = value;
}
boolean CgBackFuncInlined( // DETERMINE IF FUNCTION INVOCATION INLINED
SYMBOL sym ) // - function symbol
{
return ( sym->flag & SF_CG_INLINEABLE )
&& shouldBeInlined( sym );
}
void CgBackSetInlineRecursion( // SET INLINE RECURSION
boolean allowed ) // - TRUE ==> inline recursion allowed
{
callGraphFlags.inline_recursion = allowed;
}
boolean CgBackGetInlineRecursion(// GET INLINE RECURSION
void )
{
return( callGraphFlags.inline_recursion );
}
// Support for CgrfScop
CALLNODE* CgrfCallNode( // GET CALLNODE FOR FUNCTION
SYMBOL fun ) // - function
{
return addCallee( fun );
}
CALLNODE* CgrfDtorCall( // DTOR CALL HAS BEEN ESTABLISHED
CALLNODE* owner, // - owner
SYMBOL dtor ) // - dtor called
{
dtor->flag |= SF_REFERENCED;
addCalleeFuncToGen( owner, dtor );
return owner;
}
CALLNODE* CgrfDtorAddr( // DTOR ADDR-OF HAS BEEN ESTABLISHED
CALLNODE* owner, // - owner
SYMBOL dtor ) // - dtor called
{
dtor->flag |= SF_REFERENCED | SF_ADDR_TAKEN;
addAddrOf( owner, dtor );
return owner;
}
#ifndef NDEBUG
void* DbgCallGraph( void )
{
return call_graph;
}
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?