diff options
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. */ |
