From 955a5b73059d27eba7db0783bb4769934d8c8a82 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin@martin.st>
Date: Sun, 26 Apr 2020 04:58:33 +0300
Subject: [PATCH] Fix building for aarch64 windows with mingw toolchains (#555)

* aarch64: Check _WIN32 instead of _M_ARM64 for detecting windows

This fixes building for aarch64 with mingw toolchains. _M_ARM64 is
predefined by MSVC, while mingw compilers predefine __aarch64__.

In aarch64 specific code, change checks for _M_ARM64 into checks for
_WIN32.

In arch independent code, check for
(defined(_M_ARM64) || defined(__aarch64__)) && defined(_WIN32)
instead of just _M_ARM64.

In src/closures.c, coalesce checks like
defined(X86_WIN32) || defined(X86_WIN64) || defined(_M_ARM64)
into plain defined(_WIN32). Technically, this enables code for
ARM32 windows where it wasn't, but as far as I can see it, those
codepaths should be fine for that architecture variant as well.

* aarch64: Only use armasm source when building with MSVC

When building for windows/arm64 with clang, the normal gas style .S
source works fine. sysv.S and win64_armasm.S seem to be functionally
equivalent, with only differences being due to assembler syntax.
---
 configure.host          | 10 ++++++++--
 src/aarch64/ffi.c       | 14 +++++++-------
 src/aarch64/ffitarget.h |  8 ++++----
 src/closures.c          | 12 ++++++------
 src/prep_cif.c          |  2 +-
 5 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/configure.host b/configure.host
index 9a72cda..947e73b 100644
--- a/configure.host
+++ b/configure.host
@@ -8,7 +8,9 @@
 case "${host}" in
   aarch64*-*-cygwin* | aarch64*-*-mingw* | aarch64*-*-win* )
 	TARGET=ARM_WIN64; TARGETDIR=aarch64
-	MSVC=1
+	if test "${ax_cv_c_compiler_vendor}" = "microsoft"; then
+	  MSVC=1
+	fi
 	;;
 
   aarch64*-*-*)
@@ -256,7 +258,11 @@ case "${TARGET}" in
 	SOURCES="ffi.c sysv_msvc_arm32.S"
 	;;
   ARM_WIN64)
-	SOURCES="ffi.c win64_armasm.S"
+	if test "$MSVC" = 1; then
+		SOURCES="ffi.c win64_armasm.S"
+	else
+		SOURCES="ffi.c sysv.S"
+	fi
 	;;
   MIPS)
 	SOURCES="ffi.c o32.S n32.S"
diff --git a/src/aarch64/ffi.c b/src/aarch64/ffi.c
index 1ebf43c..2906c20 100644
--- a/src/aarch64/ffi.c
+++ b/src/aarch64/ffi.c
@@ -27,7 +27,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include <ffi.h>
 #include <ffi_common.h>
 #include "internal.h"
-#ifdef _M_ARM64
+#ifdef _WIN32
 #include <windows.h> /* FlushInstructionCache */
 #endif
 
@@ -78,7 +78,7 @@ ffi_clear_cache (void *start, void *end)
   sys_icache_invalidate (start, (char *)end - (char *)start);
 #elif defined (__GNUC__)
   __builtin___clear_cache (start, end);
-#elif defined (_M_ARM64)
+#elif defined (_WIN32)
   FlushInstructionCache(GetCurrentProcess(), start, (char*)end - (char*)start);
 #else
 #error "Missing builtin to flush instruction cache"
@@ -665,7 +665,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
 	    if (h)
 	      {
 		int elems = 4 - (h & 3);
-#ifdef _M_ARM64 /* for handling armasm calling convention */
+#ifdef _WIN32 /* for handling armasm calling convention */
                 if (cif->is_variadic)
                   {
                     if (state.ngrn + elems <= N_X_ARG_REG)
@@ -690,7 +690,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
 		  }
 		state.nsrn = N_V_ARG_REG;
 		dest = allocate_to_stack (&state, stack, ty->alignment, s);
-#ifdef _M_ARM64 /* for handling armasm calling convention */
+#ifdef _WIN32 /* for handling armasm calling convention */
 	      }
 #endif /* for handling armasm calling convention */
 	      }
@@ -808,7 +808,7 @@ ffi_prep_closure_loc (ffi_closure *closure,
   ffi_clear_cache(tramp, tramp + FFI_TRAMPOLINE_SIZE);
 
   /* Also flush the cache for code mapping.  */
-#ifdef _M_ARM64
+#ifdef _WIN32
   // Not using dlmalloc.c for Windows ARM64 builds
   // so calling ffi_data_to_code_pointer() isn't necessary
   unsigned char *tramp_code = tramp;
@@ -914,7 +914,7 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
 	  if (h)
 	    {
 	      n = 4 - (h & 3);
-#ifdef _M_ARM64  /* for handling armasm calling convention */
+#ifdef _WIN32  /* for handling armasm calling convention */
               if (cif->is_variadic)
                 {
                   if (state.ngrn + n <= N_X_ARG_REG)
@@ -954,7 +954,7 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
                       avalue[i] = allocate_to_stack(&state, stack,
                                                    ty->alignment, s);
                     }
-#ifdef _M_ARM64  /* for handling armasm calling convention */
+#ifdef _WIN32  /* for handling armasm calling convention */
                 }
 #endif  /* for handling armasm calling convention */
             }
