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 + -
显示快捷键?