aboutsummaryrefslogtreecommitdiff
path: root/src/lib_ffi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib_ffi.c')
-rw-r--r--src/lib_ffi.c109
1 files changed, 59 insertions, 50 deletions
diff --git a/src/lib_ffi.c b/src/lib_ffi.c
index 8c5c03fb..7b83ef25 100644
--- a/src/lib_ffi.c
+++ b/src/lib_ffi.c
@@ -29,6 +29,7 @@
29#include "lj_ccall.h" 29#include "lj_ccall.h"
30#include "lj_ccallback.h" 30#include "lj_ccallback.h"
31#include "lj_clib.h" 31#include "lj_clib.h"
32#include "lj_strfmt.h"
32#include "lj_ff.h" 33#include "lj_ff.h"
33#include "lj_lib.h" 34#include "lj_lib.h"
34 35
@@ -137,7 +138,7 @@ static int ffi_index_meta(lua_State *L, CTState *cts, CType *ct, MMS mm)
137 } 138 }
138 } 139 }
139 copyTV(L, base, L->top); 140 copyTV(L, base, L->top);
140 tv = L->top-1; 141 tv = L->top-1-LJ_FR2;
141 } 142 }
142 return lj_meta_tailcall(L, tv); 143 return lj_meta_tailcall(L, tv);
143} 144}
@@ -318,7 +319,7 @@ LJLIB_CF(ffi_meta___tostring)
318 } 319 }
319 } 320 }
320 } 321 }
321 lj_str_pushf(L, msg, strdata(lj_ctype_repr(L, id, NULL)), p); 322 lj_strfmt_pushf(L, msg, strdata(lj_ctype_repr(L, id, NULL)), p);
322checkgc: 323checkgc:
323 lj_gc_check(L); 324 lj_gc_check(L);
324 return 1; 325 return 1;
@@ -504,10 +505,7 @@ LJLIB_CF(ffi_new) LJLIB_REC(.)
504 } 505 }
505 if (sz == CTSIZE_INVALID) 506 if (sz == CTSIZE_INVALID)
506 lj_err_arg(L, 1, LJ_ERR_FFI_INVSIZE); 507 lj_err_arg(L, 1, LJ_ERR_FFI_INVSIZE);
507 if (!(info & CTF_VLA) && ctype_align(info) <= CT_MEMALIGN) 508 cd = lj_cdata_newx(cts, id, sz, info);
508 cd = lj_cdata_new(cts, id, sz);
509 else
510 cd = lj_cdata_newv(cts, id, sz, ctype_align(info));
511 setcdataV(L, o-1, cd); /* Anchor the uninitialized cdata. */ 509 setcdataV(L, o-1, cd); /* Anchor the uninitialized cdata. */
512 lj_cconv_ct_init(cts, ct, sz, cdataptr(cd), 510 lj_cconv_ct_init(cts, ct, sz, cdataptr(cd),
513 o, (MSize)(L->top - o)); /* Initialize cdata. */ 511 o, (MSize)(L->top - o)); /* Initialize cdata. */
@@ -515,7 +513,7 @@ LJLIB_CF(ffi_new) LJLIB_REC(.)
515 /* Handle ctype __gc metamethod. Use the fast lookup here. */ 513 /* Handle ctype __gc metamethod. Use the fast lookup here. */
516 cTValue *tv = lj_tab_getinth(cts->miscmap, -(int32_t)id); 514 cTValue *tv = lj_tab_getinth(cts->miscmap, -(int32_t)id);
517 if (tv && tvistab(tv) && (tv = lj_meta_fast(L, tabV(tv), MM_gc))) { 515 if (tv && tvistab(tv) && (tv = lj_meta_fast(L, tabV(tv), MM_gc))) {
518 GCtab *t = cts->finalizer; 516 GCtab *t = tabref(G(L)->gcroot[GCROOT_FFI_FIN]);
519 if (gcref(t->metatable)) { 517 if (gcref(t->metatable)) {
520 /* Add to finalizer table, if still enabled. */ 518 /* Add to finalizer table, if still enabled. */
521 copyTV(L, lj_tab_set(L, t, o-1), tv); 519 copyTV(L, lj_tab_set(L, t, o-1), tv);
@@ -558,6 +556,32 @@ LJLIB_CF(ffi_typeof) LJLIB_REC(.)
558 return 1; 556 return 1;
559} 557}
560 558
559/* Internal and unsupported API. */
560LJLIB_CF(ffi_typeinfo)
561{
562 CTState *cts = ctype_cts(L);
563 CTypeID id = (CTypeID)ffi_checkint(L, 1);
564 if (id > 0 && id < cts->top) {
565 CType *ct = ctype_get(cts, id);
566 GCtab *t;
567 lua_createtable(L, 0, 4); /* Increment hash size if fields are added. */
568 t = tabV(L->top-1);
569 setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "info")), (int32_t)ct->info);
570 if (ct->size != CTSIZE_INVALID)
571 setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "size")), (int32_t)ct->size);
572 if (ct->sib)
573 setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "sib")), (int32_t)ct->sib);
574 if (gcref(ct->name)) {
575 GCstr *s = gco2str(gcref(ct->name));
576 if (isdead(G(L), obj2gco(s))) flipwhite(obj2gco(s));
577 setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "name")), s);
578 }
579 lj_gc_check(L);
580 return 1;
581 }
582 return 0;
583}
584
561LJLIB_CF(ffi_istype) LJLIB_REC(.) 585LJLIB_CF(ffi_istype) LJLIB_REC(.)
562{ 586{
563 CTState *cts = ctype_cts(L); 587 CTState *cts = ctype_cts(L);
@@ -697,45 +721,54 @@ LJLIB_CF(ffi_fill) LJLIB_REC(.)
697 return 0; 721 return 0;
698} 722}
699 723
700#define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be)
701
702/* Test ABI string. */ 724/* Test ABI string. */
703LJLIB_CF(ffi_abi) LJLIB_REC(.) 725LJLIB_CF(ffi_abi) LJLIB_REC(.)
704{ 726{
705 GCstr *s = lj_lib_checkstr(L, 1); 727 GCstr *s = lj_lib_checkstr(L, 1);
706 int b = 0; 728 int b = lj_cparse_case(s,
707 switch (s->hash) {
708#if LJ_64 729#if LJ_64
709 case H_(849858eb,ad35fd06): b = 1; break; /* 64bit */ 730 "\00564bit"
710#else 731#else
711 case H_(662d3c79,d0e22477): b = 1; break; /* 32bit */ 732 "\00532bit"
712#endif 733#endif
713#if LJ_ARCH_HASFPU 734#if LJ_ARCH_HASFPU
714 case H_(e33ee463,e33ee463): b = 1; break; /* fpu */ 735 "\003fpu"
715#endif 736#endif
716#if LJ_ABI_SOFTFP 737#if LJ_ABI_SOFTFP
717 case H_(61211a23,c2e8c81c): b = 1; break; /* softfp */ 738 "\006softfp"
718#else 739#else
719 case H_(539417a8,8ce0812f): b = 1; break; /* hardfp */ 740 "\006hardfp"
720#endif 741#endif
721#if LJ_ABI_EABI 742#if LJ_ABI_EABI
722 case H_(2182df8f,f2ed1152): b = 1; break; /* eabi */ 743 "\004eabi"
723#endif 744#endif
724#if LJ_ABI_WIN 745#if LJ_ABI_WIN
725 case H_(4ab624a8,4ab624a8): b = 1; break; /* win */ 746 "\003win"
726#endif 747#endif
727 case H_(3af93066,1f001464): b = 1; break; /* le/be */ 748#if LJ_ABI_PAUTH
728 default: 749 "\005pauth"
729 break; 750#endif
730 } 751#if LJ_TARGET_UWP
752 "\003uwp"
753#endif
754#if LJ_LE
755 "\002le"
756#else
757 "\002be"
758#endif
759#if LJ_GC64
760 "\004gc64"
761#endif
762#if LJ_DUALNUM
763 "\007dualnum"
764#endif
765 ) >= 0;
731 setboolV(L->top-1, b); 766 setboolV(L->top-1, b);
732 setboolV(&G(L)->tmptv2, b); /* Remember for trace recorder. */ 767 setboolV(&G(L)->tmptv2, b); /* Remember for trace recorder. */
733 return 1; 768 return 1;
734} 769}
735 770
736#undef H_ 771LJLIB_PUSH(top-7) LJLIB_SET(!) /* Store reference to miscmap table. */
737
738LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to miscmap table. */
739 772
740LJLIB_CF(ffi_metatype) 773LJLIB_CF(ffi_metatype)
741{ 774{
@@ -761,26 +794,16 @@ LJLIB_CF(ffi_metatype)
761 return 1; 794 return 1;
762} 795}
763 796
764LJLIB_PUSH(top-7) LJLIB_SET(!) /* Store reference to finalizer table. */
765
766LJLIB_CF(ffi_gc) LJLIB_REC(.) 797LJLIB_CF(ffi_gc) LJLIB_REC(.)
767{ 798{
768 GCcdata *cd = ffi_checkcdata(L, 1); 799 GCcdata *cd = ffi_checkcdata(L, 1);
769 TValue *fin = lj_lib_checkany(L, 2); 800 TValue *fin = lj_lib_checkany(L, 2);
770 CTState *cts = ctype_cts(L); 801 CTState *cts = ctype_cts(L);
771 GCtab *t = cts->finalizer;
772 CType *ct = ctype_raw(cts, cd->ctypeid); 802 CType *ct = ctype_raw(cts, cd->ctypeid);
773 if (!(ctype_isptr(ct->info) || ctype_isstruct(ct->info) || 803 if (!(ctype_isptr(ct->info) || ctype_isstruct(ct->info) ||
774 ctype_isrefarray(ct->info))) 804 ctype_isrefarray(ct->info)))
775 lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); 805 lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE);
776 if (gcref(t->metatable)) { /* Update finalizer table, if still enabled. */ 806 lj_cdata_setfin(L, cd, gcval(fin), itype(fin));
777 copyTV(L, lj_tab_set(L, t, L->base), fin);
778 lj_gc_anybarriert(L, t);
779 if (!tvisnil(fin))
780 cd->marked |= LJ_GC_CDATA_FIN;
781 else
782 cd->marked &= ~LJ_GC_CDATA_FIN;
783 }
784 L->top = L->base+1; /* Pass through the cdata object. */ 807 L->top = L->base+1; /* Pass through the cdata object. */
785 return 1; 808 return 1;
786} 809}
@@ -803,19 +826,6 @@ LJLIB_PUSH(top-2) LJLIB_SET(arch)
803 826
804/* ------------------------------------------------------------------------ */ 827/* ------------------------------------------------------------------------ */
805 828
806/* Create special weak-keyed finalizer table. */
807static GCtab *ffi_finalizer(lua_State *L)
808{
809 /* NOBARRIER: The table is new (marked white). */
810 GCtab *t = lj_tab_new(L, 0, 1);
811 settabV(L, L->top++, t);
812 setgcref(t->metatable, obj2gco(t));
813 setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")),
814 lj_str_newlit(L, "k"));
815 t->nomm = (uint8_t)(~(1u<<MM_mode));
816 return t;
817}
818
819/* Register FFI module as loaded. */ 829/* Register FFI module as loaded. */
820static void ffi_register_module(lua_State *L) 830static void ffi_register_module(lua_State *L)
821{ 831{
@@ -831,7 +841,6 @@ LUALIB_API int luaopen_ffi(lua_State *L)
831{ 841{
832 CTState *cts = lj_ctype_init(L); 842 CTState *cts = lj_ctype_init(L);
833 settabV(L, L->top++, (cts->miscmap = lj_tab_new(L, 0, 1))); 843 settabV(L, L->top++, (cts->miscmap = lj_tab_new(L, 0, 1)));
834 cts->finalizer = ffi_finalizer(L);
835 LJ_LIB_REG(L, NULL, ffi_meta); 844 LJ_LIB_REG(L, NULL, ffi_meta);
836 /* NOBARRIER: basemt is a GC root. */ 845 /* NOBARRIER: basemt is a GC root. */
837 setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1))); 846 setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1)));