diff --git a/src/aarch64/ffitarget.h b/src/aarch64/ffitarget.h
index ecb6d2d..7a8cabe 100644
--- a/src/aarch64/ffitarget.h
+++ b/src/aarch64/ffitarget.h
@@ -32,7 +32,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #define FFI_SIZEOF_JAVA_RAW  4
 typedef unsigned long long ffi_arg;
 typedef signed long long ffi_sarg;
-#elif defined(_M_ARM64)
+#elif defined(_WIN32)
 #define FFI_SIZEOF_ARG 8
 typedef unsigned long long ffi_arg;
 typedef signed long long ffi_sarg;
@@ -69,7 +69,7 @@ typedef enum ffi_abi
 #define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE
 #endif
 
-#ifdef _M_ARM64
+#ifdef _WIN32
 #define FFI_EXTRA_CIF_FIELDS unsigned is_variadic
 #endif
 
@@ -78,13 +78,13 @@ typedef enum ffi_abi
 #if defined (__APPLE__)
 #define FFI_TARGET_SPECIFIC_VARIADIC
 #define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs
-#elif !defined(_M_ARM64)
+#elif !defined(_WIN32)
 /* iOS and Windows reserve x18 for the system.  Disable Go closures until
    a new static chain is chosen.  */
 #define FFI_GO_CLOSURES 1
 #endif
 
-#ifndef _M_ARM64
+#ifndef _WIN32
 /* No complex type on Windows */
 #define FFI_TARGET_HAS_COMPLEX_TYPE
 #endif
diff --git a/src/closures.c b/src/closures.c
index 5120021..12f8268 100644
--- a/src/closures.c
+++ b/src/closures.c
@@ -123,7 +123,7 @@ ffi_closure_free (void *ptr)
 #  define FFI_MMAP_EXEC_WRIT 1
 #  define HAVE_MNTENT 1
 # endif
-# if defined(X86_WIN32) || defined(X86_WIN64) || defined(_M_ARM64) || defined(__OS2__)
+# if defined(_WIN32) || defined(__OS2__)
 /* Windows systems may have Data Execution Protection (DEP) enabled, 
    which requires the use of VirtualMalloc/VirtualFree to alloc/free
    executable memory. */
@@ -386,7 +386,7 @@ ffi_closure_free (void *ptr)
 #endif
 #include <string.h>
 #include <stdio.h>
-#if !defined(X86_WIN32) && !defined(X86_WIN64) && !defined(_M_ARM64)
+#if !defined(_WIN32)
 #ifdef HAVE_MNTENT
 #include <mntent.h>
 #endif /* HAVE_MNTENT */
@@ -512,11 +512,11 @@ static int dlmalloc_trim(size_t) MAYBE_UNUSED;
 static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
 static void dlmalloc_stats(void) MAYBE_UNUSED;
 
-#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(_M_ARM64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
+#if !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
 /* Use these for mmap and munmap within dlmalloc.c.  */
 static void *dlmmap(void *, size_t, int, int, int, off_t);
 static int dlmunmap(void *, size_t);
-#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
+#endif /* !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
 
 #define mmap dlmmap
 #define munmap dlmunmap
@@ -526,7 +526,7 @@ static int dlmunmap(void *, size_t);
 #undef mmap
 #undef munmap
 
-#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(_M_ARM64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
+#if !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
 
 /* A mutex used to synchronize access to *exec* variables in this file.  */
 static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -908,7 +908,7 @@ segment_holding_code (mstate m, char* addr)
 }
 #endif
 
-#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(_M_ARM64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
+#endif /* !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
 
 /* Allocate a chunk of memory with the given size.  Returns a pointer
    to the writable address, and sets *CODE to the executable
diff --git a/src/prep_cif.c b/src/prep_cif.c
index 06c6544..1db3804 100644
--- a/src/prep_cif.c
+++ b/src/prep_cif.c
@@ -129,7 +129,7 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
   cif->rtype = rtype;
 
   cif->flags = 0;
-#ifdef _M_ARM64
+#if (defined(_M_ARM64) || defined(__aarch64__)) && defined(_WIN32)
   cif->is_variadic = isvariadic;
 #endif
 #if HAVE_LONG_DOUBLE_VARIANT
-- 
2.30.0.windows.2

