From bc95d54ec932fddca832e35344efbecf1344e984 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Thu, 13 Oct 2011 20:44:31 +0200 Subject: [PATCH] FFI: Fix call argument and return handling for I8/U8/I16/U16 types. --- src/lj_ccall.c | 22 +++++++++++++++------- src/lj_crecord.c | 13 ++++++++++++- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/lj_ccall.c b/src/lj_ccall.c index b5cfe616..281b45a6 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c @@ -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. */ diff --git a/src/lj_crecord.c b/src/lj_crecord.c index c688caa3..001cf600 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -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));