Fix FFI_STDCALL ABI (#514)
authorAndreas Schwab <schwab@linux-m68k.org>
Sat, 26 Oct 2019 12:57:05 +0000 (14:57 +0200)
committerAnthony Green <green@moxielogic.com>
Sat, 26 Oct 2019 12:57:05 +0000 (08:57 -0400)
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

index 883cc4a58448e0731781daf1869ca67ee95f6ea6..9a592185a1d479ddd43b90f2fb3ae0710da73a77 100644 (file)
 # 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);