Windows uses a different ABI for va_list on arm64 just like on x86_64.
On x86_64, the calling convention for windows functions is completely different from the one on other platforms. On arm64, they're mostly the same, with the only exception being variadic functions (where all float arguments are passed in integer registers, since the va_list is a single pointer).
Any functions using __builtin_ms_va_start need to be decorated with __attribute__((ms_abi)).
Add a check in configure for the support of __builtin_ms_va_list (both features appared in clang at the same time, in the 5.0 release).
This fixes running binaries that use e.g. printf style functions (e.g. midl.exe from the windows 10 sdk), fixing https://bugs.winehq.org/show_bug.cgi?id=38886.
Signed-off-by: Martin Storsjo martin@martin.st --- A new enough version of clang is available in the latest stable version of the Android NDK, r17. A new enough version is also available in Xcode 9.3, and there's finally a second stable release of vanilla Clang (6.0.0) that also contains support for this.
This effectively disables building for arm64 with gcc, though, since only clang supports this calling convention.
I guess it would be preferrable to still be able to build it even if the compiler doesn't support the ms_abi attribute and __builtin_ms_va_start (with a loud configure warning saying that it isn't ABI compatible), but as far as I can see, the headers that decide whether to use them or not don't include config.h (and probably aren't allowed to).
Querying it at build time with __has_attribute doesn't work, since this check signals that e.g. the ms_abi attribute is supported, even if building for an architecture where the attribute isn't supported. (It's currently supported on x86_64 and aarch64.) --- configure.ac | 7 +++++++ include/msvcrt/crtdefs.h | 6 +++++- include/windef.h | 6 +++++- include/wine/test.h | 4 ++-- 4 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac index 54c31d8..b4a8ef0 100644 --- a/configure.ac +++ b/configure.ac @@ -205,6 +205,13 @@ case $host in CFLAGS="$CFLAGS -marm -mfloat-abi=$float_abi" AC_SUBST(TARGETFLAGS,"-marm -mfloat-abi=$float_abi") ;; + aarch64*) + AC_MSG_CHECKING([whether $CC supports __builtin_ms_va_list]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdarg.h>]], [[void func(__builtin_ms_va_list *args);]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([You need clang >= 5.0 to build Wine for arm64.])]) + ;; i[[3456789]]86*) enable_win16=${enable_win16:-yes} ;; diff --git a/include/msvcrt/crtdefs.h b/include/msvcrt/crtdefs.h index a9edef5..0c0b087 100644 --- a/include/msvcrt/crtdefs.h +++ b/include/msvcrt/crtdefs.h @@ -62,6 +62,8 @@ # endif # elif defined(__arm__) && defined (__GNUC__) && !defined(__SOFTFP__) # define __stdcall __attribute__((pcs("aapcs-vfp"))) +# elif defined(__aarch64__) && defined (__GNUC__) +# define __stdcall __attribute__((ms_abi)) # else /* __i386__ */ # define __stdcall # endif /* __i386__ */ @@ -82,13 +84,15 @@ # endif # elif defined(__arm__) && defined (__GNUC__) && !defined(__SOFTFP__) # define __cdecl __attribute__((pcs("aapcs-vfp"))) +# elif defined(__aarch64__) && defined (__GNUC__) +# define __cdecl __attribute__((ms_abi)) # elif !defined(_MSC_VER) # define __cdecl # endif #endif /* __cdecl */
#ifndef __ms_va_list -# if defined(__x86_64__) && defined (__GNUC__) +# if (defined(__x86_64__) || defined(__aarch64__)) && defined (__GNUC__) # define __ms_va_list __builtin_ms_va_list # define __ms_va_start(list,arg) __builtin_ms_va_start(list,arg) # define __ms_va_end(list) __builtin_ms_va_end(list) diff --git a/include/windef.h b/include/windef.h index 40028f3..8e8a08a 100644 --- a/include/windef.h +++ b/include/windef.h @@ -71,6 +71,8 @@ extern "C" { # endif # elif defined(__arm__) && defined (__GNUC__) && !defined(__SOFTFP__) # define __stdcall __attribute__((pcs("aapcs-vfp"))) +# elif defined(__aarch64__) && defined (__GNUC__) +# define __stdcall __attribute__((ms_abi)) # else /* __i386__ */ # define __stdcall # endif /* __i386__ */ @@ -91,13 +93,15 @@ extern "C" { # endif # elif defined(__arm__) && defined (__GNUC__) && !defined(__SOFTFP__) # define __cdecl __attribute__((pcs("aapcs-vfp"))) +# elif defined(__aarch64__) && defined (__GNUC__) +# define __cdecl __attribute__((ms_abi)) # elif !defined(_MSC_VER) # define __cdecl # endif #endif /* __cdecl */
#ifndef __ms_va_list -# if defined(__x86_64__) && defined (__GNUC__) +# if (defined(__x86_64__) || defined(__aarch64__)) && defined (__GNUC__) # define __ms_va_list __builtin_ms_va_list # define __ms_va_start(list,arg) __builtin_ms_va_start(list,arg) # define __ms_va_end(list) __builtin_ms_va_end(list) diff --git a/include/wine/test.h b/include/wine/test.h index 21e2ac7..e3e4bcf 100644 --- a/include/wine/test.h +++ b/include/wine/test.h @@ -90,7 +90,7 @@ static inline int winetest_strcmpW( const WCHAR *str1, const WCHAR *str2 ) #define START_TEST(name) void func_##name(void) #endif
-#if defined(__x86_64__) && defined(__GNUC__) && defined(__WINE_USE_MSVCRT) +#if (defined(__x86_64__) || defined(__aarch64__)) && defined(__GNUC__) && defined(__WINE_USE_MSVCRT) #define __winetest_cdecl __cdecl #define __winetest_va_list __builtin_ms_va_list #else @@ -181,7 +181,7 @@ extern void __winetest_cdecl winetest_trace( const char *msg, ... ) WINETEST_PRI #include <stdio.h> #include <excpt.h>
-#if defined(__x86_64__) && defined(__GNUC__) && defined(__WINE_USE_MSVCRT) +#if (defined(__x86_64__) || defined(__aarch64__)) && defined(__GNUC__) && defined(__WINE_USE_MSVCRT) # define __winetest_va_start(list,arg) __builtin_ms_va_start(list,arg) # define __winetest_va_end(list) __builtin_ms_va_end(list) #else