thunk.c

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

C
487
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "plusplus.h"
#include "cgfront.h"
#include "fnbody.h"
#include "defarg.h"
#include "errdefns.h"
#include "rtngen.h"
#include "objmodel.h"
#include "cgio.h"


static SYMBOL existingThunk(    // GET EXISTING THUNK SYMBOL FOR NAME
    SCOPE scope,                // - scope to look in
    char *name )                // - thunk name
{
    SYMBOL sym;                 // - symbol for name
    SEARCH_RESULT *result;      // - search result

    if( ScopeId( scope ) == SCOPE_FILE ) {
        result = ScopeFindNaked( scope, name );
    } else {
        result = ScopeContainsMember( scope, name );
    }
    if( result != NULL ) {
        sym = result->sym_name->name_syms;
        ScopeFreeResult( result );
    } else {
        sym = NULL;
    }
    return( sym );
}


static unsigned classifyThunk(  // GET CLASSIFICATION OF THUNK
    SYMBOL sym )                // - original symbol
{
    unsigned classification;    // - classification of thunk

    DbgAssert( ! SymIsThunk( sym ) );
    if( SymIsDtor( sym ) ) {
        classification = SPECIAL_DTOR_THUNK;
    } else if( SymIsOpDel( sym ) ) {
        classification = SPECIAL_OP_DEL_THUNK;
    } else if( SymIsOpDelar( sym ) ) {
        classification = SPECIAL_OP_DELAR_THUNK;
    } else if( TypeHasNumArgs( sym->sym_type, 1 ) ) {
        DbgAssert( SymIsCtor( sym ) );
        classification = SPECIAL_COPY_THUNK;
    } else {
        DbgAssert( SymIsCtor( sym ) );
        classification = SPECIAL_CTOR_THUNK;
    }
    return classification;
}


static SYMBOL addrThunkSymbol(  // GET THUNK SYMBOL FROM ORIGINAL
    unsigned classification,    // - classification of thunk
    SYMBOL sym )                // - original symbol
{
    TYPE thunk_type;            // - type of new symbol
    SYMBOL new_sym;             // - the new symbol
    SCOPE scope;                // - scope for new symbol
    char *name;                 // - name of new symbol
    symbol_class thunk_class;   // - SC_.. for thunk

    switch( classification ) {
      case SPECIAL_OP_DEL_THUNK :
      case SPECIAL_OP_DELAR_THUNK :
        thunk_class = SC_STATIC;
        break;
      case SPECIAL_DTOR_THUNK :
      case SPECIAL_COPY_THUNK :
      case SPECIAL_CTOR_THUNK :
        thunk_class = SC_MEMBER;
        break;
      DbgDefault( "addrThunkSymbol -- bad classification" );
    }
    name = CppSpecialName( classification );
    scope = SymScope( sym );
    new_sym = existingThunk( scope, name );
    if( new_sym == NULL ) {
        thunk_type = MakeThunkFunction( sym->sym_type );
        new_sym = AllocTypedSymbol( thunk_type );
        new_sym->id = thunk_class;
        new_sym->flag |= SF_ADDR_THUNK;
        new_sym = ScopeInsert( scope, new_sym, name );
        SymDeriveThrowBits( new_sym, sym );
    }
    return new_sym;
}


static void insertArgument(     // INSERT AN ARGUMENT
    TYPE type )                 // - type of argument
{
    char *name;                 // - name of argument
    SYMBOL sym;                 // - new argument

    sym = SymMakeDummy( type, &name );
    ScopeInsert( GetCurrScope(), sym, name );
}


static void declareThunkArgs(   // DECLARE ARG.S FOR THUNK
    SYMBOL fn_sym,              // - original symbol
    TYPE fn_type )              // - type of thunk
{
    unsigned num_args;          // - # arguments
    arg_list *args;             // - arguments
    TYPE *curr;                 // - addr[ current argument type ]

    if( SymCDtorExtraParm( fn_sym ) ) {
        insertArgument( MakeCDtorExtraArgType() );
    }
    args = fn_type->u.f.args;
    for( num_args = args->num_args, curr = args->type_list
       ; num_args != 0
       ; ++curr, --num_args ) {
        insertArgument( *curr );
    }
}


