From bd29d16141d07ca4e436fe457fd6cbefd638ad15 Mon Sep 17 00:00:00 2001
From: Mike Pall <mike>
Date: Sat, 19 Feb 2011 12:56:12 +0100
Subject: 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(-)

(limited to 'src')

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,
-- 
cgit v1.2.3-55-g6feb