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;
}
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;
}
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. */
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. */
/* 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. */
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
}
/* 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;
*(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)
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. */
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:
#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,