summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Green <green@moxielogic.com>2013-02-06 17:37:15 -0500
committerAnthony Green <green@moxielogic.com>2013-02-06 17:37:15 -0500
commit6a790129427121f7db2d876e7218a3104e6d2741 (patch)
tree8238ff3b070fe20edef80d3d108b7e0b6884cead
parent370112938e705128fd5dd4017fc1a1210bd0271a (diff)
downloadlibffi-6a790129427121f7db2d876e7218a3104e6d2741.tar.gz
Work around LLVM ABI problem on x86-64
-rw-r--r--ChangeLog5
-rw-r--r--src/x86/ffi64.c21
2 files changed, 24 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 815156c..b9da7b4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-02-02 Mark H Weaver <mhw@netris.org>
+
+ * src/x86/ffi64.c (ffi_call): Sign-extend integer arguments passed
+ via general purpose registers.
+
2013-01-21 Nathan Rossi <nathan.rossi@xilinx.com>
* README: Add MicroBlaze details.
diff --git a/src/x86/ffi64.c b/src/x86/ffi64.c
index b8a823d..2014af2 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 (&reg_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 *)&reg_args->gpr[gprcount] = (SINT64) *((SINT8 *) a);
+ break;
+ case FFI_TYPE_SINT16:
+ *(SINT64 *)&reg_args->gpr[gprcount] = (SINT64) *((SINT16 *) a);
+ break;
+ case FFI_TYPE_SINT32:
+ *(SINT64 *)&reg_args->gpr[gprcount] = (SINT64) *((SINT32 *) a);
+ break;
+ default:
+ reg_args->gpr[gprcount] = 0;
+ memcpy (&reg_args->gpr[gprcount], a, size < 8 ? size : 8);
+ }
gprcount++;
break;
case X86_64_SSE_CLASS: