diff options
Diffstat (limited to 'src/lj_ccall.c')
-rw-r--r-- | src/lj_ccall.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/src/lj_ccall.c b/src/lj_ccall.c index f003d756..d5f092ea 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c | |||
@@ -901,7 +901,9 @@ static void ccall_copy_struct(CCallState *cc, CType *ctr, void *dp, void *sp, | |||
901 | 901 | ||
902 | /* -- Common C call handling ---------------------------------------------- */ | 902 | /* -- Common C call handling ---------------------------------------------- */ |
903 | 903 | ||
904 | /* Infer the destination CTypeID for a vararg argument. */ | 904 | /* Infer the destination CTypeID for a vararg argument. |
905 | ** Note: may reallocate cts->tab and invalidate CType pointers. | ||
906 | */ | ||
905 | CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o) | 907 | CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o) |
906 | { | 908 | { |
907 | if (tvisnumber(o)) { | 909 | if (tvisnumber(o)) { |
@@ -929,13 +931,16 @@ CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o) | |||
929 | } | 931 | } |
930 | } | 932 | } |
931 | 933 | ||
932 | /* Setup arguments for C call. */ | 934 | /* Setup arguments for C call. |
935 | ** Note: may reallocate cts->tab and invalidate CType pointers. | ||
936 | */ | ||
933 | static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | 937 | static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, |
934 | CCallState *cc) | 938 | CCallState *cc) |
935 | { | 939 | { |
936 | int gcsteps = 0; | 940 | int gcsteps = 0; |
937 | TValue *o, *top = L->top; | 941 | TValue *o, *top = L->top; |
938 | CTypeID fid; | 942 | CTypeID fid; |
943 | CTInfo info = ct->info; /* lj_ccall_ctid_vararg may invalidate ct pointer. */ | ||
939 | CType *ctr; | 944 | CType *ctr; |
940 | MSize maxgpr, ngpr = 0, nsp = 0, narg; | 945 | MSize maxgpr, ngpr = 0, nsp = 0, narg; |
941 | #if CCALL_NARG_FPR | 946 | #if CCALL_NARG_FPR |
@@ -954,7 +959,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
954 | #if LJ_TARGET_X86 | 959 | #if LJ_TARGET_X86 |
955 | /* x86 has several different calling conventions. */ | 960 | /* x86 has several different calling conventions. */ |
956 | cc->resx87 = 0; | 961 | cc->resx87 = 0; |
957 | switch (ctype_cconv(ct->info)) { | 962 | switch (ctype_cconv(info)) { |
958 | case CTCC_FASTCALL: maxgpr = 2; break; | 963 | case CTCC_FASTCALL: maxgpr = 2; break; |
959 | case CTCC_THISCALL: maxgpr = 1; break; | 964 | case CTCC_THISCALL: maxgpr = 1; break; |
960 | default: maxgpr = 0; break; | 965 | default: maxgpr = 0; break; |
@@ -971,7 +976,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
971 | } else if (ctype_iscomplex(ctr->info) || ctype_isstruct(ctr->info)) { | 976 | } else if (ctype_iscomplex(ctr->info) || ctype_isstruct(ctr->info)) { |
972 | /* Preallocate cdata object and anchor it after arguments. */ | 977 | /* Preallocate cdata object and anchor it after arguments. */ |
973 | CTSize sz = ctr->size; | 978 | CTSize sz = ctr->size; |
974 | GCcdata *cd = lj_cdata_new(cts, ctype_cid(ct->info), sz); | 979 | GCcdata *cd = lj_cdata_new(cts, ctype_cid(info), sz); |
975 | void *dp = cdataptr(cd); | 980 | void *dp = cdataptr(cd); |
976 | setcdataV(L, L->top++, cd); | 981 | setcdataV(L, L->top++, cd); |
977 | if (ctype_isstruct(ctr->info)) { | 982 | if (ctype_isstruct(ctr->info)) { |
@@ -994,7 +999,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
994 | } | 999 | } |
995 | 1000 | ||
996 | #if LJ_TARGET_ARM64 && LJ_ABI_WIN | 1001 | #if LJ_TARGET_ARM64 && LJ_ABI_WIN |
997 | if ((ct->info & CTF_VARARG)) { | 1002 | if ((info & CTF_VARARG)) { |
998 | nsp -= maxgpr * CTSIZE_PTR; /* May end up with negative nsp. */ | 1003 | nsp -= maxgpr * CTSIZE_PTR; /* May end up with negative nsp. */ |
999 | ngpr = maxgpr; | 1004 | ngpr = maxgpr; |
1000 | nfpr = CCALL_NARG_FPR; | 1005 | nfpr = CCALL_NARG_FPR; |
@@ -1015,7 +1020,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
1015 | lj_assertL(ctype_isfield(ctf->info), "field expected"); | 1020 | lj_assertL(ctype_isfield(ctf->info), "field expected"); |
1016 | did = ctype_cid(ctf->info); | 1021 | did = ctype_cid(ctf->info); |
1017 | } else { | 1022 | } else { |
1018 | if (!(ct->info & CTF_VARARG)) | 1023 | if (!(info & CTF_VARARG)) |
1019 | lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too many arguments. */ | 1024 | lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too many arguments. */ |
1020 | did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */ | 1025 | did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */ |
1021 | isva = 1; | 1026 | isva = 1; |
@@ -1186,11 +1191,11 @@ int lj_ccall_func(lua_State *L, GCcdata *cd) | |||
1186 | ct = ctype_rawchild(cts, ct); | 1191 | ct = ctype_rawchild(cts, ct); |
1187 | } | 1192 | } |
1188 | if (ctype_isfunc(ct->info)) { | 1193 | if (ctype_isfunc(ct->info)) { |
1194 | CTypeID id = ctype_typeid(cts, ct); | ||
1189 | CCallState cc; | 1195 | CCallState cc; |
1190 | int gcsteps, ret; | 1196 | int gcsteps, ret; |
1191 | cc.func = (void (*)(void))cdata_getptr(cdataptr(cd), sz); | 1197 | cc.func = (void (*)(void))cdata_getptr(cdataptr(cd), sz); |
1192 | gcsteps = ccall_set_args(L, cts, ct, &cc); | 1198 | gcsteps = ccall_set_args(L, cts, ct, &cc); |
1193 | ct = (CType *)((intptr_t)ct-(intptr_t)cts->tab); | ||
1194 | cts->cb.slot = ~0u; | 1199 | cts->cb.slot = ~0u; |
1195 | lj_vm_ffi_call(&cc); | 1200 | lj_vm_ffi_call(&cc); |
1196 | if (cts->cb.slot != ~0u) { /* Blacklist function that called a callback. */ | 1201 | if (cts->cb.slot != ~0u) { /* Blacklist function that called a callback. */ |
@@ -1198,7 +1203,7 @@ int lj_ccall_func(lua_State *L, GCcdata *cd) | |||
1198 | tv.u64 = ((uintptr_t)(void *)cc.func >> 2) | U64x(800000000, 00000000); | 1203 | tv.u64 = ((uintptr_t)(void *)cc.func >> 2) | U64x(800000000, 00000000); |
1199 | setboolV(lj_tab_set(L, cts->miscmap, &tv), 1); | 1204 | setboolV(lj_tab_set(L, cts->miscmap, &tv), 1); |
1200 | } | 1205 | } |
1201 | ct = (CType *)((intptr_t)ct+(intptr_t)cts->tab); /* May be reallocated. */ | 1206 | ct = ctype_get(cts, id); /* Table may have been reallocated. */ |
1202 | gcsteps += ccall_get_results(L, cts, ct, &cc, &ret); | 1207 | gcsteps += ccall_get_results(L, cts, ct, &cc, &ret); |
1203 | #if LJ_TARGET_X86 && LJ_ABI_WIN | 1208 | #if LJ_TARGET_X86 && LJ_ABI_WIN |
1204 | /* Automatically detect __stdcall and fix up C function declaration. */ | 1209 | /* Automatically detect __stdcall and fix up C function declaration. */ |