Alexandre Julliard : widl: Generate thunks for callas functions using interpreted stubs.

Alexandre Julliard julliard at winehq.org
Tue Jun 7 12:02:34 CDT 2011


Module: wine
Branch: master
Commit: 01b44d1317b4cc086e53aa020e9b5815dd999c85
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=01b44d1317b4cc086e53aa020e9b5815dd999c85

Author: Alexandre Julliard <julliard at 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);




More information about the wine-cvs mailing list