static SCOPE thunkPrologue(     // PROLOGUE FOR A SCOPE
    SYMBOL thunk_sym,           // - thunk symbol
    FUNCTION_DATA *data )       // - function data
{
    SYMBOL orig;                // - original symbol
    SCOPE arg_scope;            // - scope for arguments

    orig = thunk_sym->u.thunk_calls;
    thunk_sym->flag |= SF_INITIALIZED;
    SetCurrScope (SymScope( thunk_sym ));
    ScopeBeginFunction( thunk_sym );
    arg_scope = GetCurrScope();
    declareThunkArgs( orig, FunctionDeclarationType( orig->sym_type ) );
    FunctionBodyStartup( thunk_sym, data, FUNC_NULL );
    return arg_scope;
}


static void thunkEpilogue(      // THUNK EPILOGUE
    SYMBOL thunk_sym,           // - thunk symbol
    FUNCTION_DATA *data )       // - generation data
{
    FunctionBodyShutdown( thunk_sym, data );
    ScopeEnd( SCOPE_FUNCTION );
}


static PTREE thunkArgList(      // BUILD THUNK ARGUMENT LIST
    SCOPE scope )               // - scope for arguments
{
    char *ret_name;             // - name of return value symbol
    PTREE expr;                 // - argument expression
    PTREE list;                 // - arg. list under construction
    SYMBOL stopper;             // - stopping value
    SYMBOL sym;                 // - current symbol
    unsigned count;             // - # in list
    OMR arg_model;              // - argument calling convention model
    TYPE arg_type;              // - unmodified argument type from symbol

    ret_name = CppSpecialName( SPECIAL_RETURN_VALUE );
    stopper = ScopeOrderedStart( scope );
    sym = NULL;
    list = NULL;
    for(;;) {
        sym = ScopeOrderedNext( stopper, sym );
        if( sym == NULL ) break;
        if( sym->name->name != ret_name ) {
            arg_type = TypedefModifierRemoveOnly( sym->sym_type );
            expr = MakeNodeSymbol( sym );
            expr = NodeFetchReference( expr );
            arg_model = ObjModelArgument( TypeReferenced( arg_type ) );
            if( TypeReference( arg_type ) == NULL && arg_model != OMR_CLASS_REF ) {
                expr = NodeRvalue( expr );
            }
            list = NodeArgument( list, expr );
        }
    }
    list = NodeReverseArgs( &count, list );
    return( list );
}


SYMBOL ClassFunMakeAddressable( // MAKE SURE THE FUNCTION CAN BE ADDRESSED
    SYMBOL orig_sym )           // - original symbol
{
    SYMBOL thunk_sym;           // - thunk symbol
    unsigned classification;    // - classification of thunk

    if( orig_sym == NULL ) {
        return orig_sym;
    }
    if( ( orig_sym->id != SC_DEFAULT )
      &&( ! TypeHasPragma( orig_sym->sym_type ) ) ) {
        type_flag flags;
        TypeModFlags( orig_sym->sym_type, &flags );
        if( ! ( flags & TF1_DLLIMPORT ) ) {
            return orig_sym;
        }
    }
    classification = classifyThunk( orig_sym );
    thunk_sym = addrThunkSymbol( classification, orig_sym );
    if( NULL == thunk_sym->u.thunk_calls ) {
        if( ! SymIsVirtual( orig_sym ) ) {
            thunk_sym = SymDeriveThrowBits( thunk_sym, orig_sym );
        }
        thunk_sym->u.thunk_calls = orig_sym;
        RtnGenAddSymbol( RGSYMBOL_GenThunk, thunk_sym );
    }
    return thunk_sym;

⌨️ 快捷键说明

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