thunk.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 487 行 · 第 1/2 页
C
487 行
}
void RtnGenCallBackGenThunk( // GENERATE THUNK CODE
SYMBOL thunk_sym ) // - the thunk symbol
{
SYMBOL orig_sym; // - original symbol
PTREE args; // - arguments for call
PTREE stmt; // - expression under construction
TYPE return_type; // - return type of original, thunk
SYMBOL return_sym; // - return symbol for thunk routine
SYMBOL curr_func; // - function being compiled before thunk
SCOPE fn_scope; // - scope for thunk-function arguments
SCOPE save_scope; // - CurrScope before generation of thunk
FUNCTION_DATA func_data; // - controls thunk generation
PTREE extra_arg; // - Ctor/Dtor extra argument
PTREE user_args; // - user arguments for function
PTREE this_arg; // - "this" argument
unsigned classification; // - classification of thunk
CGFILE* cgfile; // - CGFILE for thunk
symbol_flag orig_ref; // - keep original SF_REFERENCED setting
orig_sym = thunk_sym->u.thunk_calls;
if( thunk_sym->flag & SF_REFERENCED ) {
orig_sym->flag |= SF_REFERENCED;
}
if( SymIsInitialized( thunk_sym ) ) {
return;
}
classification = classifyThunk( orig_sym );
save_scope = GetCurrScope();
curr_func = CgFrontCurrentFunction();
fn_scope = thunkPrologue( thunk_sym, &func_data );
return_type = SymFuncReturnType( thunk_sym );
args = thunkArgList( fn_scope );
orig_ref = orig_sym->flag & SF_REFERENCED;
stmt = NodeMakeCall( orig_sym, return_type, args );
if( ! orig_ref ) {
orig_sym->flag &= ~SF_REFERENCED;
}
if( ! AddDefaultArgs( orig_sym, stmt ) ) {
NodeFreeDupedExpr( stmt );
} else {
user_args = stmt->u.subtree[1];
if( SymCDtorExtraParm( orig_sym ) ) {
extra_arg = user_args;
user_args = user_args->u.subtree[0];
} else {
extra_arg = NULL;
}
if( SymIsThisMember( orig_sym ) ) {
this_arg = NodeArg( NodeThis() );
} else {
this_arg = NULL;
}
stmt = CallArgsArrange( orig_sym->sym_type
, stmt
, user_args
, this_arg
, extra_arg
, NULL );
stmt = FunctionCalled( stmt, orig_sym );
return_sym = SymFunctionReturn();
if( NULL != return_sym ) {
stmt = PTreeBinary( CO_RETURN, PTreeType( return_type ), stmt );
stmt = AnalyseNode( stmt );
}
EmitAnalysedStmt( stmt );
}
CgFrontCodePtr( IC_PROC_RETURN, return_sym );
thunkEpilogue( thunk_sym, &func_data );
SetCurrScope(save_scope);
CgFrontResumeFunction( curr_func );
cgfile = CgioLocateFile( thunk_sym );
cgfile->thunk = TRUE;
if( ( SymIsInitialized( orig_sym ) )
||( SymIsDefArg( orig_sym ) )
||( classification == SPECIAL_OP_DEL_THUNK )
||( classification == SPECIAL_OP_DELAR_THUNK ) ) {
CgioThunkMarkGen( cgfile );
}
}
static PTREE applyReturnThunk( // GENERATE A RETURN THUNK
THUNK_ACTION *thunk, // - thunk description
PTREE expr ) // - current expression
{
target_offset_t delta; // - output delta
target_offset_t vb_offset; // - output offset
target_offset_t vb_index; // - output index
TYPE ret_type; // - type of call expression
TYPE ptr_type; // - pointer equivalent of "ret_type"
PTREE dup1;
PTREE dup2;
delta = thunk->out.delta;
if( !thunk->output_virtual && delta == 0 ) {
/* no return thunk */
return( expr );
}
ret_type = NodeType( expr );
dup1 = NULL;
ptr_type = PointerTypeEquivalent( ret_type );
if( ptr_type != NULL ) {
/* only need NULL checks for pointer casts */
if( ptr_type->id == TYP_POINTER ) {
if(( ptr_type->flag & TF1_REFERENCE ) == 0 ) {
dup1 = NodeDupExpr( &expr );
}
}
}
DbgAssert( StructType( ret_type ) == NULL );
if( thunk->output_virtual ) {
vb_offset = thunk->out.vb_offset;
vb_index = thunk->out.vb_index;
expr = NodeConvertVirtualPtr( expr, ret_type, vb_offset, vb_index );
}
if( delta != 0 ) {
expr = NodeBinary( CO_PLUS, expr, NodeOffset( delta ) );
expr->type = ret_type;
}
if( dup1 != NULL ) {
dup2 = NodeDupExpr( &dup1 );
dup1 = NodeCompareToZero( dup1 );
expr = NodeTestExpr( dup1, expr, dup2 );
}
return( expr );
}
void EmitVfunThunk( // EMIT THUNK FOR VIRTUAL FUNCTION
SCOPE host_scope, // - scope for thunk insertion
THUNK_ACTION *thunk ) // - thunk description
{
SCOPE scope;
SYMBOL sym;
SYMBOL thunk_sym;
SYMBOL override_sym;
SYMBOL return_sym;
char *name;
PTREE stmt;
PTREE args;
PTREE this_arg;
PTREE return_node;
TYPE thunk_type;
TYPE fn_type;
TYPE override_class;
TYPE return_type;
SCOPE save_scope;
SCOPE fn_scope;
auto FUNCTION_DATA func_data;
override_sym = thunk->override;
if( override_sym == NULL ) {
/* pure virtual function with no override */
thunk->thunk = thunk->sym; // let CGINFO do it
return;
}
sym = thunk->sym;
if( SymIsEllipsisFunc( sym ) ) {
CErr( ERR_NO_VIRTUAL_ELLIPSE_FUNCTION_THUNKS, sym );
InfMsgPtr( INF_THUNK_TARGET, override_sym );
}
save_scope = GetCurrScope();
thunk_type = MakeThunkPragmaFunction( sym->sym_type );
thunk_sym = AllocTypedSymbol( thunk_type );
name = CppThunkName( host_scope, thunk );
scope = SymScope( thunk->sym );
SetCurrScope (scope);
thunk_sym = ScopeInsert( scope, thunk_sym, name );
thunk->thunk = thunk_sym;
ScopeBeginFunction( thunk_sym );
fn_scope = GetCurrScope();
fn_type = FunctionDeclarationType( thunk_type );
declareThunkArgs( sym, fn_type );
FunctionBodyStartup( thunk_sym, &func_data, FUNC_NO_STACK_CHECK );
if( thunk->delta != 0 ) {
CgFrontCodeUint( IC_VTHUNK_MDELTA, thunk->delta );
}
if( thunk->ctor_disp ) {
CgFrontCode( IC_VTHUNK_CDISP );
if( thunk->input_virtual ) {
CgFrontCodeUint( IC_VTHUNK_PDELTA, thunk->in.vb_offset );
CgFrontCodeUint( IC_VTHUNK_VBASE, thunk->in.vb_index );
}
if( thunk->in.delta ) {
CgFrontCodeUint( IC_VTHUNK_PDELTA, thunk->in.delta );
}
}
override_class = ScopeClass( SymScope( override_sym ) );
args = thunkArgList( fn_scope );
/* make "this" arg */
this_arg = NodeRvalue( NodeThis() );
this_arg = NodeConvert( MakePointerTo( override_class ), this_arg );
this_arg = NodeArg( this_arg );
return_type = SymFuncReturnType( override_sym );
return_node = NULL;
if( OMR_CLASS_REF == ObjModelArgument( return_type ) ) {
return_node = NodeTemporary( return_type );
}
stmt = NodeMakeCall( override_sym, return_type, args );
stmt = CallArgsArrange( override_sym->sym_type, stmt, args, this_arg, NULL, return_node );
if( return_node != NULL ) {
stmt = NodeDtorExpr( stmt, return_node->u.symcg.symbol );
stmt = PtdCtoredExprType( stmt, override_sym, return_type );
}
return_sym = SymFunctionReturn();
if( return_sym == NULL ) {
EmitAnalysedStmt( stmt );
} else {
stmt = applyReturnThunk( thunk, stmt );
stmt = PTreeBinary( CO_RETURN, PTreeType( return_type ), stmt );
stmt = AnalyseNode( stmt );
EmitAnalysedStmt( stmt );
CgFrontCodePtr( IC_PROC_RETURN, return_sym );
}
FunctionBodyShutdown( thunk_sym, &func_data );
ScopeEnd( SCOPE_FUNCTION );
SetCurrScope (save_scope);
}
// Later: generate proper thunk which will re-map arguments for
// the specialized calling conventions
//
void RtnGenCallBackRunTimeTableThunk( // GEN. THUNK TO RE-MAP CTOR/DTOR arg.s
SYMBOL sym ) // - the symbol
{
CErr2p( ERR_BAD_CALL_CONVENTION, sym );
}
void CDtorScheduleArgRemap( // SCHEDULE CTOR/DTOR ARG.S REMAP, IF REQ'D
SYMBOL cdtor ) // - CTOR OR DTOR
{
TYPE ftype; // - declaration type of function
ftype = FunctionDeclarationType( cdtor->sym_type );
if( TypeHasEllipsisArg( ftype ) || TypeHasReverseArgs( ftype ) ) {
RtnGenAddSymbol( RGSYMBOL_RunTimeTableThunk, cdtor );
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?