From a8efc2f7897b439fdf2144329d35fea820498dc7 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Sat, 26 Oct 2019 14:57:05 +0200 Subject: [PATCH] Fix FFI_STDCALL ABI (#514) Even for a stdcall function, the stack alignment is still the responsibility of the caller. Remember the original, not stack-aligned argument size, but align when setting up a stack frame. In ffi_closure_inner, return the true argument size, so that ffi_[go_]closure_STDCALL doesn't adjust too much. --- src/x86/ffi.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/x86/ffi.c b/src/x86/ffi.c index 883cc4a..9a59218 100644 --- a/src/x86/ffi.c +++ b/src/x86/ffi.c @@ -51,6 +51,13 @@ # define __declspec(x) __attribute__((x)) #endif +#if defined(_MSC_VER) && defined(_M_IX86) +/* Stack is not 16-byte aligned on Windows. */ +#define STACK_ALIGN(bytes) (bytes) +#else +#define STACK_ALIGN(bytes) FFI_ALIGN (bytes, 16) +#endif + /* Perform machine dependent cif processing. */ ffi_status FFI_HIDDEN ffi_prep_cif_machdep(ffi_cif *cif) @@ -177,12 +184,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) bytes = FFI_ALIGN (bytes, t->alignment); bytes += FFI_ALIGN (t->size, FFI_SIZEOF_ARG); } -#if defined(_MSC_VER) && defined(_M_IX86) - // stack is not 16-bit aligned on Windows cif->bytes = bytes; -#else - cif->bytes = FFI_ALIGN (bytes, 16); -#endif return FFI_OK; } @@ -290,7 +292,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, } } - bytes = cif->bytes; + bytes = STACK_ALIGN (cif->bytes); stack = alloca(bytes + sizeof(*frame) + rsize); argp = (dir < 0 ? stack + bytes : stack); frame = (struct call_frame *)(stack + bytes); @@ -434,7 +436,7 @@ ffi_closure_inner (struct closure_frame *frame, char *stack) rvalue = frame->rettemp; pabi = &abi_params[cabi]; dir = pabi->dir; - argp = (dir < 0 ? stack + cif->bytes : stack); + argp = (dir < 0 ? stack + STACK_ALIGN (cif->bytes) : stack); switch (flags) { @@ -698,7 +700,7 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue) } } - bytes = cif->bytes; + bytes = STACK_ALIGN (cif->bytes); argp = stack = (void *)((uintptr_t)alloca(bytes + sizeof(*frame) + rsize + 15) & ~16); frame = (struct call_frame *)(stack + bytes);