Various fixes for FFI calls.

Fixes the following scenarios:
 * Returning floating point value.
 * More than 4 GPR arguments.
This commit is contained in:
Michael Munday 2017-01-10 16:11:30 -05:00
parent e933353feb
commit 86a24eac4a
2 changed files with 15 additions and 5 deletions

View File

@ -585,9 +585,9 @@
#define CCALL_HANDLE_REGARG \
if (isfp) { \
if (nfpr < maxgpr) { dp = &cc->fpr[nfpr++]; goto done; } \
if (nfpr < CCALL_NARG_FPR) { dp = &cc->fpr[nfpr++]; goto done; } \
} else { \
if (ngpr < CCALL_NARG_FPR) { dp = &cc->gpr[ngpr++]; goto done; } \
if (ngpr < maxgpr) { dp = &cc->gpr[ngpr++]; goto done; } \
}
#else
@ -1074,6 +1074,15 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
*(int64_t *)dp = (int64_t)*(int32_t *)dp; /* Sign-extend to 64 bit. */
}
#endif
#if LJ_TARGET_S390X
/* Arguments need to be sign-/zero-extended to 64-bits. */
if ((ctype_isinteger_or_bool(d->info) || ctype_isenum(d->info)) && d->size <= 4) {
if (d->info & CTF_UNSIGNED)
*(uint64_t *)dp = (uint64_t)*(uint32_t *)dp;
else
*(int64_t *)dp = (int64_t)*(int32_t *)dp;
}
#endif
#if LJ_TARGET_X64 && LJ_ABI_WIN
if (isva) { /* Windows/x64 mirrors varargs in both register sets. */
if (nfpr == ngpr)

View File

@ -2164,21 +2164,22 @@ static void build_subroutines(BuildCtx *ctx)
| basr r14, r7
|
| stg CRET1, CCSTATE->gpr[0]
| stg f0, CCSTATE->fpr[0]
| std f0, CCSTATE->fpr[0]
|
| agf sp, CCSTATE->spadj
| lmg r6, r15, 48(sp)
| br r14
|
|2:
| sll r1, 3
| lay r10, (offsetof(CCallState, stack))(CCSTATE) // Source.
| lay r11, (CCALL_SPS_EXTRA*8)(sp) // Destination.
|3:
| chi r1, 256
| jl >4
| mvc 0(256, r11), 0(r10)
| la r10, 256*8(r10)
| la r11, 256*8(r11)
| la r10, 256(r10)
| la r11, 256(r11)
| ahi r1, -256
| j <3
|