aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2011-01-11 03:36:49 +0100
committerMike Pall <mike>2011-01-11 03:36:49 +0100
commit8d858bfefa2049af382b8f01203df59699ec2909 (patch)
tree379cd3b5aed094d60d72cbe8b60396d396ac8d3c /src
parenta54843bb510d4f51e4ce404fe2d42ba80fc74a04 (diff)
downloadluajit-8d858bfefa2049af382b8f01203df59699ec2909.tar.gz
luajit-8d858bfefa2049af382b8f01203df59699ec2909.tar.bz2
luajit-8d858bfefa2049af382b8f01203df59699ec2909.zip
FFI: Fix C calls with complex values on x64.
Diffstat (limited to 'src')
-rw-r--r--src/lj_ccall.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/src/lj_ccall.c b/src/lj_ccall.c
index 6d5156fb..57afb57e 100644
--- a/src/lj_ccall.c
+++ b/src/lj_ccall.c
@@ -44,9 +44,9 @@
44 44
45#define CCALL_HANDLE_REGARG \ 45#define CCALL_HANDLE_REGARG \
46 if (isfp) { /* Try to pass argument in FPRs. */ \ 46 if (isfp) { /* Try to pass argument in FPRs. */ \
47 if (nfpr + isfp <= CCALL_NARG_FPR) { \ 47 if (nfpr + n <= CCALL_NARG_FPR) { \
48 dp = &cc->fpr[nfpr]; \ 48 dp = &cc->fpr[nfpr]; \
49 nfpr += isfp; \ 49 nfpr += n; \
50 goto done; \ 50 goto done; \
51 } \ 51 } \
52 } else { /* Try to pass argument in GPRs. */ \ 52 } else { /* Try to pass argument in GPRs. */ \
@@ -273,6 +273,13 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
273 cc->fpr[ngpr-1].l[0] = cc->gpr[ngpr-1]; 273 cc->fpr[ngpr-1].l[0] = cc->gpr[ngpr-1];
274 } 274 }
275#endif 275#endif
276#if LJ_TARGET_X64 && !LJ_ABI_WIN
277 if (isfp == 2 && n == 2 &&
278 (uint8_t *)dp == (uint8_t *)&cc->fpr[nfpr-2]) {
279 cc->fpr[nfpr-1].d[0] = cc->fpr[nfpr-2].d[1];
280 cc->fpr[nfpr-2].d[1] = 0;
281 }
282#endif
276 } 283 }
277 if (fid) lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too few arguments. */ 284 if (fid) lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too few arguments. */
278 285
@@ -309,20 +316,20 @@ static int ccall_get_results(lua_State *L, CTState *cts, CType *ct,
309 /* Return cdata object which is already on top of stack. */ 316 /* Return cdata object which is already on top of stack. */
310#if !CCALL_COMPLEX_RETREF || !CCALL_COMPLEXF_RETREF 317#if !CCALL_COMPLEX_RETREF || !CCALL_COMPLEXF_RETREF
311 void *dp = cdataptr(cdataV(L->top-1)); /* Use preallocated object. */ 318 void *dp = cdataptr(cdataV(L->top-1)); /* Use preallocated object. */
312#if CCALL_COMPLEX_RETREF && !CCALL_COMPLEXF_RETREF 319#if !CCALL_NUM_FPR
320 memcpy(dp, sp, ctr->size); /* Copy complex from GPRs. */
321#elif CCALL_COMPLEX_RETREF && !CCALL_COMPLEXF_RETREF
313 if (ctr->size == 2*sizeof(float)) 322 if (ctr->size == 2*sizeof(float))
314 memcpy(dp, sp, ctr->size); /* Copy complex float from GPRs. */ 323 *(int64_t *)dp = *(int64_t *)sp; /* Copy complex float from GPRs. */
315#elif CCALL_NUM_FPR 324#elif LJ_TARGET_X64
316 /* Copy non-contiguous re/im part from FPRs to cdata object. */ 325 if (ctr->size == 2*sizeof(float)) { /* Copy complex float from FPR. */
317 if (ctr->size == 2*sizeof(float)) { 326 *(int64_t *)dp = cc->fpr[0].l[0];
318 ((float *)dp)[0] = cc->fpr[0].f[0]; 327 } else { /* Copy non-contiguous complex double from FPRs. */
319 ((float *)dp)[1] = cc->fpr[1].f[0]; 328 ((int64_t *)dp)[0] = cc->fpr[0].l[0];
320 } else { 329 ((int64_t *)dp)[1] = cc->fpr[1].l[0];
321 ((double *)dp)[0] = cc->fpr[0].d[0];
322 ((double *)dp)[1] = cc->fpr[1].d[0];
323 } 330 }
324#else 331#else
325 memcpy(dp, sp, ctr->size); /* Copy complex from GPRs. */ 332#error "missing definition for handling of complex return values"
326#endif 333#endif
327#endif 334#endif
328 return 1; /* One GC step. */ 335 return 1; /* One GC step. */