Module: wine Branch: master Commit: 01b44d1317b4cc086e53aa020e9b5815dd999c85 URL: http://source.winehq.org/git/wine.git/?a=commit;h=01b44d1317b4cc086e53aa020e...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Jun 7 12:00:50 2011 +0200
widl: Generate thunks for callas functions using interpreted stubs.
---
tools/widl/proxy.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++- tools/widl/typegen.c | 51 ++++++++++++++++++++++-------------- tools/widl/typegen.h | 1 + 3 files changed, 99 insertions(+), 21 deletions(-)
diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c index 616b326..27c54aa 100644 --- a/tools/widl/proxy.c +++ b/tools/widl/proxy.c @@ -513,6 +513,31 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas, print_proxy("\n"); }
+static void gen_stub_thunk( type_t *iface, const var_t *func, unsigned int proc_offset ) +{ + int has_ret = !is_void( type_function_get_rettype( func->type )); + const var_t *arg, *callas = is_callas( func->attrs ); + const var_list_t *args = type_get_function_args( func->type ); + + indent = 0; + print_proxy( "void __RPC_API %s_%s_Thunk( PMIDL_STUB_MESSAGE pStubMsg )\n", + iface->name, get_name(func) ); + print_proxy( "{\n"); + indent++; + write_func_param_struct( proxy, iface, func->type, "pParamStruct" ); + print_proxy( "%s%s_%s_Stub( pParamStruct->This", + has_ret ? "pParamStruct->_RetVal = " : "", iface->name, callas->name ); + indent++; + if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) + { + fprintf( proxy, ",\n%*spParamStruct->%s", 4 * indent, "", arg->name ); + } + fprintf( proxy, " );\n" ); + indent--; + indent--; + print_proxy( "}\n\n"); +} + int count_methods(const type_t *iface) { const statement_t *stmt; @@ -594,11 +619,33 @@ static int write_stub_methods(type_t *iface, int skip) return i; }
+static void write_thunk_methods( type_t *iface ) +{ + const statement_t *stmt; + int i = 0; + + STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) + { + var_t *func = stmt->u.var; + const var_t *cas = is_callas(func->attrs); + + if (is_local( func->attrs )) continue; + if (i) fprintf(proxy, ",\n"); + if (cas && is_interpreted_func( iface, func )) + print_proxy( "%s_%s_Thunk", iface->name, func->name ); + else + print_proxy( "0" ); + i++; + } + fputc( '\n', proxy ); +} + static void write_proxy(type_t *iface, unsigned int *proc_offset) { int count; const statement_t *stmt; int first_func = 1; + int needs_stub_thunks = 0; int needs_inline_stubs = need_inline_stubs( iface );
STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) { @@ -627,6 +674,11 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) func->procstring_offset = *proc_offset; gen_proxy(iface, func, idx, *proc_offset); gen_stub(iface, func, cname, *proc_offset); + if (cas && is_interpreted_func( iface, func )) + { + needs_stub_thunks = 1; + gen_stub_thunk(iface, func, *proc_offset); + } *proc_offset += get_size_procformatstring_func( iface, func ); } } @@ -654,6 +706,17 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) indent--; print_proxy( "};\n\n");
+ /* stub thunk table */ + if (needs_stub_thunks) + { + print_proxy( "static const STUB_THUNK %s_StubThunkTable[] =\n", iface->name); + print_proxy( "{\n"); + indent++; + write_thunk_methods( iface ); + indent--; + print_proxy( "};\n\n"); + } + /* server info */ print_proxy( "static const MIDL_SERVER_INFO %s_ServerInfo =\n", iface->name ); print_proxy( "{\n" ); @@ -662,7 +725,10 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) print_proxy( "0,\n" ); print_proxy( "__MIDL_ProcFormatString.Format,\n" ); print_proxy( "&%s_FormatStringOffsetTable[-3],\n", iface->name ); - print_proxy( "0,\n" ); + if (needs_stub_thunks) + print_proxy( "&%s_StubThunkTable[-3],\n", iface->name ); + else + print_proxy( "0,\n" ); print_proxy( "0,\n" ); print_proxy( "0,\n" ); print_proxy( "0\n" ); diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 87242d1..7620653 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -4632,6 +4632,36 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char }
+void write_func_param_struct( FILE *file, const type_t *iface, const type_t *func, const char *var_name ) +{ + const var_list_t *args = type_get_function_args( func ); + const var_t *arg; + + print_file(file, 1, "struct _PARAM_STRUCT\n" ); + print_file(file, 1, "{\n" ); + if (is_object( iface )) print_file(file, 2, "%s *This;\n", iface->name ); + + if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) + { + print_file(file, 2, "%s", ""); + write_type_left( file, (type_t *)arg->type, TRUE ); + if (needs_space_after( arg->type )) fputc( ' ', file ); + if (is_array( arg->type ) && !type_array_is_decl_as_ptr( arg->type )) fputc( '*', file ); + /* FIXME: should check for large args being passed by pointer */ + if (is_array( arg->type ) || is_ptr( arg->type ) || type_memsize( arg->type ) == pointer_size) + fprintf( file, "%s;\n", arg->name ); + else + fprintf( file, "%s DECLSPEC_ALIGN(%u);\n", arg->name, pointer_size ); + } + if (!is_void( type_function_get_rettype( func ))) + { + print_file(file, 2, "%s", ""); + write_type_decl( file, type_function_get_rettype( func ), "_RetVal" ); + fprintf( file, ";\n" ); + } + print_file(file, 1, "} *%s = (struct _PARAM_STRUCT *)pStubMsg->StackTop;\n\n", var_name ); +} + int write_expr_eval_routines(FILE *file, const char *iface) { static const char *var_name = "pS"; @@ -4650,26 +4680,7 @@ int write_expr_eval_routines(FILE *file, const char *iface) print_file(file, 0, "{\n"); if (type_get_type( eval->cont_type ) == TYPE_FUNCTION) { - const var_list_t *args = type_get_function_args( eval->cont_type ); - const var_t *arg; - - print_file(file, 1, "struct _PARAM_STRUCT\n" ); - print_file(file, 1, "{\n" ); - if (is_object( eval->iface )) print_file(file, 2, "%s *This;\n", eval->iface->name ); - - if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) - { - print_file(file, 2, "%s", ""); - write_type_left( file, (type_t *)arg->type, TRUE ); - if (needs_space_after( arg->type )) fputc( ' ', file ); - if (is_array( arg->type ) && !type_array_is_decl_as_ptr( arg->type )) fputc( '*', file ); - /* FIXME: should check for large args being passed by pointer */ - if (is_array( arg->type ) || is_ptr( arg->type ) || type_memsize( arg->type ) == pointer_size) - fprintf( file, "%s;\n", arg->name ); - else - fprintf( file, "%s DECLSPEC_ALIGN(%u);\n", arg->name, pointer_size ); - } - print_file(file, 1, "} *pS = (struct _PARAM_STRUCT *)pStubMsg->StackTop;\n" ); + write_func_param_struct( file, eval->iface, eval->cont_type, "pS" ); } else { diff --git a/tools/widl/typegen.h b/tools/widl/typegen.h index 5920fb1..7f3aed1 100644 --- a/tools/widl/typegen.h +++ b/tools/widl/typegen.h @@ -75,6 +75,7 @@ unsigned int get_size_procformatstring(const statement_list_t *stmts, type_pred_ unsigned int get_size_typeformatstring(const statement_list_t *stmts, type_pred_t pred); void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char *local_var_prefix ); void declare_stub_args( FILE *file, int indent, const var_t *func ); +void write_func_param_struct( FILE *file, const type_t *iface, const type_t *func, const char *var_name ); int write_expr_eval_routines(FILE *file, const char *iface); void write_expr_eval_routine_list(FILE *file, const char *iface); void write_user_quad_list(FILE *file);