From 6a790129427121f7db2d876e7218a3104e6d2741 Mon Sep 17 00:00:00 2001 From: Anthony Green Date: Wed, 6 Feb 2013 17:37:15 -0500 Subject: [PATCH] Work around LLVM ABI problem on x86-64 --- ChangeLog | 5 +++++ src/x86/ffi64.c | 21 +++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 815156c4..b9da7b40 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-02-02 Mark H Weaver + + * src/x86/ffi64.c (ffi_call): Sign-extend integer arguments passed + via general purpose registers. + 2013-01-21 Nathan Rossi * README: Add MicroBlaze details. diff --git a/src/x86/ffi64.c b/src/x86/ffi64.c index b8a823d3..2014af24 100644 --- a/src/x86/ffi64.c +++ b/src/x86/ffi64.c @@ -484,8 +484,25 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { case X86_64_INTEGER_CLASS: case X86_64_INTEGERSI_CLASS: - reg_args->gpr[gprcount] = 0; - memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); + /* Sign-extend integer arguments passed in general + purpose registers, to cope with the fact that + LLVM incorrectly assumes that this will be done + (the x86-64 PS ABI does not specify this). */ + switch (arg_types[i]->type) + { + case FFI_TYPE_SINT8: + *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT8 *) a); + break; + case FFI_TYPE_SINT16: + *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT16 *) a); + break; + case FFI_TYPE_SINT32: + *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT32 *) a); + break; + default: + reg_args->gpr[gprcount] = 0; + memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); + } gprcount++; break; case X86_64_SSE_CLASS: