Generate stub functions directly in assembly.
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index 87c69f8..afb4c63 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -177,6 +177,7 @@
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 d2406e3..c3f1307 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -454,18 +454,6 @@
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 5c3e749..4e166c7 100644
--- a/tools/winebuild/parser.c
+++ b/tools/winebuild/parser.c
@@ -368,6 +368,7 @@
{
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 8b181e3..8c4659a 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -270,38 +270,62 @@
/*******************************************************************
- * 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;
- for (i = 0; i < spec->nb_entry_points; i++)
+ if (!has_stubs( spec )) return;
+
+ 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 @@
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 @@
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 0b5bc7d..22d105c 100644
--- a/tools/winebuild/utils.c
+++ b/tools/winebuild/utils.c
@@ -297,6 +297,23 @@
/*******************************************************************
+ * 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
*
* Map a string to a valid C identifier.