diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib_ffi.c | 11 | ||||
| -rw-r--r-- | src/lj_ccall.c | 13 | ||||
| -rw-r--r-- | src/lj_cconv.c | 20 | ||||
| -rw-r--r-- | 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) | |||
| 74 | void *p; | 74 | void *p; |
| 75 | if (o >= L->top) | 75 | if (o >= L->top) |
| 76 | lj_err_arg(L, narg, LJ_ERR_NOVAL); | 76 | lj_err_arg(L, narg, LJ_ERR_NOVAL); |
| 77 | lj_cconv_ct_tv(cts, ctype_get(cts, id), (uint8_t *)&p, o, 0); | 77 | lj_cconv_ct_tv(cts, ctype_get(cts, id), (uint8_t *)&p, o, CCF_ARG(narg)); |
| 78 | return p; | 78 | return p; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| @@ -86,7 +86,8 @@ static int32_t ffi_checkint(lua_State *L, int narg) | |||
| 86 | int32_t i; | 86 | int32_t i; |
| 87 | if (o >= L->top) | 87 | if (o >= L->top) |
| 88 | lj_err_arg(L, narg, LJ_ERR_NOVAL); | 88 | lj_err_arg(L, narg, LJ_ERR_NOVAL); |
| 89 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0); | 89 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, |
| 90 | CCF_ARG(narg)); | ||
| 90 | return i; | 91 | return i; |
| 91 | } | 92 | } |
| 92 | 93 | ||
| @@ -444,9 +445,11 @@ LJLIB_CF(ffi_string) LJLIB_REC(.) | |||
| 444 | size_t len; | 445 | size_t len; |
| 445 | if (o+1 < L->top) { | 446 | if (o+1 < L->top) { |
| 446 | len = (size_t)ffi_checkint(L, 2); | 447 | len = (size_t)ffi_checkint(L, 2); |
| 447 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p, o, 0); | 448 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p, o, |
| 449 | CCF_ARG(1)); | ||
| 448 | } else { | 450 | } else { |
| 449 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CCHAR), (uint8_t *)&p, o, 0); | 451 | lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CCHAR), (uint8_t *)&p, o, |
| 452 | CCF_ARG(1)); | ||
| 450 | len = strlen(p); | 453 | len = strlen(p); |
| 451 | } | 454 | } |
| 452 | L->top = o+1; /* Make sure this is the last item on the stack. */ | 455 | 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 @@ | |||
| 140 | int rcl[2]; rcl[0] = rcl[1] = 0; \ | 140 | int rcl[2]; rcl[0] = rcl[1] = 0; \ |
| 141 | if (!ccall_classify_struct(cts, d, rcl, 0)) { \ | 141 | if (!ccall_classify_struct(cts, d, rcl, 0)) { \ |
| 142 | cc->nsp = nsp; cc->ngpr = ngpr; cc->nfpr = nfpr; \ | 142 | cc->nsp = nsp; cc->ngpr = ngpr; cc->nfpr = nfpr; \ |
| 143 | if (ccall_struct_arg(cc, cts, d, rcl, o)) goto err_nyi; \ | 143 | if (ccall_struct_arg(cc, cts, d, rcl, o, narg)) goto err_nyi; \ |
| 144 | nsp = cc->nsp; ngpr = cc->ngpr; nfpr = cc->nfpr; \ | 144 | nsp = cc->nsp; ngpr = cc->ngpr; nfpr = cc->nfpr; \ |
| 145 | continue; \ | 145 | continue; \ |
| 146 | } /* Pass all other structs by value on stack. */ | 146 | } /* Pass all other structs by value on stack. */ |
| @@ -278,11 +278,12 @@ static int ccall_struct_reg(CCallState *cc, GPRArg *dp, int *rcl) | |||
| 278 | 278 | ||
| 279 | /* Pass a small struct argument. */ | 279 | /* Pass a small struct argument. */ |
| 280 | static int ccall_struct_arg(CCallState *cc, CTState *cts, CType *d, int *rcl, | 280 | static int ccall_struct_arg(CCallState *cc, CTState *cts, CType *d, int *rcl, |
| 281 | TValue *o) | 281 | TValue *o, int narg) |
| 282 | { | 282 | { |
| 283 | GPRArg dp[2]; | 283 | GPRArg dp[2]; |
| 284 | dp[0] = dp[1] = 0; | 284 | dp[0] = dp[1] = 0; |
| 285 | lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, 0); /* Convert to temp. struct. */ | 285 | /* Convert to temp. struct. */ |
| 286 | lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg)); | ||
| 286 | if (!ccall_struct_reg(cc, dp, rcl)) { /* Register overflow? Pass on stack. */ | 287 | if (!ccall_struct_reg(cc, dp, rcl)) { /* Register overflow? Pass on stack. */ |
| 287 | MSize nsp = cc->nsp, n = rcl[1] ? 2 : 1; | 288 | MSize nsp = cc->nsp, n = rcl[1] ? 2 : 1; |
| 288 | if (nsp + n > CCALL_MAXSTACK) return 1; /* Too many arguments. */ | 289 | 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, | |||
| 347 | TValue *o, *top = L->top; | 348 | TValue *o, *top = L->top; |
| 348 | CTypeID fid; | 349 | CTypeID fid; |
| 349 | CType *ctr; | 350 | CType *ctr; |
| 350 | MSize maxgpr, ngpr = 0, nsp = 0; | 351 | MSize maxgpr, ngpr = 0, nsp = 0, narg; |
| 351 | #if CCALL_NARG_FPR | 352 | #if CCALL_NARG_FPR |
| 352 | MSize nfpr = 0; | 353 | MSize nfpr = 0; |
| 353 | #endif | 354 | #endif |
| @@ -401,7 +402,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
| 401 | } | 402 | } |
| 402 | 403 | ||
| 403 | /* Walk through all passed arguments. */ | 404 | /* Walk through all passed arguments. */ |
| 404 | for (o = L->base+1; o < top; o++) { | 405 | for (o = L->base+1, narg = 1; o < top; o++, narg++) { |
| 405 | CTypeID did; | 406 | CTypeID did; |
| 406 | CType *d; | 407 | CType *d; |
| 407 | CTSize sz; | 408 | CTSize sz; |
| @@ -466,7 +467,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
| 466 | *(void **)dp = rp; | 467 | *(void **)dp = rp; |
| 467 | dp = rp; | 468 | dp = rp; |
| 468 | } | 469 | } |
| 469 | lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, 0); | 470 | lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg)); |
| 470 | #if LJ_TARGET_X64 && LJ_ABI_WIN | 471 | #if LJ_TARGET_X64 && LJ_ABI_WIN |
| 471 | if (isva) { /* Windows/x64 mirrors varargs in both register sets. */ | 472 | if (isva) { /* Windows/x64 mirrors varargs in both register sets. */ |
| 472 | if (nfpr == ngpr) | 473 | 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, | |||
| 22 | const char *dst = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, d), NULL)); | 22 | const char *dst = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, d), NULL)); |
| 23 | const char *src; | 23 | const char *src; |
| 24 | if ((flags & CCF_FROMTV)) | 24 | if ((flags & CCF_FROMTV)) |
| 25 | src = lj_obj_typename[1+(ctype_isnum(s->info) ? LUA_TNUMBER : LUA_TSTRING)]; | 25 | src = lj_obj_typename[1+(ctype_isnum(s->info) ? LUA_TNUMBER : |
| 26 | ctype_isarray(s->info) ? LUA_TSTRING : LUA_TNIL)]; | ||
| 26 | else | 27 | else |
| 27 | src = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, s), NULL)); | 28 | src = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, s), NULL)); |
| 28 | lj_err_callerv(cts->L, LJ_ERR_FFI_BADCONV, src, dst); | 29 | if (CCF_GETARG(flags)) |
| 30 | lj_err_argv(cts->L, CCF_GETARG(flags), LJ_ERR_FFI_BADCONV, src, dst); | ||
| 31 | else | ||
| 32 | lj_err_callerv(cts->L, LJ_ERR_FFI_BADCONV, src, dst); | ||
| 29 | } | 33 | } |
| 30 | 34 | ||
| 31 | /* Bad conversion from TValue. */ | 35 | /* Bad conversion from TValue. */ |
| 32 | LJ_NORET static void cconv_err_convtv(CTState *cts, CType *d, TValue *o) | 36 | LJ_NORET static void cconv_err_convtv(CTState *cts, CType *d, TValue *o, |
| 37 | CTInfo flags) | ||
| 33 | { | 38 | { |
| 34 | const char *dst = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, d), NULL)); | 39 | const char *dst = strdata(lj_ctype_repr(cts->L, ctype_typeid(cts, d), NULL)); |
| 35 | lj_err_callerv(cts->L, LJ_ERR_FFI_BADCONV, typename(o), dst); | 40 | const char *src = typename(o); |
| 41 | if (CCF_GETARG(flags)) | ||
| 42 | lj_err_argv(cts->L, CCF_GETARG(flags), LJ_ERR_FFI_BADCONV, src, dst); | ||
| 43 | else | ||
| 44 | lj_err_callerv(cts->L, LJ_ERR_FFI_BADCONV, src, dst); | ||
| 36 | } | 45 | } |
| 37 | 46 | ||
| 38 | /* Initializer overflow. */ | 47 | /* Initializer overflow. */ |
| @@ -570,13 +579,14 @@ void lj_cconv_ct_tv(CTState *cts, CType *d, | |||
| 570 | sid = CTID_BOOL; | 579 | sid = CTID_BOOL; |
| 571 | } else if (tvisnil(o)) { | 580 | } else if (tvisnil(o)) { |
| 572 | tmpptr = (void *)0; | 581 | tmpptr = (void *)0; |
| 582 | flags |= CCF_FROMTV; | ||
| 573 | } else if (tvisudata(o)) { | 583 | } else if (tvisudata(o)) { |
| 574 | tmpptr = uddata(udataV(o)); | 584 | tmpptr = uddata(udataV(o)); |
| 575 | } else if (tvislightud(o)) { | 585 | } else if (tvislightud(o)) { |
| 576 | tmpptr = lightudV(o); | 586 | tmpptr = lightudV(o); |
| 577 | } else { | 587 | } else { |
| 578 | err_conv: | 588 | err_conv: |
| 579 | cconv_err_convtv(cts, d, o); | 589 | cconv_err_convtv(cts, d, o, flags); |
| 580 | } | 590 | } |
| 581 | s = ctype_get(cts, sid); | 591 | s = ctype_get(cts, sid); |
| 582 | doconv: | 592 | 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) | |||
| 48 | #define CCF_SAME 0x00000004u | 48 | #define CCF_SAME 0x00000004u |
| 49 | #define CCF_IGNQUAL 0x00000008u | 49 | #define CCF_IGNQUAL 0x00000008u |
| 50 | 50 | ||
| 51 | #define CCF_ARG_SHIFT 8 | ||
| 52 | #define CCF_ARG(n) ((n) << CCF_ARG_SHIFT) | ||
| 53 | #define CCF_GETARG(f) ((f) >> CCF_ARG_SHIFT) | ||
| 51 | 54 | ||
| 52 | LJ_FUNC int lj_cconv_compatptr(CTState *cts, CType *d, CType *s, CTInfo flags); | 55 | LJ_FUNC int lj_cconv_compatptr(CTState *cts, CType *d, CType *s, CTInfo flags); |
| 53 | LJ_FUNC void lj_cconv_ct_ct(CTState *cts, CType *d, CType *s, | 56 | LJ_FUNC void lj_cconv_ct_ct(CTState *cts, CType *d, CType *s, |
