cgbkcgrf.c

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

C
1,508
字号
            break;
        }
    }
    return retn;
}


static TCF addAddrOf(           // ADD ADDRESS-OF IF REQUIRED
    CALLNODE *cnode,            // - node in call graph for calling function
    SYMBOL callee )             // - function possibly addressed
{
    TCF tcf;
    CALLNODE *rnode;            // - node of referenced function

    if( callee != NULL ) {
        tcf = cgbackFuncType( callee );
        switch( tcf ) {
          case TCF_INLINE :
          case TCF_STATIC :
          case TCF_VFT :
            rnode = addCallee( callee );
            CgrfAddAddrOf( call_graph, cnode, rnode );
            break;
          case TCF_NOT_FUNC :
            break;
          default :
            callee->flag |= SF_ADDR_TAKEN;
        }
        return( tcf );
    }
    return( TCF_NULL );
}


// type signature reference causes address-of references from source node
// to member functions which are inline.
//
static void addTypeSigRefs(     // ADD REFERENCES FOR TYPE SIGNATURE
    CALLNODE *cnode,            // - node in call graph for calling function
    TYPE type )                 // - signature type
{
    TYPE_SIG *tsig;             // - type-signature for type

    tsig = BeTypeSignature( type );
    addAddrOf( cnode, tsig->dtor );
    addAddrOf( cnode, tsig->default_ctor );
    addAddrOf( cnode, tsig->copy_ctor );
}


static void addCalleeFunc(      // ADD FUNCTION CALL TO CALL GRAPH
    CALLNODE *cnode,            // - node in call graph for calling function
    SYMBOL callee )             // - called symbol
{
    switch( cgbackFuncType( callee ) ) {
      case TCF_INLINE :
      case TCF_STATIC :
        CgrfAddCall( call_graph, cnode, addCallee( callee ) );
        // drops thru
      case TCF_OTHER_FUNC :
//      funCalled( callee );
        break;
    }
}


// For a function to be generated, there has not been an addr-of taken
// for the function ==> generate one here.
//
static void addCalleeFuncToGen( // ADD FUNCTION CALL FOR FUNC. TO BE GEN'ED
    CALLNODE *cnode,            // - node in call graph for calling function
    SYMBOL callee )             // - called symbol
{
    addAddrOf( cnode, callee );
    addCalleeFunc( cnode, callee );
}


static void scanInit(           // INIT FOR COMMONALITY BETWEEN SCAN, RE-SCAN
    CALLNODE *cnode,            // - node in call graph for calling function
    CGFILE *file_ctl,           // - current file
    SCAN_INFO* scan )           // - scan information
{
    call_graph->scanning = cnode;
    call_graph->stmt_scope = FALSE;
    cnode->stmt_state = STS_NONE;
    cnode->stab_gen = FALSE;
    cnode->dtor_method = DTM_DIRECT;
    scan->cnode = cnode;
    scan->scope_call_blk_dtor = NULL;
    scan->scope_call_tmp_dtor = NULL;
    scan->scope_call_cmp_dtor = NULL;
    scan->has_except_spec = FALSE;
    scan->file_ctl = file_ctl;
    CgioOpenInput( file_ctl );
}

static void dtorRef(            // reference a dtor in state table
    CGINTER *ins,               // - IC instr
    SCAN_INFO *sc,              // - scan info
    CALLNODE *cnode )           // - node in call graph for calling function
{
    SYMBOL dtor = ins->value.pvalue;

    switch( sc->func_dtm ) {
      case DTM_DIRECT_TABLE :
        addAddrOf( cnode, dtor );
        // drops thru
      case DTM_DIRECT :
        addCalleeFuncToGen( cnode, dtor );
        break;
      default :
        addAddrOf( cnode, dtor );
        break;
    }
}


