From 3fa5678ea96d216133054c8a3f094d42b4f9e82a Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Wed, 14 Sep 2005 15:49:45 +0000
Subject: [PATCH] Generate stub functions directly in assembly.

---
 tools/winebuild/build.h  |  1 +
 tools/winebuild/import.c | 12 -------
 tools/winebuild/parser.c |  1 +
 tools/winebuild/spec32.c | 67 +++++++++++++++++++++++++++-------------
 tools/winebuild/utils.c  | 17 ++++++++++
 5 files changed, 64 insertions(+), 34 deletions(-)

diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index 87c69f8b666..afb4c635c45 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -177,6 +177,7 @@ extern void dump_bytes( FILE *outfile, const unsigned char *data, int len,
 extern int remove_stdcall_decoration( char *name );
 extern DLLSPEC *alloc_dll_spec(void);
 extern void free_dll_spec( DLLSPEC *spec );
+extern int has_stubs( const DLLSPEC *spec );
 extern const char *make_c_identifier( const char *str );
 extern unsigned int get_alignment(unsigned int align);
 extern unsigned int get_page_size(void);
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index d2406e3244c..c3f13071d51 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -454,18 +454,6 @@ static void add_import_func( struct import *imp, ORDDEF *func )
     if (imp->delay) total_delayed++;
 }
 
-/* check if the spec file exports any stubs */
-static int has_stubs( const DLLSPEC *spec )
-{
-    int i;
-    for (i = 0; i < spec->nb_entry_points; i++)
-    {
-        ORDDEF *odp = &spec->entry_points[i];
-        if (odp->type == TYPE_STUB) return 1;
-    }
-    return 0;
-}
-
 /* get the default entry point for a given spec file */
 static const char *get_default_entry_point( const DLLSPEC *spec )
 {
diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c
index 5c3e74930d9..4e166c7ee87 100644
--- a/tools/winebuild/parser.c
+++ b/tools/winebuild/parser.c
@@ -368,6 +368,7 @@ static int parse_spec_stub( ORDDEF *odp, DLLSPEC *spec )
 {
     odp->u.func.arg_types[0] = '\0';
     odp->link_name = xstrdup("");
+    odp->flags |= FLAG_I386;  /* don't bother generating stubs for Winelib */
     return 1;
 }
 
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index 8b181e37298..8c4659a1f62 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -270,38 +270,62 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
 
 
 /*******************************************************************
- *         output_stub_funcs
+ *         output_stubs
  *
  * Output the functions for stub entry points
 */
-static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
+static void output_stubs( FILE *outfile, DLLSPEC *spec )
 {
-    int i;
+    const char *name, *exp_name;
+    int i, pos;
+
+    if (!has_stubs( spec )) return;
 
-    for (i = 0; i < spec->nb_entry_points; i++)
+    fprintf( outfile, "asm(\".text\\n\"\n" );
+
+    for (i = pos = 0; i < spec->nb_entry_points; i++)
     {
         ORDDEF *odp = &spec->entry_points[i];
         if (odp->type != TYPE_STUB) continue;
-        fprintf( outfile, "#ifdef __GNUC__\n" );
-        fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func ) __attribute__((noreturn));\n" );
-        fprintf( outfile, "#else\n" );
-        fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func );\n" );
-        fprintf( outfile, "#endif\n\n" );
-        break;
+
+        name = make_internal_name( odp, spec, "stub" );
+        exp_name = odp->name ? odp->name : odp->export_name;
+        fprintf( outfile, "    \"\\t.align %d\\n\"\n", get_alignment(4) );
+        fprintf( outfile, "    \"\\t%s\\n\"\n", func_declaration(name) );
+        fprintf( outfile, "    \"%s:\\n\"\n", asm_name(name) );
+        fprintf( outfile, "    \"\\tcall .L__wine_stub_getpc_%d\\n\"\n", i );
+        fprintf( outfile, "    \".L__wine_stub_getpc_%d:\\n\"\n", i );
+        fprintf( outfile, "    \"\\tpopl %%eax\\n\"\n" );
+        if (exp_name)
+        {
+            fprintf( outfile, "    \"\\tleal .L__wine_stub_strings+%d-.L__wine_stub_getpc_%d(%%eax),%%ecx\\n\"\n",
+                     pos, i );
+            fprintf( outfile, "    \"\\tpushl %%ecx\\n\"\n" );
+            pos += strlen(exp_name) + 1;
+        }
+        else
+            fprintf( outfile, "    \"\\tpushl $%d\\n\"\n", odp->ordinal );
+        fprintf( outfile, "    \"\\tleal %s-.L__wine_stub_getpc_%d(%%eax),%%ecx\\n\"\n",
+                 asm_name("__wine_spec_file_name"), i );
+        fprintf( outfile, "    \"\\tpushl %%ecx\\n\"\n" );
+        fprintf( outfile, "    \"\\tcall %s\\n\"\n", asm_name("__wine_spec_unimplemented_stub") );
+        fprintf( outfile, "    \"\\t%s\\n\"\n", func_size(name) );
     }
 
-    for (i = 0; i < spec->nb_entry_points; i++)
+    if (pos)
     {
-        const ORDDEF *odp = &spec->entry_points[i];
-        if (odp->type != TYPE_STUB) continue;
-        fprintf( outfile, "void %s(void) ", make_internal_name( odp, spec, "stub" ) );
-        if (odp->name)
-            fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->name );
-        else if (odp->export_name)
-            fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->export_name );
-        else
-            fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%d\"); }\n", odp->ordinal );
+        fprintf( outfile, "    \".L__wine_stub_strings:\\n\"\n" );
+        for (i = 0; i < spec->nb_entry_points; i++)
+        {
+            ORDDEF *odp = &spec->entry_points[i];
+            if (odp->type != TYPE_STUB) continue;
+            exp_name = odp->name ? odp->name : odp->export_name;
+            if (exp_name)
+                fprintf( outfile, "    \"\\t%s \\\"%s\\\"\\n\"\n", get_asm_string_keyword(), exp_name );
+        }
     }
+
+    fprintf( outfile, ");\n" );
 }
 
 
@@ -434,8 +458,6 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
 
     fprintf( outfile, "const char __wine_spec_file_name[] = \"%s\";\n", spec->file_name );
 
-    output_stub_funcs( outfile, spec );
-
     /* Output the resources */
 
     resources_size = output_resources( outfile, spec );
@@ -542,6 +564,7 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
     fprintf( outfile, "    \"\\t.long 0,0\\n\"\n" );  /* DataDirectory[15] */
     fprintf( outfile, ");\n" );
 
+    output_stubs( outfile, spec );
     output_exports( outfile, spec );
     output_imports( outfile, spec );
     output_dll_init( outfile, "__wine_spec_init_ctor", NULL );
diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c
index 0b5bc7dbcd7..22d105cca5d 100644
--- a/tools/winebuild/utils.c
+++ b/tools/winebuild/utils.c
@@ -296,6 +296,23 @@ void free_dll_spec( DLLSPEC *spec )
 }
 
 
+/*******************************************************************
+ *         has_stubs
+ *
+ * Check if the spec file exports any stubs
+ */
+int has_stubs( const DLLSPEC *spec )
+{
+    int i;
+    for (i = 0; i < spec->nb_entry_points; i++)
+    {
+        ORDDEF *odp = &spec->entry_points[i];
+        if (odp->type == TYPE_STUB) return 1;
+    }
+    return 0;
+}
+
+
 /*******************************************************************
  *         make_c_identifier
  *
-- 
GitLab