It's still not safe to call a __fastcall function from Wine source, though, since we can't rely on this being present.
winebuild still wants the old wrapper names, so for now we define aliases.
Signed-off-by: Chip Davis cdavis@codeweavers.com --- dlls/hal/hal.c | 2 +- include/ddk/wdm.h | 6 +++--- include/windef.h | 21 +++++++++++++++------ include/wine/asm.h | 26 +++++++++++++++++++------- 4 files changed, 38 insertions(+), 17 deletions(-)
diff --git a/dlls/hal/hal.c b/dlls/hal/hal.c index 21ce6e12c99..2365cac57d0 100644 --- a/dlls/hal/hal.c +++ b/dlls/hal/hal.c @@ -34,7 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl);
#ifdef __i386__
-#ifndef _WIN32 +#if !defined(_WIN32) && ((__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4))
extern void * WINAPI wrap_fastcall_func1( void *func, const void *a ); __ASM_STDCALL_FUNC( wrap_fastcall_func1, 8, diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index a092216b824..3094fdbe42d 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1554,9 +1554,9 @@ ULONG WINAPI ExGetSharedWaiterCount(ERESOURCE*); void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST,PALLOCATE_FUNCTION,PFREE_FUNCTION,ULONG,SIZE_T,ULONG,USHORT); void WINAPI ExInitializePagedLookasideList(PPAGED_LOOKASIDE_LIST,PALLOCATE_FUNCTION,PFREE_FUNCTION,ULONG,SIZE_T,ULONG,USHORT); NTSTATUS WINAPI ExInitializeResourceLite(ERESOURCE*); -PSLIST_ENTRY WINAPI ExInterlockedFlushSList(PSLIST_HEADER); -PSLIST_ENTRY WINAPI ExInterlockedPopEntrySList(PSLIST_HEADER,PKSPIN_LOCK); -PSLIST_ENTRY WINAPI ExInterlockedPushEntrySList(PSLIST_HEADER,PSLIST_ENTRY,PKSPIN_LOCK); +PSLIST_ENTRY FASTCALL ExInterlockedFlushSList(PSLIST_HEADER); +PSLIST_ENTRY FASTCALL ExInterlockedPopEntrySList(PSLIST_HEADER,PKSPIN_LOCK); +PSLIST_ENTRY FASTCALL ExInterlockedPushEntrySList(PSLIST_HEADER,PSLIST_ENTRY,PKSPIN_LOCK); LIST_ENTRY * WINAPI ExInterlockedRemoveHeadList(LIST_ENTRY*,KSPIN_LOCK*); BOOLEAN WINAPI ExIsResourceAcquiredExclusiveLite(ERESOURCE*); ULONG WINAPI ExIsResourceAcquiredSharedLite(ERESOURCE*); diff --git a/include/windef.h b/include/windef.h index 0074d5cf6c4..b52f5eb836c 100644 --- a/include/windef.h +++ b/include/windef.h @@ -101,10 +101,22 @@ extern "C" { #endif /* __cdecl */
#ifndef __fastcall -# ifndef _MSC_VER +# ifdef __i386__ +# ifdef __GNUC__ +# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) || defined(__APPLE__) +# define __fastcall __attribute__((__fastcall__)) __attribute__((__force_align_arg_pointer__)) +# elif (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4)) +# define __fastcall __attribute__((__fastcall__)) +# else +# define __fastcall __stdcall +# endif +# elif !defined(_MSC_VER) +# define __fastcall __stdcall +# endif +# else # define __fastcall __stdcall # endif -#endif +#endif /* __fastcall */
#ifndef __thiscall # define __thiscall __stdcall @@ -150,10 +162,7 @@ extern "C" { #define _stdcall __ONLY_IN_WINELIB(__stdcall) #endif #ifndef _fastcall -#define _fastcall __ONLY_IN_WINELIB(__stdcall) -#endif -#ifndef __fastcall -#define __fastcall __ONLY_IN_WINELIB(__stdcall) +#define _fastcall __ONLY_IN_WINELIB(__fastcall) #endif #ifndef __export #define __export __ONLY_IN_WINELIB(__stdcall) diff --git a/include/wine/asm.h b/include/wine/asm.h index 8c664476ef1..c45d84c7307 100644 --- a/include/wine/asm.h +++ b/include/wine/asm.h @@ -29,8 +29,10 @@
#if defined(_WIN32) && defined(__i386__) # define __ASM_STDCALL(name,args) __ASM_NAME(name) "@" #args +# define __ASM_FASTCALL(name, args) "@" name "@" #args #else # define __ASM_STDCALL(name,args) __ASM_NAME(name) +# define __ASM_FASTCALL(name, args) __ASM_NAME(name) #endif
#if defined(__GCC_HAVE_DWARF2_CFI_ASM) || defined(__APPLE__) @@ -56,22 +58,22 @@ #endif
#ifdef __GNUC__ -# define __ASM_DEFINE_FUNC(name,code) \ - asm(".text\n\t.align 4\n\t.globl " name "\n\t" __ASM_FUNC_TYPE(name) __ASM_SEH("\n\t.seh_proc " name) "\n" name ":\n\t" \ - __ASM_CFI(".cfi_startproc\n\t") code __ASM_CFI("\n\t.cfi_endproc") __ASM_SEH("\n\t.seh_endproc") ); +# define __ASM_GLOBAL(code) asm(code); #else -# define __ASM_DEFINE_FUNC(name,code) void __asm_dummy_##__LINE__(void) { \ - asm(".text\n\t.align 4\n\t.globl " name "\n\t" __ASM_FUNC_TYPE(name) __ASM_SEH("\n\t.seh_proc " name) "\n" name ":\n\t" \ - __ASM_CFI(".cfi_startproc\n\t") code __ASM_CFI("\n\t.cfi_endproc") __ASM_SEH("\n\t.seh_endproc") ); } +# define __ASM_GLOBAL(code) void __asm_dummy_##__LINE__(void) { asm(code); } #endif
+#define __ASM_DEFINE_FUNC(name,code) \ + __ASM_GLOBAL( ".text\n\t.align 4\n\t.globl " name "\n\t" __ASM_FUNC_TYPE(name) __ASM_SEH("\n\t.seh_proc " name) "\n" name ":\n\t" \ + __ASM_CFI(".cfi_startproc\n\t") code __ASM_CFI("\n\t.cfi_endproc") __ASM_SEH("\n\t.seh_endproc") ); + #define __ASM_GLOBAL_FUNC(name,code) __ASM_DEFINE_FUNC(__ASM_NAME(#name),code)
#define __ASM_STDCALL_FUNC(name,args,code) __ASM_DEFINE_FUNC(__ASM_STDCALL(#name,args),code)
/* fastcall support */
-#if defined(__i386__) && !defined(_WIN32) +#if defined(__i386__) && !defined(_WIN32) && ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4)))
# define DEFINE_FASTCALL1_WRAPPER(func) \ __ASM_STDCALL_FUNC( __fastcall_ ## func, 4, \ @@ -87,6 +89,16 @@ "pushl %eax\n\t" \ "jmp " __ASM_STDCALL(#func,args) )
+#elif defined(__i386__) && !defined(_WIN32) + +/* winebuild still uses the thunk names, so provide them */ +# define DEFINE_FASTCALL1_WRAPPER(func) \ + __ASM_GLOBAL( ".globl " __ASM_STDCALL("__fastcall_" #func, 4) "\n\t" \ + __ASM_STDCALL("__fastcall_" #func, 4) " = " __ASM_FASTCALL(#func, 4) "\n\t" ); +# define DEFINE_FASTCALL_WRAPPER(func,args) \ + __ASM_GLOBAL( ".globl " __ASM_STDCALL("__fastcall_" #func, args) "\n\t" \ + __ASM_STDCALL("__fastcall_" #func, args) " = " __ASM_FASTCALL(#func, args) "\n\t" ); + #else /* __i386__ */
# define DEFINE_FASTCALL1_WRAPPER(func) /* nothing */
Signed-off-by: Chip Davis cdavis@codeweavers.com --- dlls/mshtml/htmlevent.c | 11 +++++++++++ dlls/mshtml/nsembed.c | 10 ++++++++++ dlls/ole32/stg_prop.c | 14 +++++++++++++- dlls/riched20/editor.h | 2 +- dlls/riched20/editstr.h | 6 +++++- dlls/riched20/txthost.c | 8 ++++---- dlls/riched20/txtsrv.c | 12 ++++++------ include/windef.h | 22 ++++++++++++++++++++-- include/wine/asm.h | 26 +++++++++++++++++++------- 9 files changed, 89 insertions(+), 22 deletions(-)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 4cf994587fc..a4fb47ba25e 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -1024,12 +1024,23 @@ static HRESULT WINAPI DOMEvent_get_type(IDOMEvent *iface, BSTR *p) }
#ifdef __i386__ + +#if defined(__MINGW32__) || (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || __has_attribute(thiscall) + +#define nsIDOMEvent_InitEvent(_this,type,bubbles,cancelable) \ + ((void (__thiscall*)(nsIDOMEvent*,const nsAString*,cpp_bool,cpp_bool)) \ + (_this)->lpVtbl->InitEvent)(_this,type,bubbles,cancelable) + +#else + #define nsIDOMEvent_InitEvent(_this,type,bubbles,cancelable) \ ((void (WINAPI*)(void*,nsIDOMEvent*,const nsAString*,cpp_bool,cpp_bool)) \ &call_thiscall_func)((_this)->lpVtbl->InitEvent,_this,type,bubbles,cancelable)
#endif
+#endif + static HRESULT WINAPI DOMEvent_initEvent(IDOMEvent *iface, BSTR type, VARIANT_BOOL can_bubble, VARIANT_BOOL cancelable) { DOMEvent *This = impl_from_IDOMEvent(iface); diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c index 244341248ed..af66861ad48 100644 --- a/dlls/mshtml/nsembed.c +++ b/dlls/mshtml/nsembed.c @@ -2343,6 +2343,13 @@ void detach_gecko_browser(GeckoBrowser *This) * This will be removed after the next Gecko update, that will change calling convention on Gecko side. */ #ifdef __i386__ + +#if defined(__MINGW32__) || (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || __has_attribute(thiscall) + +#define nsIScriptObjectPrincipal_GetPrincipal(this) ((void* (__thiscall*)(void*))(this)->lpVtbl->GetPrincipal)(this) + +#else + __ASM_GLOBAL_FUNC(call_thiscall_func, "popl %eax\n\t" "popl %edx\n\t" @@ -2350,6 +2357,9 @@ __ASM_GLOBAL_FUNC(call_thiscall_func, "pushl %eax\n\t" "jmp *%edx\n\t") #define nsIScriptObjectPrincipal_GetPrincipal(this) ((void* (WINAPI*)(void*,void*))&call_thiscall_func)((this)->lpVtbl->GetPrincipal,this) + +#endif + #endif
nsIXMLHttpRequest *create_nsxhr(nsIDOMWindow *nswindow) diff --git a/dlls/ole32/stg_prop.c b/dlls/ole32/stg_prop.c index 708147e51dc..0ee38d11abd 100644 --- a/dlls/ole32/stg_prop.c +++ b/dlls/ole32/stg_prop.c @@ -2896,7 +2896,17 @@ end: return hr; }
-#ifdef __i386__ /* thiscall functions are i386-specific */ +#if defined(__i386__) /* thiscall functions are i386-specific */ + +#if defined(__MINGW32__) || (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || __has_attribute(thiscall) + +static void* __thiscall Allocate_PMemoryAllocator(void *this, ULONG cbSize) +{ + void* (__thiscall *fn)(void*,ULONG) = **(void***)this; + return fn(this, cbSize); +} + +#else
#define DEFINE_STDCALL_WRAPPER(num,func,args) \ __ASM_STDCALL_FUNC(func, args, \ @@ -2909,6 +2919,8 @@ end: DEFINE_STDCALL_WRAPPER(0,Allocate_PMemoryAllocator,8) extern void* WINAPI Allocate_PMemoryAllocator(void *this, ULONG cbSize);
+#endif + #else
static void* WINAPI Allocate_PMemoryAllocator(void *this, ULONG cbSize) diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 1f033b4187c..e49d96e864f 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -276,7 +276,7 @@ void ME_InitTableDef(ME_TextEditor *editor, struct RTFTable *tableDef) DECLSPEC_
/* txthost.c */ ITextHost *ME_CreateTextHost(HWND hwnd, CREATESTRUCTW *cs, BOOL bEmulateVersion10) DECLSPEC_HIDDEN; -#if defined(__i386__) && !defined(__MINGW32__) /* Use wrappers to perform thiscall on i386 */ +#if defined(__i386__) && !defined(HAVE_THISCALL) /* Use wrappers to perform thiscall on i386 */ #define TXTHOST_VTABLE(This) (&itextHostStdcallVtbl) #else /* __i386__ */ #define TXTHOST_VTABLE(This) (This)->lpVtbl diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index a2e6f8584b7..df39d8143d4 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -51,7 +51,11 @@ #include "wine/heap.h" #include "wine/list.h"
-#if defined(__i386__) && !defined(__MINGW32__) +#if defined(__MINGW32__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __has_attribute(thiscall) +# define HAVE_THISCALL +#endif + +#if defined(__i386__) && !defined(HAVE_THISCALL) extern const struct ITextHostVtbl itextHostStdcallVtbl DECLSPEC_HIDDEN; #endif /* __i386__ */
diff --git a/dlls/riched20/txthost.c b/dlls/riched20/txthost.c index 3f25625ed52..cffa8efa1a3 100644 --- a/dlls/riched20/txthost.c +++ b/dlls/riched20/txthost.c @@ -69,7 +69,7 @@ static inline ITextHostImpl *impl_from_ITextHost(ITextHost *iface) return CONTAINING_RECORD(iface, ITextHostImpl, ITextHost_iface); }
-static HRESULT WINAPI ITextHostImpl_QueryInterface(ITextHost *iface, REFIID riid, void **ppvObject) +static HRESULT STDMETHODCALLTYPE ITextHostImpl_QueryInterface(ITextHost *iface, REFIID riid, void **ppvObject) { ITextHostImpl *This = impl_from_ITextHost(iface);
@@ -83,14 +83,14 @@ static HRESULT WINAPI ITextHostImpl_QueryInterface(ITextHost *iface, REFIID riid return E_NOINTERFACE; }
-static ULONG WINAPI ITextHostImpl_AddRef(ITextHost *iface) +static ULONG STDMETHODCALLTYPE ITextHostImpl_AddRef(ITextHost *iface) { ITextHostImpl *This = impl_from_ITextHost(iface); ULONG ref = InterlockedIncrement(&This->ref); return ref; }
-static ULONG WINAPI ITextHostImpl_Release(ITextHost *iface) +static ULONG STDMETHODCALLTYPE ITextHostImpl_Release(ITextHost *iface) { ITextHostImpl *This = impl_from_ITextHost(iface); ULONG ref = InterlockedDecrement(&This->ref); @@ -522,7 +522,7 @@ DECLSPEC_HIDDEN HRESULT __thiscall ITextHostImpl_TxGetSelectionBarWidth(ITextHos }
-#if defined(__i386__) && !defined(__MINGW32__) /* thiscall functions are i386-specific */ +#if defined(__i386__) && !defined(HAVE_THISCALL) /* thiscall functions are i386-specific */
#define STDCALL(func) (void *) __stdcall_ ## func #ifdef _MSC_VER diff --git a/dlls/riched20/txtsrv.c b/dlls/riched20/txtsrv.c index 12761621c4c..8ded7b8b5a7 100644 --- a/dlls/riched20/txtsrv.c +++ b/dlls/riched20/txtsrv.c @@ -49,7 +49,7 @@ static inline ITextServicesImpl *impl_from_IUnknown(IUnknown *iface) return CONTAINING_RECORD(iface, ITextServicesImpl, IUnknown_inner); }
-static HRESULT WINAPI ITextServicesImpl_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +static HRESULT STDMETHODCALLTYPE ITextServicesImpl_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) { ITextServicesImpl *This = impl_from_IUnknown(iface);
@@ -75,7 +75,7 @@ static HRESULT WINAPI ITextServicesImpl_QueryInterface(IUnknown *iface, REFIID r return S_OK; }
-static ULONG WINAPI ITextServicesImpl_AddRef(IUnknown *iface) +static ULONG STDMETHODCALLTYPE ITextServicesImpl_AddRef(IUnknown *iface) { ITextServicesImpl *This = impl_from_IUnknown(iface); LONG ref = InterlockedIncrement(&This->ref); @@ -85,7 +85,7 @@ static ULONG WINAPI ITextServicesImpl_AddRef(IUnknown *iface) return ref; }
-static ULONG WINAPI ITextServicesImpl_Release(IUnknown *iface) +static ULONG STDMETHODCALLTYPE ITextServicesImpl_Release(IUnknown *iface) { ITextServicesImpl *This = impl_from_IUnknown(iface); LONG ref = InterlockedDecrement(&This->ref); @@ -114,19 +114,19 @@ static inline ITextServicesImpl *impl_from_ITextServices(ITextServices *iface) return CONTAINING_RECORD(iface, ITextServicesImpl, ITextServices_iface); }
-static HRESULT WINAPI fnTextSrv_QueryInterface(ITextServices *iface, REFIID riid, void **ppv) +static HRESULT STDMETHODCALLTYPE fnTextSrv_QueryInterface(ITextServices *iface, REFIID riid, void **ppv) { ITextServicesImpl *This = impl_from_ITextServices(iface); return IUnknown_QueryInterface(This->outer_unk, riid, ppv); }
-static ULONG WINAPI fnTextSrv_AddRef(ITextServices *iface) +static ULONG STDMETHODCALLTYPE fnTextSrv_AddRef(ITextServices *iface) { ITextServicesImpl *This = impl_from_ITextServices(iface); return IUnknown_AddRef(This->outer_unk); }
-static ULONG WINAPI fnTextSrv_Release(ITextServices *iface) +static ULONG STDMETHODCALLTYPE fnTextSrv_Release(ITextServices *iface) { ITextServicesImpl *This = impl_from_ITextServices(iface); return IUnknown_Release(This->outer_unk); diff --git a/include/windef.h b/include/windef.h index b52f5eb836c..8169bd112f3 100644 --- a/include/windef.h +++ b/include/windef.h @@ -119,8 +119,26 @@ extern "C" { #endif /* __fastcall */
#ifndef __thiscall -# define __thiscall __stdcall -#endif +# ifdef __i386__ +# ifdef __GNUC__ +# if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +# define __thiscall __attribute__((__thiscall__, __force_align_arg_pointer__)) +# elif defined(__has_attribute) +# if __has_attribute(thiscall) +# define __thiscall __attribute__((__thiscall__, __force_align_arg_pointer__)) +# else +# define __thiscall __stdcall +# endif +# else +# define __thiscall __stdcall +# endif +# else +# define __thiscall __stdcall +# endif +# else +# define __thiscall __stdcall +# endif +#endif /* __thiscall */
#ifndef __ms_va_list # if (defined(__x86_64__) || defined(__aarch64__)) && defined (__GNUC__) diff --git a/include/wine/asm.h b/include/wine/asm.h index c45d84c7307..e71cb959acc 100644 --- a/include/wine/asm.h +++ b/include/wine/asm.h @@ -110,7 +110,18 @@
#if defined(__i386__) && !defined(__MINGW32__)
-# ifdef _MSC_VER +# ifndef __has_attribute +# define __has_attribute(a) 0 +# endif + +# if __has_attribute(thiscall) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +/* winebuild still uses the thunk names */ +# define DEFINE_THISCALL_WRAPPER(func,args) \ + __ASM_GLOBAL( ".globl " __ASM_STDCALL("__thiscall_" #func, args) "\n\t" \ + __ASM_STDCALL("__thiscall_" #func, args) " = " __ASM_NAME(#func) "\n\t" ); +# define THISCALL(func) func +# define THISCALL_NAME(func) __ASM_NAME(#func) +# elif defined(_MSC_VER) # define DEFINE_THISCALL_WRAPPER(func,args) \ __declspec(naked) void __thiscall_##func(void) \ { __asm { \ @@ -119,19 +130,20 @@ push eax \ jmp func \ } } +# define THISCALL(func) (void *)__thiscall_ ## func +# define THISCALL_NAME(func) __ASM_NAME("__thiscall_" #func) # else /* _MSC_VER */ # define DEFINE_THISCALL_WRAPPER(func,args) \ extern void __thiscall_ ## func(void); \ __ASM_STDCALL_FUNC( __thiscall_ ## func, args, \ - "popl %eax\n\t" \ - "pushl %ecx\n\t" \ - "pushl %eax\n\t" \ + "popl %eax\n\t" \ + "pushl %ecx\n\t" \ + "pushl %eax\n\t" \ "jmp " __ASM_STDCALL(#func,args) ) +# define THISCALL(func) (void *)__thiscall_ ## func +# define THISCALL_NAME(func) __ASM_NAME("__thiscall_" #func) # endif /* _MSC_VER */
-# define THISCALL(func) (void *)__thiscall_ ## func -# define THISCALL_NAME(func) __ASM_NAME("__thiscall_" #func) - #else /* __i386__ */
# define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=60775
Your paranoid android.
=== debian10 (32 bit report) ===
mshtml: htmllocation.c:346: Test failed: FILE: IPersistMoniker_Load failed: 0x800c0005
ole32: clipboard.c:1049: Test failed: OleIsCurrentClipboard returned 0 clipboard.c:1117: Test failed: 1 WM_DRAWCLIPBOARD received
=== debian10 (32 bit Chinese:China report) ===
mshtml: htmllocation.c:346: Test failed: FILE: IPersistMoniker_Load failed: 0x800c0005
=== debian10 (32 bit WoW report) ===
mshtml: htmllocation.c:346: Test failed: FILE: IPersistMoniker_Load failed: 0x800c0005
=== debian10 (64 bit WoW report) ===
mshtml: htmllocation.c:346: Test failed: FILE: IPersistMoniker_Load failed: 0x800c0005