From c2a6859012d928b67a83619bd5087674a96b9254 Mon Sep 17 00:00:00 2001 From: Paul Monson Date: Wed, 7 Aug 2019 11:57:45 -0700 Subject: [PATCH] fix mingw build and crashing bugs for Python Windows ARM64 (#496) * fix mingw build and crashing bugs for Python Windows ARM64 * Fix issues found in PR review --- .appveyor.yml | 7 +++++++ Makefile.am | 1 + configure.host | 8 ++++++++ msvc_build/aarch64/aarch64_include/ffi.h | 3 +-- msvcc.sh | 11 +++++++++++ src/aarch64/ffi.c | 12 +++++++++--- src/aarch64/ffitarget.h | 4 ++++ src/aarch64/win64_armasm.S | 18 ++++++++++-------- src/prep_cif.c | 4 ++-- 9 files changed, 53 insertions(+), 15 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 1c7fe9bb8..7a97c2aa5 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -13,6 +13,7 @@ platform: - x64 - x86 - arm + - arm64 environment: global: @@ -30,6 +31,12 @@ install: $env:HOST="i686-pc-cygwin" $env:MSVCC="/cygdrive/c/projects/libffi/msvcc.sh" $env:SRC_ARCHITECTURE="x86" + } ElseIf ($env:Platform -Match "arm64") { + $env:VCVARS_PLATFORM="x86_arm64" + $env:BUILD="i686-pc-cygwin" + $env:HOST="aarch64-w64-cygwin" + $env:MSVCC="/cygdrive/c/projects/libffi/msvcc.sh -marm64" + $env:SRC_ARCHITECTURE="aarch64" } ElseIf ($env:Platform -Match "arm") { $env:VCVARS_PLATFORM="x86_arm" $env:BUILD="i686-pc-cygwin" diff --git a/Makefile.am b/Makefile.am index b74b73bbb..07d928e31 100644 --- a/Makefile.am +++ b/Makefile.am @@ -79,6 +79,7 @@ noinst_HEADERS = \ EXTRA_libffi_la_SOURCES = \ src/aarch64/ffi.c src/aarch64/sysv.S \ + src/aarch64/win64_armasm.S \ src/alpha/ffi.c src/alpha/osf.S \ src/arc/ffi.c src/arc/arcompact.S \ src/arm/ffi.c src/arm/sysv.S \ diff --git a/configure.host b/configure.host index 8181a6118..6762eba0e 100644 --- a/configure.host +++ b/configure.host @@ -6,6 +6,11 @@ # THIS TABLE IS SORTED. KEEP IT THAT WAY. # Most of the time we can define all the variables all at once... case "${host}" in + aarch64*-*-cygwin* | aarch64*-*-mingw* | aarch64*-*-win* ) + TARGET=ARM_WIN64; TARGETDIR=aarch64 + MSVC=1 + ;; + aarch64*-*-*) TARGET=AARCH64; TARGETDIR=aarch64 SOURCES="ffi.c sysv.S" @@ -250,6 +255,9 @@ case "${TARGET}" in ARM_WIN32) SOURCES="ffi.c sysv_msvc_arm32.S" ;; + ARM_WIN64) + SOURCES="ffi.c win64_armasm.S" + ;; MIPS) SOURCES="ffi.c o32.S n32.S" ;; diff --git a/msvc_build/aarch64/aarch64_include/ffi.h b/msvc_build/aarch64/aarch64_include/ffi.h index 3adb5cb90..02f26a2f0 100644 --- a/msvc_build/aarch64/aarch64_include/ffi.h +++ b/msvc_build/aarch64/aarch64_include/ffi.h @@ -197,7 +197,7 @@ FFI_EXTERN ffi_type ffi_type_float; FFI_EXTERN ffi_type ffi_type_double; FFI_EXTERN ffi_type ffi_type_pointer; -#ifndef _M_ARM64 +#ifndef _M_ARM64 FFI_EXTERN ffi_type ffi_type_longdouble; #else #define ffi_type_longdouble ffi_type_double @@ -227,7 +227,6 @@ typedef struct { ffi_type *rtype; unsigned bytes; unsigned flags; - unsigned isVariadic; #ifdef FFI_EXTRA_CIF_FIELDS FFI_EXTRA_CIF_FIELDS; #endif diff --git a/msvcc.sh b/msvcc.sh index 9c52f527c..97facd698 100755 --- a/msvcc.sh +++ b/msvcc.sh @@ -85,6 +85,11 @@ do safeseh= shift 1 ;; + -marm64) + ml='armasm64' + safeseh= + shift 1 + ;; -clang-cl) cl="clang-cl" shift 1 @@ -299,6 +304,10 @@ if [ -n "$assembly" ]; then defines="$defines -D_M_ARM" fi + if [ $ml = "armasm64" ]; then + defines="$defines -D_M_ARM64" + fi + if test -n "$verbose"; then echo "$cl -nologo -EP $includes $defines $src > $ppsrc" fi @@ -307,6 +316,8 @@ if [ -n "$assembly" ]; then output="$(echo $output | sed 's%/F[dpa][^ ]*%%g')" if [ $ml = "armasm" ]; then args="-nologo -g -oldit $armasm_output $ppsrc -errorReport:prompt" + elif [ $ml = "armasm64" ]; then + args="-nologo -g $armasm_output $ppsrc -errorReport:prompt" else args="-nologo $safeseh $single $output $ppsrc" fi diff --git a/src/aarch64/ffi.c b/src/aarch64/ffi.c index 4225f725e..1ebf43c19 100644 --- a/src/aarch64/ffi.c +++ b/src/aarch64/ffi.c @@ -666,7 +666,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue, { int elems = 4 - (h & 3); #ifdef _M_ARM64 /* for handling armasm calling convention */ - if (cif->isVariadic) + if (cif->is_variadic) { if (state.ngrn + elems <= N_X_ARG_REG) { @@ -808,7 +808,13 @@ 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 + // Not using dlmalloc.c for Windows ARM64 builds + // so calling ffi_data_to_code_pointer() isn't necessary + unsigned char *tramp_code = tramp; + #else unsigned char *tramp_code = ffi_data_to_code_pointer (tramp); + #endif ffi_clear_cache (tramp_code, tramp_code + FFI_TRAMPOLINE_SIZE); #endif @@ -909,7 +915,7 @@ ffi_closure_SYSV_inner (ffi_cif *cif, { n = 4 - (h & 3); #ifdef _M_ARM64 /* for handling armasm calling convention */ - if (cif->isVariadic) + if (cif->is_variadic) { if (state.ngrn + n <= N_X_ARG_REG) { @@ -948,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 _M_ARM64 /* for handling armasm calling convention */ } #endif /* for handling armasm calling convention */ } diff --git a/src/aarch64/ffitarget.h b/src/aarch64/ffitarget.h index 32c4f084c..ecb6d2dea 100644 --- a/src/aarch64/ffitarget.h +++ b/src/aarch64/ffitarget.h @@ -69,6 +69,10 @@ typedef enum ffi_abi #define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE #endif +#ifdef _M_ARM64 +#define FFI_EXTRA_CIF_FIELDS unsigned is_variadic +#endif + /* ---- Internal ---- */ #if defined (__APPLE__) diff --git a/src/aarch64/win64_armasm.S b/src/aarch64/win64_armasm.S index 906ceffb4..8ebc44423 100644 --- a/src/aarch64/win64_armasm.S +++ b/src/aarch64/win64_armasm.S @@ -57,12 +57,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ x5 closure */ - NESTED_ENTRY ffi_call_SYSV - /* Use a stack frame allocated by our caller. */ - PROLOG_NOP stp x29, x30, [x1, #32] - /* For unwind information, Windows has to store fp and lr */ + NESTED_ENTRY ffi_call_SYSV_fake + + /* For unwind information, Windows has to store fp and lr */ PROLOG_SAVE_REG_PAIR x29, x30, #-32! - + + ALTERNATE_ENTRY ffi_call_SYSV + /* Use a stack frame allocated by our caller. */ + stp x29, x30, [x1] mov x29, x1 mov sp, x0 @@ -97,8 +99,8 @@ ffi_call_SYSV_L1 /* Partially deconstruct the stack frame. */ mov sp, x29 - ldp x29, x30, [x29, #32] - + ldp x29, x30, [x29] + /* Save the return value as directed. */ adr x5, ffi_call_SYSV_return and w4, w4, #AARCH64_RET_MASK @@ -177,7 +179,7 @@ ffi_call_SYSV_return nop - NESTED_END ffi_call_SYSV + NESTED_END ffi_call_SYSV_fake /* ffi_closure_SYSV diff --git a/src/prep_cif.c b/src/prep_cif.c index 406e4b61c..06c654403 100644 --- a/src/prep_cif.c +++ b/src/prep_cif.c @@ -129,8 +129,8 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, cif->rtype = rtype; cif->flags = 0; - #ifdef _M_ARM64 - cif->isVariadic = isvariadic; +#ifdef _M_ARM64 + cif->is_variadic = isvariadic; #endif #if HAVE_LONG_DOUBLE_VARIANT ffi_prep_types (abi);