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