From bd29d16141d07ca4e436fe457fd6cbefd638ad15 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Sat, 19 Feb 2011 12:56:12 +0100 Subject: [PATCH] FFI: Improve conversion error messages. --- src/lib_ffi.c | 11 +++++++---- src/lj_ccall.c | 13 +++++++------ src/lj_cconv.c | 20 +++++++++++++++----- src/lj_cconv.h | 3 +++ 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/lib_ffi.c b/src/lib_ffi.c index 361c3ba1..e88b6f54 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c @@ -74,7 +74,7 @@ static void *ffi_checkptr(lua_State *L, int narg, CTypeID id) void *p; if (o >= L->top) lj_err_arg(L, narg, LJ_ERR_NOVAL); - lj_cconv_ct_tv(cts, ctype_get(cts, id), (uint8_t *)&p, o, 0); + lj_cconv_ct_tv(cts, ctype_get(cts, id), (uint8_t *)&p, o, CCF_ARG(narg)); return p; } @@ -86,7 +86,8 @@ static int32_t ffi_checkint(lua_State *L, int narg) int32_t i; if (o >= L->top) lj_err_arg(L, narg, LJ_ERR_NOVAL); - lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0); + lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, + CCF_ARG(narg)); return i; } @@ -444,9 +445,11 @@ LJLIB_CF(ffi_string) LJLIB_REC(.) size_t len; if (o+1 < L->top) { len = (size_t)ffi_checkint(L, 2); - lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p, o, 0); + lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p, o, + CCF_ARG(1)); } else { - lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CCHAR), (uint8_t *)&p, o, 0); + lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CCHAR), (uint8_t *)&p, o, + CCF_ARG(1)); len = strlen(p); } L->top = o+1; /* Make sure this is the last item on the stack. */ diff --git a/src/lj_ccall.c b/src/lj_ccall.c index f2eceb6d..3f548c30 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c @@ -140,7 +140,7 @@ int rcl[2]; rcl[0] = rcl[1] = 0; \ if (!ccall_classify_struct(cts, d, rcl, 0)) { \ cc->nsp = nsp; cc->ngpr = ngpr; cc->nfpr = nfpr; \ - if (ccall_struct_arg(cc, cts, d, rcl, o)) goto err_nyi; \ + if (ccall_struct_arg(cc, cts, d, rcl, o, narg)) goto err_nyi; \ nsp = cc->nsp; ngpr = cc->ngpr; nfpr = cc->nfpr; \ continue; \ } /* Pass all other structs by value on stack. */ @@ -278,11 +278,12 @@ static int ccall_struct_reg(CCallState *cc, GPRArg *dp, int *rcl) /* Pass a small struct argument. */ static int ccall_struct_arg(CCallState *cc, CTState *cts, CType *d, int *rcl, - TValue *o) + TValue *o, int narg) { GPRArg dp[2]; dp[0] = dp[1] = 0; - lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, 0); /* Convert to temp. struct. */ + /* Convert to temp. struct. */ + lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg)); if (!ccall_struct_reg(cc, dp, rcl)) { /* Register overflow? Pass on stack. */ MSize nsp = cc->nsp, n = rcl[1] ? 2 : 1; if (nsp + n > CCALL_MAXSTACK) return 1; /* Too many arguments. */ @@ -347,7 +348,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, TValue *o, *top = L->top; CTypeID fid; CType *ctr; - MSize maxgpr, ngpr = 0, nsp = 0; + MSize maxgpr, ngpr = 0, nsp = 0, narg; #if CCALL_NARG_FPR MSize nfpr = 0; #endif @@ -401,7 +402,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, } /* Walk through all passed arguments. */ - for (o = L->base+1; o < top; o++) { + for (o = L->base+1, narg = 1; o < top; o++, narg++) { CTypeID did; CType *d; CTSize sz; @@ -466,7 +467,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, *(void **)dp = rp; dp = rp; } - lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, 0); + lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg)); #if LJ_TARGET_X64 && LJ_ABI_WIN if (isva) { /* Windows/x64 mirrors varargs in both register sets. */ if (nfpr == ngpr) diff --git a/src/lj_cconv.c b/src/lj_cconv.c index 1e6df8d8..94a9895f 100644 --- a/src/lj_cconv.c +++ b/src/lj_cconv.c @@ -22,17 +22,26 @@ LJ_NORET static void cconv_err_conv(CTState *cts, CType *d, CType *s, const char *dst = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, d), NULL)); const char *src; if ((flags & CCF_FROMTV)) - src = lj_obj_typename[1+(ctype_isnum(s->info) ? LUA_TNUMBER : LUA_TSTRING)]; + src = lj_obj_typename[1+(ctype_isnum(s->info) ? LUA_TNUMBER : + ctype_isarray(s->info) ? LUA_TSTRING : LUA_TNIL)]; else src = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, s), NULL)); - lj_err_callerv(cts->L, LJ_ERR_FFI_BADCONV, src, dst); + if (CCF_GETARG(flags)) + lj_err_argv(cts->L, CCF_GETARG(flags), LJ_ERR_FFI_BADCONV, src, dst); + else + lj_err_callerv(cts->L, LJ_ERR_FFI_BADCONV, src, dst); } /* Bad conversion from TValue. */ -LJ_NORET static void cconv_err_convtv(CTState *cts, CType *d, TValue *o) +LJ_NORET static void cconv_err_convtv(CTState *cts, CType *d, TValue *o, + CTInfo flags) { const char *dst = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, d), NULL)); - lj_err_callerv(cts->L, LJ_ERR_FFI_BADCONV, typename(o), dst); + const char *src = typename(o); + if (CCF_GETARG(flags)) + lj_err_argv(cts->L, CCF_GETARG(flags), LJ_ERR_FFI_BADCONV, src, dst); + else + lj_err_callerv(cts->L, LJ_ERR_FFI_BADCONV, src, dst); } /* Initializer overflow. */ @@ -570,13 +579,14 @@ void lj_cconv_ct_tv(CTState *cts, CType *d, sid = CTID_BOOL; } else if (tvisnil(o)) { tmpptr = (void *)0; + flags |= CCF_FROMTV; } else if (tvisudata(o)) { tmpptr = uddata(udataV(o)); } else if (tvislightud(o)) { tmpptr = lightudV(o); } else { err_conv: - cconv_err_convtv(cts, d, o); + cconv_err_convtv(cts, d, o, flags); } s = ctype_get(cts, sid); doconv: diff --git a/src/lj_cconv.h b/src/lj_cconv.h index 494f9d4e..47c14596 100644 --- a/src/lj_cconv.h +++ b/src/lj_cconv.h @@ -48,6 +48,9 @@ static LJ_AINLINE uint32_t cconv_idx(CTInfo info) #define CCF_SAME 0x00000004u #define CCF_IGNQUAL 0x00000008u +#define CCF_ARG_SHIFT 8 +#define CCF_ARG(n) ((n) << CCF_ARG_SHIFT) +#define CCF_GETARG(f) ((f) >> CCF_ARG_SHIFT) LJ_FUNC int lj_cconv_compatptr(CTState *cts, CType *d, CType *s, CTInfo flags); LJ_FUNC void lj_cconv_ct_ct(CTState *cts, CType *d, CType *s,