mirror of
https://github.com/partic2/libffi
synced 2026-11-10 18:17:19 +00:00
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.
This commit is contained in:
committed by
Anthony Green
parent
ca112537df
commit
a8efc2f789
+10
-8
@@ -51,6 +51,13 @@
|
|||||||
# define __declspec(x) __attribute__((x))
|
# define __declspec(x) __attribute__((x))
|
||||||
#endif
|
#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. */
|
/* Perform machine dependent cif processing. */
|
||||||
ffi_status FFI_HIDDEN
|
ffi_status FFI_HIDDEN
|
||||||
ffi_prep_cif_machdep(ffi_cif *cif)
|
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 (bytes, t->alignment);
|
||||||
bytes += FFI_ALIGN (t->size, FFI_SIZEOF_ARG);
|
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;
|
cif->bytes = bytes;
|
||||||
#else
|
|
||||||
cif->bytes = FFI_ALIGN (bytes, 16);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return FFI_OK;
|
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);
|
stack = alloca(bytes + sizeof(*frame) + rsize);
|
||||||
argp = (dir < 0 ? stack + bytes : stack);
|
argp = (dir < 0 ? stack + bytes : stack);
|
||||||
frame = (struct call_frame *)(stack + bytes);
|
frame = (struct call_frame *)(stack + bytes);
|
||||||
@@ -434,7 +436,7 @@ ffi_closure_inner (struct closure_frame *frame, char *stack)
|
|||||||
rvalue = frame->rettemp;
|
rvalue = frame->rettemp;
|
||||||
pabi = &abi_params[cabi];
|
pabi = &abi_params[cabi];
|
||||||
dir = pabi->dir;
|
dir = pabi->dir;
|
||||||
argp = (dir < 0 ? stack + cif->bytes : stack);
|
argp = (dir < 0 ? stack + STACK_ALIGN (cif->bytes) : stack);
|
||||||
|
|
||||||
switch (flags)
|
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 =
|
argp = stack =
|
||||||
(void *)((uintptr_t)alloca(bytes + sizeof(*frame) + rsize + 15) & ~16);
|
(void *)((uintptr_t)alloca(bytes + sizeof(*frame) + rsize + 15) & ~16);
|
||||||
frame = (struct call_frame *)(stack + bytes);
|
frame = (struct call_frame *)(stack + bytes);
|
||||||
|
|||||||
Reference in New Issue
Block a user