Sync to Wine-0_9_4:
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.
Modified: trunk/reactos/tools/winebuild/build.h
Modified: trunk/reactos/tools/winebuild/import.c
Modified: trunk/reactos/tools/winebuild/parser.c
Modified: trunk/reactos/tools/winebuild/relay.c
Modified: trunk/reactos/tools/winebuild/spec32.c
Modified: trunk/reactos/tools/winebuild/utils.c
Modified: trunk/reactos/tools/winebuild/winebuild.man.in

Modified: trunk/reactos/tools/winebuild/build.h
--- trunk/reactos/tools/winebuild/build.h	2005-12-26 21:47:28 UTC (rev 20343)
+++ trunk/reactos/tools/winebuild/build.h	2005-12-26 22:51:29 UTC (rev 20344)
@@ -189,6 +189,7 @@
 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 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 );

Modified: trunk/reactos/tools/winebuild/import.c
--- trunk/reactos/tools/winebuild/import.c	2005-12-26 21:47:28 UTC (rev 20343)
+++ trunk/reactos/tools/winebuild/import.c	2005-12-26 22:51:29 UTC (rev 20344)
@@ -1245,5 +1245,6 @@
     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 );
 }

Modified: trunk/reactos/tools/winebuild/parser.c
--- trunk/reactos/tools/winebuild/parser.c	2005-12-26 21:47:28 UTC (rev 20343)
+++ trunk/reactos/tools/winebuild/parser.c	2005-12-26 22:51:29 UTC (rev 20344)
@@ -516,12 +516,6 @@
         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" ) ||

Modified: trunk/reactos/tools/winebuild/relay.c
--- trunk/reactos/tools/winebuild/relay.c	2005-12-26 21:47:28 UTC (rev 20343)
+++ trunk/reactos/tools/winebuild/relay.c	2005-12-26 22:51:29 UTC (rev 20344)
@@ -849,7 +849,7 @@
     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" );
 }

Modified: trunk/reactos/tools/winebuild/spec32.c
--- trunk/reactos/tools/winebuild/spec32.c	2005-12-26 21:47:28 UTC (rev 20343)
+++ trunk/reactos/tools/winebuild/spec32.c	2005-12-26 22:51:29 UTC (rev 20344)
@@ -37,8 +37,33 @@
 #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
  *
@@ -62,6 +87,101 @@
 
 
 /*******************************************************************
+ *         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
  *
  * Output the export table for a Win32 module.
@@ -183,58 +303,27 @@
                 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;
+        fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
+        return;
+    }
 
-            /* 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;
+    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() );
 
-            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();
-
-            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;
-
-        ignore:
-            fprintf( outfile, "\t.long 0,0,0,0\n" );
-        }
-    }
-    else fprintf( outfile, "\t.long 0\n" );
+    output_relay_debug( outfile, spec );
 }
 
 

Modified: trunk/reactos/tools/winebuild/utils.c
--- trunk/reactos/tools/winebuild/utils.c	2005-12-26 21:47:28 UTC (rev 20343)
+++ trunk/reactos/tools/winebuild/utils.c	2005-12-26 22:51:29 UTC (rev 20344)
@@ -585,6 +585,15 @@
     }
 }
 
+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)

Modified: trunk/reactos/tools/winebuild/winebuild.man.in
--- trunk/reactos/tools/winebuild/winebuild.man.in	2005-12-26 21:47:28 UTC (rev 20343)
+++ trunk/reactos/tools/winebuild/winebuild.man.in	2005-12-26 22:51:29 UTC (rev 20344)
@@ -260,7 +260,7 @@
 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