// Note: there are some conditions under which we could safely flush
//       the return optimizations.  These are not considered now to
//       remain conservative.
//
static void scanFunctionBody(   // SCAN FUNCTION FOR CALLS
    CALLNODE *cnode,            // - node in call graph for calling function
    CGFILE *file_ctl )          // - current file
{
    SCAN_INFO sc;               // - scan information
    CGINTER *ins;               // - current instruction
    unsigned opcodes;           // - number of significant opcodes
    TYPE curr_type;             // - current type in virtual file
    SYMBOL func;                // - name of function
    SYMBOL sym;                 // - symbol from IC
    TCF tcf;                    // - symbol classification

    if( file_ctl == NULL ) {
        return;
    }
    if( cnode->calls_done ) {
        return;
    }
    scanInit( cnode, file_ctl, &sc );
    ExtraRptIncrementCtr( ctr_funs_scanned );
    _DUMP_CGRF( "scan function body: %s\n", sc.file_ctl->symbol );
    func = sc.file_ctl->symbol;
    if( NULL != func ) {
        func->flag &= ~SF_ADDR_TAKEN;
        _printScanInt( "-- function flags: %x\n", func->flag );
    }
    opcodes = 0;
//  call_graph->assumed_longjump = FALSE;
//  call_graph->does_longjump = FALSE;
    for( ; ; ) {
        ins = CgioReadICMaskCount( sc.file_ctl, ICOPM_CALLGRAPH, ICOPM_OE_COUNT, &opcodes );
        // The following comment is a trigger for the ICMASK program to start
        // scanning for case IC_* patterns.
        // ICMASK BEGIN CALLGRAPH (do not remove)
        switch( ins->opcode ) {
          case IC_DTOR_DLT_BEG :
//          CgioReadICUntilOpcode( sc.file_ctl, IC_DTOR_DLT_END );
            continue;
          case IC_DTOR_DAR_BEG :
//          CgioReadICUntilOpcode( sc.file_ctl, IC_DTOR_DAR_END );
            continue;
          case IC_EXPR_TS :
            addTypeSigRefs( cnode, ins->value.pvalue );
            continue;
          case IC_DATA_PTR_SYM :
            addAddrOf( cnode, ins->value.pvalue );
            continue;
          case IC_DTOR_STATIC :
            addAddrOf( cnode, RoDtorFind( ins->value.pvalue ) );
            continue;
          case IC_SCOPE_CALL_BDTOR :
            if( call_graph->scope_call_opt ) {
                sc.scope_call_blk_dtor = ins->value.pvalue;
            } else {
                dtorRef( ins, &sc, cnode );
            }
            continue;
          case IC_SCOPE_CALL_CDTOR :
            if( call_graph->scope_call_opt ) {
                sc.scope_call_cmp_dtor = ins->value.pvalue;
            } else {
                dtorRef( ins, &sc, cnode );
            }
            continue;
          case IC_SCOPE_CALL_TDTOR :
            if( call_graph->scope_call_opt ) {
                sc.scope_call_tmp_dtor = ins->value.pvalue;
            } else {
                dtorRef( ins, &sc, cnode );
            }
            continue;
          case IC_SCOPE_CALL_FUN :
            if( ! call_graph->scope_call_opt ) continue;
            CgResScopeCall( cnode
                          , ins->value.pvalue
                          , sc.scope_call_cmp_dtor
                          , sc.scope_call_tmp_dtor
                          , sc.scope_call_blk_dtor );
            sc.scope_call_tmp_dtor = NULL;
            sc.scope_call_cmp_dtor = NULL;
            sc.scope_call_blk_dtor = NULL;
            continue;
          case IC_BLOCK_OPEN :
          case IC_BLOCK_DEAD :
          { SCOPE scope = ins->value.pvalue;
            if( NULL != scope && scope->try_catch ) {
                CgrfMarkNodeGen( cnode );
                scope->cg_stab = TRUE;
            }
            if( call_graph->scope_call_opt ) {
                sc.curr_scope = scope;
                CgResScBlkScanBegin( sc.curr_scope, cnode, sc.func_dtm );
            } else {
                if( NULL != scope ) {
                    switch( sc.func_dtm ) {
                      case DTM_DIRECT :
                        break;
                      default :
                        CgrfMarkNodeGen( cnode );
                        scope->cg_stab = TRUE;
                        break;
                    }
                }
            }
          } continue;
          case IC_BLOCK_DONE :
          case IC_BLOCK_END :
            if( ! call_graph->scope_call_opt ) continue;
            sc.curr_scope = CgResScScanEnd();
            continue;
          case IC_EXPR_TEMP:
            if( ! call_graph->scope_call_opt ) continue;
            CgResScStmtScanBegin( sc.curr_scope, cnode, sc.func_dtm );
            call_graph->stmt_scope = TRUE;
            continue;
          case IC_STMT_SCOPE_END :
            if( ! call_graph->scope_call_opt ) continue;
            if( call_graph->stmt_scope ) {
                CgResScScanEnd();
                call_graph->stmt_scope = FALSE;
            }
            continue;
          case IC_EXCEPT_SPEC :
            if( call_graph->scope_call_opt ) {
                CgResScopeGen( cnode );
            }
            sc.has_except_spec = TRUE;
            cnode->stab_gen = TRUE;
            // drops thru
          case IC_CATCH :
            addTypeSigRefs( cnode, ins->value.pvalue );
            continue;
          case IC_TRY :
            if( call_graph->scope_call_opt ) {
                CgResScopeGen( cnode );
                cnode->stmt_state = STS_GEN;
            }
            cnode->stab_gen = TRUE;
            continue;
          case IC_CALL_SETUP :
          { if( NULL != func
             && SymIsThunk( func ) ) {
              SYMBOL called = ins->value.pvalue;
              CALLNODE* called_node = addNode( called );
              forceGeneration( called_node );
            }
            addCalleeFunc( cnode, ins->value.pvalue );
          } continue;
          case IC_DTOR_SUBOBJS :
            cnode->state_table = TRUE;
            if( sc.func_dtm != DTM_DIRECT_SMALL ) continue;
            // drops thru
          case IC_DLT_DTORED :
            if( ! call_graph->scope_call_opt ) {
                cnode->state_table = TRUE;
                CgrfMarkNodeGen( cnode );
                continue;
            }
            // drops thru
          case IC_SCOPE_CALL_GEN :
            if( call_graph->scope_call_opt ) {
                CgResScopeGen( cnode );
            }
            continue;
          case IC_SCOPE_THROW :
            if( ! call_graph->scope_call_opt ) continue;
            CgResScopeThrow( cnode );
            continue;
          case IC_NEW_CTORED :
          { SYMBOL opdel = CgBackOpDelete( ins->value.pvalue );
            addAddrOf( cnode, opdel );
            if( call_graph->scope_call_opt ) {
                CgResScopeCall( cnode, NULL, NULL, opdel, NULL );
            }
          } continue;
          case IC_RTTI_REF :     // REFERENCE TO RTTI CLASS INFO
            RttiRef( ins->value.pvalue );
            continue;
          case IC_TYPEID_REF :     // REFERENCE TO TYPEID INFO
            TypeidRef( ins->value.pvalue );
            continue;
          case IC_VFT_REF :     // REFERENCE TO VFT
            addAddrOf( cnode, ins->value.pvalue );
            continue;
          case IC_FUNCTION_STAB :
            cnode->state_table = TRUE;
            cnode->cond_flags = ins->value.uvalue;
            continue;
          case IC_THROW_RO_BLK :
          { THROW_CNV_CTL ctl;  // - controls conversions
            target_size_t not_used; // - offset not used
            TYPE type;          // - a conversion from thrown object
            ThrowCnvInit( &ctl, ins->value.pvalue );
            for( ; ; ) {
                type = ThrowCnvType( &ctl, &not_used );
                if( type == NULL ) break;
                addTypeSigRefs( cnode, type );
            }
            ThrowCnvFini( &ctl );
          } continue;
          case IC_SET_TYPE :
            curr_type = ins->value.pvalue;
            continue;
          case IC_LEAF_NAME_FRONT :
            sym = ins->value.pvalue;
            curr_type = sym->sym_type;
            tcf = addAddrOf( cnode, sym );
            if( tcf == TCF_NOT_FUNC ) {
                type_flag flags;
                TypeGetActualFlags( sym->sym_type, &flags );
                if( flags & TF1_THREAD ) {
                    SegmentMarkUsed( SEG_TLS );
                }
            }
            continue;
          case IC_FUNCTION_DTM :
            sc.func_dtm = ins->value.uvalue;
            cnode->dtor_method = sc.func_dtm;
            if( DTM_DIRECT_SMALL == sc.func_dtm
             || DTM_TABLE_SMALL == sc.func_dtm ) {
                cnode->depth = max_inline_depth + 1;
                sc.file_ctl->not_inline = TRUE;
//              callGraphFlags.not_inlined_set = TRUE;
                _DUMP_CGRF( "static'ed dtor for -xds: %s\n", func );
            }
            continue;
          case IC_VFT_BEG :     // START OF VFT DEFINITION
          { VFT_DEFN* pvft;     // - points at vft definition
            SYMBOL sym;
            ExtraRptIncrementCtr( ctr_vfts_scanned );
            pvft = RingCarveAlloc( carve_vft, &vft_defs );
            sym = ins->value.pvalue;
            pvft->vft = sym;
            sym->flag &= ~SF_REFERENCED;
            pvft->cgfile = sc.file_ctl;
            pvft->location = CgioLastRead( sc.file_ctl );
            CgioReadICUntilOpcode( sc.file_ctl, IC_INIT_DONE );
          } continue;
          case IC_EOF :
            break;
          default:
            DbgNever();
        }
        // ICMASK END (do not remove)
        break;
    }
    cnode->opcodes = opcodes;
    CgioCloseInputFile( sc.file_ctl );
    func = callNodeCaller( cnode );
    _printScanInt( "-- function flags: %x\n"
                 , func == NULL ? 0 : func->flag );
}


static void pushCaller(         // PUSH A CALLER FOR DEPTH COMPUTATION

⌨️ 快捷键说明

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