diff options
author | Mike Pall <mike> | 2011-01-11 03:36:49 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2011-01-11 03:36:49 +0100 |
commit | 8d858bfefa2049af382b8f01203df59699ec2909 (patch) | |
tree | 379cd3b5aed094d60d72cbe8b60396d396ac8d3c /src | |
parent | a54843bb510d4f51e4ce404fe2d42ba80fc74a04 (diff) | |
download | luajit-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.c | 33 |
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. */ |