aboutsummaryrefslogtreecommitdiff
path: root/src/lj_ccall.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_ccall.c')
-rw-r--r--src/lj_ccall.c39
1 files changed, 26 insertions, 13 deletions
diff --git a/src/lj_ccall.c b/src/lj_ccall.c
index ae69cd28..d5f092ea 100644
--- a/src/lj_ccall.c
+++ b/src/lj_ccall.c
@@ -781,17 +781,24 @@ static unsigned int ccall_classify_struct(CTState *cts, CType *ct)
781{ 781{
782 CTSize sz = ct->size; 782 CTSize sz = ct->size;
783 unsigned int r = 0, n = 0, isu = (ct->info & CTF_UNION); 783 unsigned int r = 0, n = 0, isu = (ct->info & CTF_UNION);
784 while (ct->sib) { 784 while (ct->sib && n <= 4) {
785 unsigned int m = 1;
785 CType *sct; 786 CType *sct;
786 ct = ctype_get(cts, ct->sib); 787 ct = ctype_get(cts, ct->sib);
787 if (ctype_isfield(ct->info)) { 788 if (ctype_isfield(ct->info)) {
788 sct = ctype_rawchild(cts, ct); 789 sct = ctype_rawchild(cts, ct);
790 if (ctype_isarray(sct->info)) {
791 CType *cct = ctype_rawchild(cts, sct);
792 if (!cct->size) continue;
793 m = sct->size / cct->size;
794 sct = cct;
795 }
789 if (ctype_isfp(sct->info)) { 796 if (ctype_isfp(sct->info)) {
790 r |= sct->size; 797 r |= sct->size;
791 if (!isu) n++; else if (n == 0) n = 1; 798 if (!isu) n += m; else if (n < m) n = m;
792 } else if (ctype_iscomplex(sct->info)) { 799 } else if (ctype_iscomplex(sct->info)) {
793 r |= (sct->size >> 1); 800 r |= (sct->size >> 1);
794 if (!isu) n += 2; else if (n < 2) n = 2; 801 if (!isu) n += 2*m; else if (n < 2*m) n = 2*m;
795 } else if (ctype_isstruct(sct->info)) { 802 } else if (ctype_isstruct(sct->info)) {
796 goto substruct; 803 goto substruct;
797 } else { 804 } else {
@@ -803,10 +810,11 @@ static unsigned int ccall_classify_struct(CTState *cts, CType *ct)
803 sct = ctype_rawchild(cts, ct); 810 sct = ctype_rawchild(cts, ct);
804 substruct: 811 substruct:
805 if (sct->size > 0) { 812 if (sct->size > 0) {
806 unsigned int s = ccall_classify_struct(cts, sct); 813 unsigned int s = ccall_classify_struct(cts, sct), sn;
807 if (s <= 1) goto noth; 814 if (s <= 1) goto noth;
808 r |= (s & 255); 815 r |= (s & 255);
809 if (!isu) n += (s >> 8); else if (n < (s >>8)) n = (s >> 8); 816 sn = (s >> 8) * m;
817 if (!isu) n += sn; else if (n < sn) n = sn;
810 } 818 }
811 } 819 }
812 } 820 }
@@ -893,7 +901,9 @@ static void ccall_copy_struct(CCallState *cc, CType *ctr, void *dp, void *sp,
893 901
894/* -- Common C call handling ---------------------------------------------- */ 902/* -- Common C call handling ---------------------------------------------- */
895 903
896/* 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*/
897CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o) 907CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o)
898{ 908{
899 if (tvisnumber(o)) { 909 if (tvisnumber(o)) {
@@ -921,13 +931,16 @@ CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o)
921 } 931 }
922} 932}
923 933
924/* Setup arguments for C call. */ 934/* Setup arguments for C call.
935** Note: may reallocate cts->tab and invalidate CType pointers.
936*/
925static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, 937static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
926 CCallState *cc) 938 CCallState *cc)
927{ 939{
928 int gcsteps = 0; 940 int gcsteps = 0;
929 TValue *o, *top = L->top; 941 TValue *o, *top = L->top;
930 CTypeID fid; 942 CTypeID fid;
943 CTInfo info = ct->info; /* lj_ccall_ctid_vararg may invalidate ct pointer. */
931 CType *ctr; 944 CType *ctr;
932 MSize maxgpr, ngpr = 0, nsp = 0, narg; 945 MSize maxgpr, ngpr = 0, nsp = 0, narg;
933#if CCALL_NARG_FPR 946#if CCALL_NARG_FPR
@@ -946,7 +959,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
946#if LJ_TARGET_X86 959#if LJ_TARGET_X86
947 /* x86 has several different calling conventions. */ 960 /* x86 has several different calling conventions. */
948 cc->resx87 = 0; 961 cc->resx87 = 0;
949 switch (ctype_cconv(ct->info)) { 962 switch (ctype_cconv(info)) {
950 case CTCC_FASTCALL: maxgpr = 2; break; 963 case CTCC_FASTCALL: maxgpr = 2; break;
951 case CTCC_THISCALL: maxgpr = 1; break; 964 case CTCC_THISCALL: maxgpr = 1; break;
952 default: maxgpr = 0; break; 965 default: maxgpr = 0; break;
@@ -963,7 +976,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
963 } else if (ctype_iscomplex(ctr->info) || ctype_isstruct(ctr->info)) { 976 } else if (ctype_iscomplex(ctr->info) || ctype_isstruct(ctr->info)) {
964 /* Preallocate cdata object and anchor it after arguments. */ 977 /* Preallocate cdata object and anchor it after arguments. */
965 CTSize sz = ctr->size; 978 CTSize sz = ctr->size;
966 GCcdata *cd = lj_cdata_new(cts, ctype_cid(ct->info), sz); 979 GCcdata *cd = lj_cdata_new(cts, ctype_cid(info), sz);
967 void *dp = cdataptr(cd); 980 void *dp = cdataptr(cd);
968 setcdataV(L, L->top++, cd); 981 setcdataV(L, L->top++, cd);
969 if (ctype_isstruct(ctr->info)) { 982 if (ctype_isstruct(ctr->info)) {
@@ -986,7 +999,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
986 } 999 }
987 1000
988#if LJ_TARGET_ARM64 && LJ_ABI_WIN 1001#if LJ_TARGET_ARM64 && LJ_ABI_WIN
989 if ((ct->info & CTF_VARARG)) { 1002 if ((info & CTF_VARARG)) {
990 nsp -= maxgpr * CTSIZE_PTR; /* May end up with negative nsp. */ 1003 nsp -= maxgpr * CTSIZE_PTR; /* May end up with negative nsp. */
991 ngpr = maxgpr; 1004 ngpr = maxgpr;
992 nfpr = CCALL_NARG_FPR; 1005 nfpr = CCALL_NARG_FPR;
@@ -1007,7 +1020,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
1007 lj_assertL(ctype_isfield(ctf->info), "field expected"); 1020 lj_assertL(ctype_isfield(ctf->info), "field expected");
1008 did = ctype_cid(ctf->info); 1021 did = ctype_cid(ctf->info);
1009 } else { 1022 } else {
1010 if (!(ct->info & CTF_VARARG)) 1023 if (!(info & CTF_VARARG))
1011 lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too many arguments. */ 1024 lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too many arguments. */
1012 did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */ 1025 did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */
1013 isva = 1; 1026 isva = 1;
@@ -1178,11 +1191,11 @@ int lj_ccall_func(lua_State *L, GCcdata *cd)
1178 ct = ctype_rawchild(cts, ct); 1191 ct = ctype_rawchild(cts, ct);
1179 } 1192 }
1180 if (ctype_isfunc(ct->info)) { 1193 if (ctype_isfunc(ct->info)) {
1194 CTypeID id = ctype_typeid(cts, ct);
1181 CCallState cc; 1195 CCallState cc;
1182 int gcsteps, ret; 1196 int gcsteps, ret;
1183 cc.func = (void (*)(void))cdata_getptr(cdataptr(cd), sz); 1197 cc.func = (void (*)(void))cdata_getptr(cdataptr(cd), sz);
1184 gcsteps = ccall_set_args(L, cts, ct, &cc); 1198 gcsteps = ccall_set_args(L, cts, ct, &cc);
1185 ct = (CType *)((intptr_t)ct-(intptr_t)cts->tab);
1186 cts->cb.slot = ~0u; 1199 cts->cb.slot = ~0u;
1187 lj_vm_ffi_call(&cc); 1200 lj_vm_ffi_call(&cc);
1188 if (cts->cb.slot != ~0u) { /* Blacklist function that called a callback. */ 1201 if (cts->cb.slot != ~0u) { /* Blacklist function that called a callback. */
@@ -1190,7 +1203,7 @@ int lj_ccall_func(lua_State *L, GCcdata *cd)
1190 tv.u64 = ((uintptr_t)(void *)cc.func >> 2) | U64x(800000000, 00000000); 1203 tv.u64 = ((uintptr_t)(void *)cc.func >> 2) | U64x(800000000, 00000000);
1191 setboolV(lj_tab_set(L, cts->miscmap, &tv), 1); 1204 setboolV(lj_tab_set(L, cts->miscmap, &tv), 1);
1192 } 1205 }
1193 ct = (CType *)((intptr_t)ct+(intptr_t)cts->tab); /* May be reallocated. */ 1206 ct = ctype_get(cts, id); /* Table may have been reallocated. */
1194 gcsteps += ccall_get_results(L, cts, ct, &cc, &ret); 1207 gcsteps += ccall_get_results(L, cts, ct, &cc, &ret);
1195#if LJ_TARGET_X86 && LJ_ABI_WIN 1208#if LJ_TARGET_X86 && LJ_ABI_WIN
1196 /* Automatically detect __stdcall and fix up C function declaration. */ 1209 /* Automatically detect __stdcall and fix up C function declaration. */