diff options
Diffstat (limited to '')
| -rw-r--r-- | src/lj_ccall.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/src/lj_ccall.c b/src/lj_ccall.c index 9c99bec7..5d6bb03d 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c | |||
| @@ -623,7 +623,9 @@ noth: /* Not a homogeneous float/double aggregate. */ | |||
| 623 | 623 | ||
| 624 | /* -- Common C call handling ---------------------------------------------- */ | 624 | /* -- Common C call handling ---------------------------------------------- */ |
| 625 | 625 | ||
| 626 | /* Infer the destination CTypeID for a vararg argument. */ | 626 | /* Infer the destination CTypeID for a vararg argument. |
| 627 | ** Note: may reallocate cts->tab and invalidate CType pointers. | ||
| 628 | */ | ||
| 627 | CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o) | 629 | CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o) |
| 628 | { | 630 | { |
| 629 | if (tvisnumber(o)) { | 631 | if (tvisnumber(o)) { |
| @@ -651,13 +653,16 @@ CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o) | |||
| 651 | } | 653 | } |
| 652 | } | 654 | } |
| 653 | 655 | ||
| 654 | /* Setup arguments for C call. */ | 656 | /* Setup arguments for C call. |
| 657 | ** Note: may reallocate cts->tab and invalidate CType pointers. | ||
| 658 | */ | ||
| 655 | static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | 659 | static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, |
| 656 | CCallState *cc) | 660 | CCallState *cc) |
| 657 | { | 661 | { |
| 658 | int gcsteps = 0; | 662 | int gcsteps = 0; |
| 659 | TValue *o, *top = L->top; | 663 | TValue *o, *top = L->top; |
| 660 | CTypeID fid; | 664 | CTypeID fid; |
| 665 | CTInfo info = ct->info; /* lj_ccall_ctid_vararg may invalidate ct pointer. */ | ||
| 661 | CType *ctr; | 666 | CType *ctr; |
| 662 | MSize maxgpr, ngpr = 0, nsp = 0, narg; | 667 | MSize maxgpr, ngpr = 0, nsp = 0, narg; |
| 663 | #if CCALL_NARG_FPR | 668 | #if CCALL_NARG_FPR |
| @@ -676,7 +681,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
| 676 | #if LJ_TARGET_X86 | 681 | #if LJ_TARGET_X86 |
| 677 | /* x86 has several different calling conventions. */ | 682 | /* x86 has several different calling conventions. */ |
| 678 | cc->resx87 = 0; | 683 | cc->resx87 = 0; |
| 679 | switch (ctype_cconv(ct->info)) { | 684 | switch (ctype_cconv(info)) { |
| 680 | case CTCC_FASTCALL: maxgpr = 2; break; | 685 | case CTCC_FASTCALL: maxgpr = 2; break; |
| 681 | case CTCC_THISCALL: maxgpr = 1; break; | 686 | case CTCC_THISCALL: maxgpr = 1; break; |
| 682 | default: maxgpr = 0; break; | 687 | default: maxgpr = 0; break; |
| @@ -693,7 +698,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
| 693 | } else if (ctype_iscomplex(ctr->info) || ctype_isstruct(ctr->info)) { | 698 | } else if (ctype_iscomplex(ctr->info) || ctype_isstruct(ctr->info)) { |
| 694 | /* Preallocate cdata object and anchor it after arguments. */ | 699 | /* Preallocate cdata object and anchor it after arguments. */ |
| 695 | CTSize sz = ctr->size; | 700 | CTSize sz = ctr->size; |
| 696 | GCcdata *cd = lj_cdata_new(cts, ctype_cid(ct->info), sz); | 701 | GCcdata *cd = lj_cdata_new(cts, ctype_cid(info), sz); |
| 697 | void *dp = cdataptr(cd); | 702 | void *dp = cdataptr(cd); |
| 698 | setcdataV(L, L->top++, cd); | 703 | setcdataV(L, L->top++, cd); |
| 699 | if (ctype_isstruct(ctr->info)) { | 704 | if (ctype_isstruct(ctr->info)) { |
| @@ -729,7 +734,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
| 729 | lua_assert(ctype_isfield(ctf->info)); | 734 | lua_assert(ctype_isfield(ctf->info)); |
| 730 | did = ctype_cid(ctf->info); | 735 | did = ctype_cid(ctf->info); |
| 731 | } else { | 736 | } else { |
| 732 | if (!(ct->info & CTF_VARARG)) | 737 | if (!(info & CTF_VARARG)) |
| 733 | lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too many arguments. */ | 738 | lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too many arguments. */ |
| 734 | did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */ | 739 | did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */ |
| 735 | isva = 1; | 740 | isva = 1; |
| @@ -869,11 +874,11 @@ int lj_ccall_func(lua_State *L, GCcdata *cd) | |||
| 869 | ct = ctype_rawchild(cts, ct); | 874 | ct = ctype_rawchild(cts, ct); |
| 870 | } | 875 | } |
| 871 | if (ctype_isfunc(ct->info)) { | 876 | if (ctype_isfunc(ct->info)) { |
| 877 | CTypeID id = ctype_typeid(cts, ct); | ||
| 872 | CCallState cc; | 878 | CCallState cc; |
| 873 | int gcsteps, ret; | 879 | int gcsteps, ret; |
| 874 | cc.func = (void (*)(void))cdata_getptr(cdataptr(cd), sz); | 880 | cc.func = (void (*)(void))cdata_getptr(cdataptr(cd), sz); |
| 875 | gcsteps = ccall_set_args(L, cts, ct, &cc); | 881 | gcsteps = ccall_set_args(L, cts, ct, &cc); |
| 876 | ct = (CType *)((intptr_t)ct-(intptr_t)cts->tab); | ||
| 877 | cts->cb.slot = ~0u; | 882 | cts->cb.slot = ~0u; |
| 878 | lj_vm_ffi_call(&cc); | 883 | lj_vm_ffi_call(&cc); |
| 879 | if (cts->cb.slot != ~0u) { /* Blacklist function that called a callback. */ | 884 | if (cts->cb.slot != ~0u) { /* Blacklist function that called a callback. */ |
| @@ -881,7 +886,7 @@ int lj_ccall_func(lua_State *L, GCcdata *cd) | |||
| 881 | setlightudV(&tv, (void *)cc.func); | 886 | setlightudV(&tv, (void *)cc.func); |
| 882 | setboolV(lj_tab_set(L, cts->miscmap, &tv), 1); | 887 | setboolV(lj_tab_set(L, cts->miscmap, &tv), 1); |
| 883 | } | 888 | } |
| 884 | ct = (CType *)((intptr_t)ct+(intptr_t)cts->tab); /* May be reallocated. */ | 889 | ct = ctype_get(cts, id); /* Table may have been reallocated. */ |
| 885 | gcsteps += ccall_get_results(L, cts, ct, &cc, &ret); | 890 | gcsteps += ccall_get_results(L, cts, ct, &cc, &ret); |
| 886 | #if LJ_TARGET_X86 && LJ_ABI_WIN | 891 | #if LJ_TARGET_X86 && LJ_ABI_WIN |
| 887 | /* Automatically detect __stdcall and fix up C function declaration. */ | 892 | /* Automatically detect __stdcall and fix up C function declaration. */ |
