diff options
Diffstat (limited to 'src/lj_ccall.c')
-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. */ |