FFI: Fix call argument and return handling for I8/U8/I16/U16 types.

This commit is contained in:
Mike Pall 2011-10-13 20:44:31 +02:00
parent 120c3adbff
commit bc95d54ec9
2 changed files with 27 additions and 8 deletions

View File

@ -515,11 +515,8 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
/* Find out how (by value/ref) and where (GPR/FPR) to pass an argument. */
if (ctype_isnum(d->info)) {
if (sz > 8) goto err_nyi;
if ((d->info & CTF_FP)) {
if ((d->info & CTF_FP))
isfp = 1;
} else if (sz < CTSIZE_PTR) {
d = ctype_get(cts, CTID_INT_PSZ);
}
} else if (ctype_isvector(d->info)) {
if (CCALL_VECTOR_REG && (sz == 8 || sz == 16))
isfp = 1;
@ -557,6 +554,15 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
dp = rp;
}
lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg));
/* Extend passed integers to 32 bits at least. */
if (ctype_isinteger_or_bool(d->info) && d->size < 4) {
if (d->info & CTF_UNSIGNED)
*(uint32_t *)dp = d->size == 1 ? (uint32_t)*(uint8_t *)dp :
(uint32_t)*(uint16_t *)dp;
else
*(int32_t *)dp = d->size == 1 ? (int32_t)*(int8_t *)dp :
(int32_t)*(int16_t *)dp;
}
#if LJ_TARGET_X64 && LJ_ABI_WIN
if (isva) { /* Windows/x64 mirrors varargs in both register sets. */
if (nfpr == ngpr)
@ -593,7 +599,7 @@ static int ccall_get_results(lua_State *L, CTState *cts, CType *ct,
CCallState *cc, int *ret)
{
CType *ctr = ctype_rawchild(cts, ct);
void *sp = &cc->gpr[0];
uint8_t *sp = (uint8_t *)&cc->gpr[0];
if (ctype_isvoid(ctr->info)) {
*ret = 0; /* Zero results. */
return 0; /* No additional GC step. */
@ -613,17 +619,19 @@ static int ccall_get_results(lua_State *L, CTState *cts, CType *ct,
CCALL_HANDLE_COMPLEXRET2
return 1; /* One GC step. */
}
if (LJ_BE && ctype_isinteger_or_bool(ctr->info) && ctr->size < CTSIZE_PTR)
sp += (CTSIZE_PTR - ctr->size);
#ifdef CCALL_HANDLE_RET
CCALL_HANDLE_RET
#endif
#if CCALL_NUM_FPR
if (ctype_isfp(ctr->info) || ctype_isvector(ctr->info))
sp = &cc->fpr[0];
sp = (uint8_t *)&cc->fpr[0];
#endif
/* No reference types end up here, so there's no need for the CTypeID. */
lua_assert(!(ctype_isrefarray(ctr->info) || ctype_isstruct(ctr->info)));
if (ctype_isenum(ctr->info)) ctr = ctype_child(cts, ctr);
return lj_cconv_tv_ct(cts, ctr, 0, L->top-1, (uint8_t *)sp);
return lj_cconv_tv_ct(cts, ctr, 0, L->top-1, sp);
}
/* Call C function. */

View File

@ -759,7 +759,14 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd,
if (!(ctype_isnum(d->info) || ctype_isptr(d->info) ||
ctype_isenum(d->info)))
lj_trace_err(J, LJ_TRERR_NYICALL);
args[n] = crec_ct_tv(J, d, 0, J->base[n+1], &rd->argv[n+1]);
tr = crec_ct_tv(J, d, 0, J->base[n+1], &rd->argv[n+1]);
if (ctype_isinteger_or_bool(d->info) && d->size < 4) {
if ((d->info & CTF_UNSIGNED))
tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_U8 : IRT_U16, 0);
else
tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_I8 : IRT_I16, IRCONV_SEXT);
}
args[n] = tr;
}
tr = args[0];
for (i = 1; i < n; i++)
@ -799,6 +806,10 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd)
tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func);
if (t == IRT_FLOAT || t == IRT_U32) {
tr = emitconv(tr, IRT_NUM, t, 0);
} else if (t == IRT_I8 || t == IRT_I16) {
tr = emitconv(tr, IRT_INT, t, IRCONV_SEXT);
} else if (t == IRT_U8 || t == IRT_U16) {
tr = emitconv(tr, IRT_INT, t, 0);
} else if (t == IRT_PTR || (LJ_64 && t == IRT_P32) ||
(t == IRT_I64 || t == IRT_U64)) {
TRef trid = lj_ir_kint(J, ctype_cid(ct->info));