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