Sync to Wine-0_9_4:
authorGé van Geldorp <ge@gse.nl>
Mon, 26 Dec 2005 22:51:29 +0000 (22:51 +0000)
committerGé van Geldorp <ge@gse.nl>
Mon, 26 Dec 2005 22:51:29 +0000 (22:51 +0000)
Alexandre Julliard <julliard@winehq.org>
- winebuild: Allow -register flag for Win32 too.
  This way it can be used as hint for the relay code.
- ntdll: Make __wine_call_from_32_restore_regs take a context pointer.
  Changed exception raise functions to call it explicitly.
- ntdll: New implementation of relay thunks.
  New implementation of relay thunks that doesn't require modifying code
  on the fly, so that the thunks can be put in the text section.
  Some performance improvements.

svn path=/trunk/; revision=20344

reactos/tools/winebuild/build.h
reactos/tools/winebuild/import.c
reactos/tools/winebuild/parser.c
reactos/tools/winebuild/relay.c
reactos/tools/winebuild/spec32.c
reactos/tools/winebuild/utils.c
reactos/tools/winebuild/winebuild.man.in

index 8543ef6..7f66b5b 100644 (file)
@@ -189,6 +189,7 @@ extern const char *asm_globl( const char *func );
 extern const char *get_asm_ptr_keyword(void);
 extern const char *get_asm_string_keyword(void);
 extern const char *get_asm_short_keyword(void);
+extern const char *get_asm_rodata_section(void);
 extern const char *get_asm_string_section(void);
 extern void output_function_size( FILE *outfile, const char *name );
 
@@ -199,6 +200,7 @@ extern void add_extra_ld_symbol( const char *name );
 extern void read_undef_symbols( DLLSPEC *spec, char **argv );
 extern int resolve_imports( DLLSPEC *spec );
 extern int has_imports(void);
+extern int has_relays( DLLSPEC *spec );
 extern void output_get_pc_thunk( FILE *outfile );
 extern void output_stubs( FILE *outfile, DLLSPEC *spec );
 extern void output_imports( FILE *outfile, DLLSPEC *spec );
index 6f8bd28..a51eb30 100644 (file)
@@ -1245,5 +1245,6 @@ void output_imports( FILE *outfile, DLLSPEC *spec )
     output_immediate_import_thunks( outfile );
     output_delayed_import_thunks( outfile, spec );
     output_external_link_imports( outfile, spec );
-    if (nb_imports || ext_link_imports.count || has_stubs(spec)) output_get_pc_thunk( outfile );
+    if (nb_imports || ext_link_imports.count || has_stubs(spec) || has_relays(spec))
+        output_get_pc_thunk( outfile );
 }
index 5352b7a..1ea3376 100644 (file)
@@ -516,12 +516,6 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
         odp->ordinal = ordinal;
     }
 
