Support the WIN64/EFI64 calling convention on all X86_64 platforms Add a new calling convention FFI_EFI64, alias FFI_WIN64, on all X86_64 platforms. This allows libffi compiled on a 64-bit x86 platform to call EFI functions. Compile in ffiw64.c and win64.S on all X86_64 platforms. When compiled for a platform other than X86_WIN64, ffiw64.c suffixes its functions with _efi64, to avoid conflict with the platform's actual implementations of those functions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
diff --git a/configure.host b/configure.host
index c6f6a02..a4a22b7 100644
--- a/configure.host
+++ b/configure.host
@@ -246,7 +246,7 @@ case "${TARGET}" in
SOURCES="ffi.c sysv.S"
;;
X86_64)
- SOURCES="ffi64.c unix64.S"
+ SOURCES="ffi64.c unix64.S ffiw64.c win64.S"
;;
X86_WIN64)
SOURCES="ffiw64.c win64.S"
diff --git a/src/x86/ffi64.c b/src/x86/ffi64.c
index 131b5e3..f52749e 100644
--- a/src/x86/ffi64.c
+++ b/src/x86/ffi64.c
@@ -388,6 +388,9 @@ examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES],
/* Perform machine dependent cif processing. */
+extern ffi_status
+ffi_prep_cif_machdep_efi64(ffi_cif *cif);
+
ffi_status
ffi_prep_cif_machdep (ffi_cif *cif)
{
@@ -396,6 +399,8 @@ ffi_prep_cif_machdep (ffi_cif *cif)
size_t bytes, n, rtype_size;
ffi_type *rtype;
+ if (cif->abi == FFI_EFI64)
+ return ffi_prep_cif_machdep_efi64(cif);
if (cif->abi != FFI_UNIX64)
return FFI_BAD_ABI;
@@ -657,22 +662,41 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
flags, rvalue, fn);
}
+extern void
+ffi_call_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue);
+
void
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
+ if (cif->abi == FFI_EFI64)
+ return ffi_call_efi64(cif, fn, rvalue, avalue);
ffi_call_int (cif, fn, rvalue, avalue, NULL);
}
+extern void
+ffi_call_go_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue,
+ void **avalue, void *closure);
+
void
ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
{
+ if (cif->abi == FFI_EFI64)
+ ffi_call_go_efi64(cif, fn, rvalue, avalue, closure);
ffi_call_int (cif, fn, rvalue, avalue, closure);
}
+
extern void ffi_closure_unix64(void) FFI_HIDDEN;
extern void ffi_closure_unix64_sse(void) FFI_HIDDEN;
+extern ffi_status
+ffi_prep_closure_loc_efi64(ffi_closure* closure,
+ ffi_cif* cif,
+ void (*fun)(ffi_cif*, void*, void**, void*),
+ void *user_data,
+ void *codeloc);
+
ffi_status
ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif,
@@ -691,6 +715,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
void (*dest)(void);
char *tramp = closure->tramp;
+ if (cif->abi == FFI_EFI64)
+ return ffi_prep_closure_loc_efi64(closure, cif, fun, user_data, codeloc);
if (cif->abi != FFI_UNIX64)
return FFI_BAD_ABI;
@@ -805,10 +831,16 @@ ffi_closure_unix64_inner(ffi_cif *cif,
extern void ffi_go_closure_unix64(void) FFI_HIDDEN;
extern void ffi_go_closure_unix64_sse(void) FFI_HIDDEN;
+extern ffi_status
+ffi_prep_go_closure_efi64(ffi_go_closure* closure, ffi_cif* cif,
+ void (*fun)(ffi_cif*, void*, void**, void*));
+
ffi_status
ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*))
{
+ if (cif->abi == FFI_EFI64)
+ return ffi_prep_go_closure_efi64(closure, cif, fun);
if (cif->abi != FFI_UNIX64)
return FFI_BAD_ABI;
diff --git a/src/x86/ffitarget.h b/src/x86/ffitarget.h
index 8c1dcac..25e3f4f 100644
--- a/src/x86/ffitarget.h
+++ b/src/x86/ffitarget.h
@@ -87,6 +87,8 @@ typedef enum ffi_abi {
#elif defined(X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
FFI_FIRST_ABI = 1,
FFI_UNIX64,
+ FFI_WIN64,
+ FFI_EFI64 = FFI_WIN64,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_UNIX64
diff --git a/src/x86/ffiw64.c b/src/x86/ffiw64.c
index 31e1d19..0029be0 100644
--- a/src/x86/ffiw64.c
+++ b/src/x86/ffiw64.c
@@ -30,6 +30,10 @@
#include <stdint.h>
#ifdef X86_WIN64
+#define EFI64(name) name
+#else
+#define EFI64(name) name##_efi64
+#endif
struct win64_call_frame
{
@@ -44,7 +48,7 @@ extern void ffi_call_win64 (void *stack, struct win64_call_frame *,
void *closure) FFI_HIDDEN;
ffi_status
-ffi_prep_cif_machdep (ffi_cif *cif)
+EFI64(ffi_prep_cif_machdep)(ffi_cif *cif)
{
int flags, n;
@@ -159,13 +163,13 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
}
void
-ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+EFI64(ffi_call)(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
ffi_call_int (cif, fn, rvalue, avalue, NULL);
}
void
-ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
+EFI64(ffi_call_go)(ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
{
ffi_call_int (cif, fn, rvalue, avalue, closure);
@@ -176,7 +180,7 @@ extern void ffi_closure_win64(void) FFI_HIDDEN;
extern void ffi_go_closure_win64(void) FFI_HIDDEN;
ffi_status
-ffi_prep_closure_loc (ffi_closure* closure,
+EFI64(ffi_prep_closure_loc)(ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data,
@@ -206,7 +210,7 @@ ffi_prep_closure_loc (ffi_closure* closure,
}
ffi_status
-ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
+EFI64(ffi_prep_go_closure)(ffi_go_closure* closure, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*))
{
if (cif->abi != FFI_WIN64)
@@ -277,5 +281,3 @@ ffi_closure_win64_inner(ffi_cif *cif,
fun (cif, rvalue, avalue, user_data);
return flags;
}
-
-#endif /* X86_WIN64 */