-    if (spec->type == SPEC_WIN32 && odp->flags & FLAG_REGISTER)
-    {
-        error( "-register flag not supported for Win32 entry points\n" );
-        goto error;
-    }
-
     if (odp->type == TYPE_STDCALL && !(odp->flags & FLAG_PRIVATE))
     {
         if (!strcmp( odp->name, "DllRegisterServer" ) ||
index e53a839..ccf37ec 100644 (file)
@@ -849,7 +849,7 @@ static void BuildCallFrom32Regs( FILE *outfile )
     output_function_size( outfile, "__wine_call_from_32_regs" );
 
     function_header( outfile, "__wine_call_from_32_restore_regs" );
-    fprintf( outfile, "\tleal 4(%%esp),%%ecx\n" );
+    fprintf( outfile, "\tmovl 4(%%esp),%%ecx\n" );
     fprintf( outfile, "\tjmp 2b\n" );
     output_function_size( outfile, "__wine_call_from_32_restore_regs" );
 }
index ed500c7..bf45ffd 100644 (file)
 #include "build.h"
 
 
+/* check if entry point needs a relay thunk */
+static inline int needs_relay( const ORDDEF *odp )
+{
+    /* skip nonexistent entry points */
+    if (!odp) return 0;
+    /* skip non-functions */
+    if ((odp->type != TYPE_STDCALL) && (odp->type != TYPE_CDECL)) return 0;
+    /* skip norelay and forward entry points */
+    if (odp->flags & (FLAG_NORELAY|FLAG_FORWARD)) return 0;
+    return 1;
+}
+
+/* check if dll will output relay thunks */
+int has_relays( DLLSPEC *spec )
+{
+    unsigned int i;
 
+    if (target_cpu != CPU_x86) return 0;
+
+    for (i = spec->base; i <= spec->limit; i++)
+    {
+        ORDDEF *odp = spec->ordinals[i];
+        if (needs_relay( odp )) return 1;
+    }
+    return 0;
+}
 
 /*******************************************************************
  *         make_internal_name
@@ -61,6 +86,101 @@ static const char *make_internal_name( const ORDDEF *odp, DLLSPEC *spec, const c
 }
 
 
+/*******************************************************************
+ *         output_relay_debug
+ *
+ * Output entry points for relay debugging
+ */
+static void output_relay_debug( FILE *outfile, DLLSPEC *spec )
+{
+    unsigned int i, j, args, flags;
+
+    /* first the table of entry point offsets */
+
+    fprintf( outfile, "\t%s\n", get_asm_rodata_section() );
+    fprintf( outfile, "\t.align %d\n", get_alignment(4) );
+    fprintf( outfile, ".L__wine_spec_relay_entry_point_offsets:\n" );
+
+    for (i = spec->base; i <= spec->limit; i++)
+    {
+        ORDDEF *odp = spec->ordinals[i];
+
+        if (needs_relay( odp ))
+            fprintf( outfile, "\t.long .L__wine_spec_relay_entry_point_%d-__wine_spec_relay_entry_points\n", i );
+        else
+            fprintf( outfile, "\t.long 0\n" );
+    }
+
+    /* then the table of argument types */
+
+    fprintf( outfile, "\t.align %d\n", get_alignment(4) );
+    fprintf( outfile, ".L__wine_spec_relay_arg_types:\n" );
+
+    for (i = spec->base; i <= spec->limit; i++)
+    {
+        ORDDEF *odp = spec->ordinals[i];
+        unsigned int mask = 0;
+
+        if (needs_relay( odp ))
+        {
+            for (j = 0; j < 16 && odp->u.func.arg_types[j]; j++)
+            {
+                if (odp->u.func.arg_types[j] == 't') mask |= 1<< (j*2);
+                if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
+            }
+        }
+        fprintf( outfile, "\t.long 0x%08x\n", mask );
+    }
+
+    /* then the relay thunks */
+
+    fprintf( outfile, "\t.text\n" );
+    fprintf( outfile, "__wine_spec_relay_entry_points:\n" );
+    fprintf( outfile, "\tnop\n" );  /* to avoid 0 offset */
+
+    for (i = spec->base; i <= spec->limit; i++)
+    {
+        ORDDEF *odp = spec->ordinals[i];
+
+        if (!needs_relay( odp )) continue;
+
+        fprintf( outfile, "\t.align %d\n", get_alignment(4) );
+        fprintf( outfile, ".L__wine_spec_relay_entry_point_%d:\n", i );
+
+        if (odp->flags & FLAG_REGISTER)
+            fprintf( outfile, "\tpushl %%eax\n" );
+        else
+            fprintf( outfile, "\tpushl %%esp\n" );
+
+        args = strlen(odp->u.func.arg_types);
+        flags = 0;
+        if (odp->flags & FLAG_RET64) flags |= 1;
+        if (odp->type == TYPE_STDCALL) flags |= 2;
+        fprintf( outfile, "\tpushl $%u\n", (flags << 24) | (args << 16) | (i - spec->base) );
+
+        if (UsePIC)
+        {
+            fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
+            fprintf( outfile, "1:\tleal .L__wine_spec_relay_descr-1b(%%eax),%%eax\n" );
+        }
+        else fprintf( outfile, "\tmovl $.L__wine_spec_relay_descr,%%eax\n" );
+        fprintf( outfile, "\tpushl %%eax\n" );
+
+        if (odp->flags & FLAG_REGISTER)
+        {
+            fprintf( outfile, "\tcall *8(%%eax)\n" );
+        }
+        else
+        {
+            fprintf( outfile, "\tcall *4(%%eax)\n" );
+            if (odp->type == TYPE_STDCALL)
+                fprintf( outfile, "\tret $%u\n", args * get_ptr_size() );
+            else
+                fprintf( outfile, "\tret\n" );
+        }
+    }
+}
+
 /*******************************************************************
  *         output_exports
  *
@@ -183,58 +303,27 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
                 fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), odp->link_name );
         }
     }
-    fprintf( outfile, "\t.align %d\n", get_alignment(4) );
+    fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
     fprintf( outfile, ".L__wine_spec_exports_end:\n" );
 
     /* output relays */
 
     /* we only support relay debugging on i386 */
-    if (target_cpu == CPU_x86)
+    if (target_cpu != CPU_x86)
     {
-        for (i = spec->base; i <= spec->limit; i++)
-        {
-            ORDDEF *odp = spec->ordinals[i];
-            unsigned int j, args, mask = 0;
-
-            /* skip nonexistent entry points */
-            if (!odp) goto ignore;
-            /* skip non-functions */
-            if ((odp->type != TYPE_STDCALL) && (odp->type != TYPE_CDECL)) goto ignore;
-            /* skip norelay and forward entry points */
-            if (odp->flags & (FLAG_NORELAY|FLAG_FORWARD)) goto ignore;
-
-            for (j = 0; odp->u.func.arg_types[j]; j++)
-            {
-                if (odp->u.func.arg_types[j] == 't') mask |= 1<< (j*2);
-                if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
-            }
-            if ((odp->flags & FLAG_RET64) && (j < 16)) mask |= 0x80000000;
-
-            args = strlen(odp->u.func.arg_types) * get_ptr_size();
+        fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
+        return;
+    }
 
-            switch(odp->type)
-            {
-            case TYPE_STDCALL:
-                fprintf( outfile, "\tjmp %s\n", asm_name(odp->link_name) );
-                fprintf( outfile, "\tret $%d\n", args );
-                fprintf( outfile, "\t.long %s,0x%08x\n", asm_name(odp->link_name), mask );
-                break;
-            case TYPE_CDECL:
-                fprintf( outfile, "\tjmp %s\n", asm_name(odp->link_name) );
-                fprintf( outfile, "\tret\n" );
-                fprintf( outfile, "\t%s %d\n", get_asm_short_keyword(), args );
-                fprintf( outfile, "\t.long %s,0x%08x\n", asm_name(odp->link_name), mask );
-                break;
-            default:
-                assert(0);
-            }
-            continue;
+    fprintf( outfile, ".L__wine_spec_relay_descr:\n" );
+    fprintf( outfile, "\t%s 0xdeb90001\n", get_asm_ptr_keyword() );  /* magic */
+    fprintf( outfile, "\t%s 0,0\n", get_asm_ptr_keyword() );         /* relay funcs */
+    fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );           /* private data */
+    fprintf( outfile, "\t%s __wine_spec_relay_entry_points\n", get_asm_ptr_keyword() );
+    fprintf( outfile, "\t%s .L__wine_spec_relay_entry_point_offsets\n", get_asm_ptr_keyword() );
+    fprintf( outfile, "\t%s .L__wine_spec_relay_arg_types\n", get_asm_ptr_keyword() );
 
-        ignore:
-            fprintf( outfile, "\t.long 0,0,0,0\n" );
-        }
-    }
-    else fprintf( outfile, "\t.long 0\n" );
+    output_relay_debug( outfile, spec );
 }
 
 
index fbbfa45..85d5523 100644 (file)
@@ -585,6 +585,15 @@ const char *get_asm_short_keyword(void)
     }
 }
 
+const char *get_asm_rodata_section(void)
+{
+    switch (target_platform)
+    {
+    case PLATFORM_APPLE: return ".const";
+    default:             return ".section .rodata";
+    }
+}
+
 const char *get_asm_string_section(void)
 {
     switch (target_platform)
index a682a10..6c9bafc 100644 (file)
@@ -260,7 +260,7 @@ The function returns a 64-bit value (Win32 only).
 The entry point is only available on i386 platforms.
 .TP
 .B -register
-The function uses CPU register to pass arguments (Win16 only).
+The function uses CPU register to pass arguments.
 .TP
 .B -private
 The function cannot be imported from other dlls, it can only be