3 ** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
25 #include "lj_cparse.h"
28 #include "lj_carith.h"
34 /* -- C type checks ------------------------------------------------------- */
36 /* Check first argument for a C type and returns its ID. */
37 static CTypeID
ffi_checkctype(lua_State
*L
, CTState
*cts
)
42 lj_err_argtype(L
, 1, "C type");
44 if (tvisstr(o
)) { /* Parse an abstract C type declaration. */
50 cp
.srcname
= strdata(s
);
52 cp
.mode
= CPARSE_MODE_ABSTRACT
|CPARSE_MODE_NOIMPLICIT
;
53 errcode
= lj_cparse(&cp
);
54 if (errcode
) lj_err_throw(L
, errcode
); /* Propagate errors. */
58 if (!tviscdata(o
)) goto err_argtype
;
60 return cd
->typeid == CTID_CTYPEID
? *(CTypeID
*)cdataptr(cd
) : cd
->typeid;
64 /* Check argument for C data and return it. */
65 static GCcdata
*ffi_checkcdata(lua_State
*L
, int narg
)
67 TValue
*o
= L
->base
+ narg
-1;
68 if (!(o
< L
->top
&& tviscdata(o
)))
69 lj_err_argt(L
, narg
, LUA_TCDATA
);
73 /* Convert argument to C pointer. */
74 static void *ffi_checkptr(lua_State
*L
, int narg
, CTypeID id
)
76 CTState
*cts
= ctype_cts(L
);
77 TValue
*o
= L
->base
+ narg
-1;
80 lj_err_arg(L
, narg
, LJ_ERR_NOVAL
);
81 lj_cconv_ct_tv(cts
, ctype_get(cts
, id
), (uint8_t *)&p
, o
, CCF_ARG(narg
));
85 /* Convert argument to int32_t. */
86 static int32_t ffi_checkint(lua_State
*L
, int narg
)
88 CTState
*cts
= ctype_cts(L
);
89 TValue
*o
= L
->base
+ narg
-1;
92 lj_err_arg(L
, narg
, LJ_ERR_NOVAL
);
93 lj_cconv_ct_tv(cts
, ctype_get(cts
, CTID_INT32
), (uint8_t *)&i
, o
,
98 /* -- C type metamethods -------------------------------------------------- */
100 #define LJLIB_MODULE_ffi_meta
102 /* Handle ctype __index/__newindex metamethods. */
103 static int ffi_index_meta(lua_State
*L
, CTState
*cts
, CType
*ct
, MMS mm
)
105 CTypeID id
= ctype_typeid(cts
, ct
);
106 cTValue
*tv
= lj_ctype_meta(cts
, id
, mm
);
107 TValue
*base
= L
->base
;
111 s
= strdata(lj_ctype_repr(L
, id
, NULL
));
112 if (tvisstr(L
->base
+1))
113 lj_err_callerv(L
, LJ_ERR_FFI_BADMEMBER
, s
, strVdata(L
->base
+1));
115 lj_err_callerv(L
, LJ_ERR_FFI_BADIDX
, s
);
118 if (mm
== MM_index
) {
119 cTValue
*o
= lj_meta_tget(L
, tv
, base
+1);
121 if (tvisnil(o
)) goto err_index
;
122 copyTV(L
, L
->top
-1, o
);
126 TValue
*o
= lj_meta_tset(L
, tv
, base
+1);
128 copyTV(L
, o
, base
+2);
134 return lj_meta_tailcall(L
, tv
);
137 LJLIB_CF(ffi_meta___index
) LJLIB_REC(cdata_index
0)
139 CTState
*cts
= ctype_cts(L
);
144 if (!(o
+1 < L
->top
&& tviscdata(o
))) /* Also checks for presence of key. */
145 lj_err_argt(L
, 1, LUA_TCDATA
);
146 ct
= lj_cdata_index(cts
, cdataV(o
), o
+1, &p
, &qual
);
148 return ffi_index_meta(L
, cts
, ct
, MM_index
);
149 if (lj_cdata_get(cts
, ct
, L
->top
-1, p
))
154 LJLIB_CF(ffi_meta___newindex
) LJLIB_REC(cdata_index
1)
156 CTState
*cts
= ctype_cts(L
);
161 if (!(o
+2 < L
->top
&& tviscdata(o
))) /* Also checks for key and value. */
162 lj_err_argt(L
, 1, LUA_TCDATA
);
163 ct
= lj_cdata_index(cts
, cdataV(o
), o
+1, &p
, &qual
);
165 if ((qual
& CTF_CONST
))
166 lj_err_caller(L
, LJ_ERR_FFI_WRCONST
);
167 return ffi_index_meta(L
, cts
, ct
, MM_newindex
);
169 lj_cdata_set(cts
, ct
, p
, o
+2, qual
);
173 /* Common handler for cdata arithmetic. */
174 static int ffi_arith(lua_State
*L
)
176 MMS mm
= (MMS
)(curr_func(L
)->c
.ffid
- (int)FF_ffi_meta___eq
+ (int)MM_eq
);
177 return lj_carith_op(L
, mm
);
180 /* The following functions must be in contiguous ORDER MM. */
181 LJLIB_CF(ffi_meta___eq
) LJLIB_REC(cdata_arith MM_eq
)
186 LJLIB_CF(ffi_meta___len
) LJLIB_REC(cdata_arith MM_len
)
191 LJLIB_CF(ffi_meta___lt
) LJLIB_REC(cdata_arith MM_lt
)
196 LJLIB_CF(ffi_meta___le
) LJLIB_REC(cdata_arith MM_le
)
201 LJLIB_CF(ffi_meta___concat
) LJLIB_REC(cdata_arith MM_concat
)
206 /* Handle ctype __call metamethod. */
207 static int ffi_call_meta(lua_State
*L
, CTypeID id
)
209 CTState
*cts
= ctype_cts(L
);
210 CType
*ct
= ctype_raw(cts
, id
);
212 if (ctype_isptr(ct
->info
)) id
= ctype_cid(ct
->info
);
213 tv
= lj_ctype_meta(cts
, id
, MM_call
);
215 lj_err_callerv(L
, LJ_ERR_FFI_BADCALL
, strdata(lj_ctype_repr(L
, id
, NULL
)));
216 return lj_meta_tailcall(L
, tv
);
219 /* Forward declaration. */
220 static int lj_cf_ffi_new(lua_State
*L
);
222 LJLIB_CF(ffi_meta___call
) LJLIB_REC(cdata_call
)
224 GCcdata
*cd
= ffi_checkcdata(L
, 1);
226 if (cd
->typeid == CTID_CTYPEID
)
227 return lj_cf_ffi_new(L
);
228 if ((ret
= lj_ccall_func(L
, cd
)) < 0)
229 return ffi_call_meta(L
, cd
->typeid);
233 LJLIB_CF(ffi_meta___add
) LJLIB_REC(cdata_arith MM_add
)
238 LJLIB_CF(ffi_meta___sub
) LJLIB_REC(cdata_arith MM_sub
)
243 LJLIB_CF(ffi_meta___mul
) LJLIB_REC(cdata_arith MM_mul
)
248 LJLIB_CF(ffi_meta___div
) LJLIB_REC(cdata_arith MM_div
)
253 LJLIB_CF(ffi_meta___mod
) LJLIB_REC(cdata_arith MM_mod
)
258 LJLIB_CF(ffi_meta___pow
) LJLIB_REC(cdata_arith MM_pow
)
263 LJLIB_CF(ffi_meta___unm
) LJLIB_REC(cdata_arith MM_unm
)
267 /* End of contiguous ORDER MM. */
269 LJLIB_CF(ffi_meta___tostring
)
271 GCcdata
*cd
= ffi_checkcdata(L
, 1);
272 const char *msg
= "cdata<%s>: %p";
273 CTypeID id
= cd
->typeid;
274 void *p
= cdataptr(cd
);
275 if (id
== CTID_CTYPEID
) {
279 CTState
*cts
= ctype_cts(L
);
280 CType
*ct
= ctype_raw(cts
, id
);
281 if (ctype_isref(ct
->info
)) ct
= ctype_rawchild(cts
, ct
);
282 if (ctype_iscomplex(ct
->info
)) {
283 setstrV(L
, L
->top
-1, lj_ctype_repr_complex(L
, cdataptr(cd
), ct
->size
));
285 } else if (ct
->size
== 8 && ctype_isinteger(ct
->info
)) {
286 setstrV(L
, L
->top
-1, lj_ctype_repr_int64(L
, *(uint64_t *)cdataptr(cd
),
287 (ct
->info
& CTF_UNSIGNED
)));
289 } else if (ctype_isfunc(ct
->info
)) {
292 if (ctype_isptr(ct
->info
)) {
293 p
= cdata_getptr(p
, ct
->size
);
294 ct
= ctype_rawchild(cts
, ct
);
296 if (ctype_isstruct(ct
->info
) || ctype_isvector(ct
->info
)) {
297 /* Handle ctype __tostring metamethod. */
298 cTValue
*tv
= lj_ctype_meta(cts
, ctype_typeid(cts
, ct
), MM_tostring
);
300 return lj_meta_tailcall(L
, tv
);
304 lj_str_pushf(L
, msg
, strdata(lj_ctype_repr(L
, id
, NULL
)), p
);
310 LJLIB_PUSH("ffi") LJLIB_SET(__metatable
)
312 #include "lj_libdef.h"
314 /* -- C library metamethods ----------------------------------------------- */
316 #define LJLIB_MODULE_ffi_clib
318 /* Index C library by a name. */
319 static TValue
*ffi_clib_index(lua_State
*L
)
323 if (!(o
< L
->top
&& tvisudata(o
) && udataV(o
)->udtype
== UDTYPE_FFI_CLIB
))
324 lj_err_argt(L
, 1, LUA_TUSERDATA
);
325 cl
= (CLibrary
*)uddata(udataV(o
));
326 if (!(o
+1 < L
->top
&& tvisstr(o
+1)))
327 lj_err_argt(L
, 2, LUA_TSTRING
);
328 return lj_clib_index(L
, cl
, strV(o
+1));
331 LJLIB_CF(ffi_clib___index
) LJLIB_REC(clib_index
1)
333 TValue
*tv
= ffi_clib_index(L
);
335 CTState
*cts
= ctype_cts(L
);
336 GCcdata
*cd
= cdataV(tv
);
337 CType
*s
= ctype_get(cts
, cd
->typeid);
338 if (ctype_isextern(s
->info
)) {
339 CTypeID sid
= ctype_cid(s
->info
);
340 void *sp
= *(void **)cdataptr(cd
);
341 CType
*ct
= ctype_raw(cts
, sid
);
342 if (ctype_isenum(ct
->info
)) ct
= ctype_child(cts
, ct
);
343 if (lj_cconv_tv_ct(cts
, ct
, sid
, L
->top
-1, sp
))
348 copyTV(L
, L
->top
-1, tv
);
352 LJLIB_CF(ffi_clib___newindex
) LJLIB_REC(clib_index
0)
354 TValue
*tv
= ffi_clib_index(L
);
355 TValue
*o
= L
->base
+2;
356 if (o
< L
->top
&& tviscdata(tv
)) {
357 CTState
*cts
= ctype_cts(L
);
358 GCcdata
*cd
= cdataV(tv
);
359 CType
*d
= ctype_get(cts
, cd
->typeid);
360 if (ctype_isextern(d
->info
)) {
362 for (;;) { /* Skip attributes and collect qualifiers. */
363 d
= ctype_child(cts
, d
);
364 if (!ctype_isattrib(d
->info
)) break;
365 if (ctype_attrib(d
->info
) == CTA_QUAL
) qual
|= d
->size
;
367 if (!((d
->info
|qual
) & CTF_CONST
)) {
368 lj_cconv_ct_tv(cts
, d
, *(void **)cdataptr(cd
), o
, 0);
373 lj_err_caller(L
, LJ_ERR_FFI_WRCONST
);
374 return 0; /* unreachable */
377 LJLIB_CF(ffi_clib___gc
)
380 if (o
< L
->top
&& tvisudata(o
) && udataV(o
)->udtype
== UDTYPE_FFI_CLIB
)
381 lj_clib_unload((CLibrary
*)uddata(udataV(o
)));
385 #include "lj_libdef.h"
387 /* -- FFI library functions ----------------------------------------------- */
389 #define LJLIB_MODULE_ffi
393 GCstr
*s
= lj_lib_checkstr(L
, 1);
397 cp
.cts
= ctype_cts(L
);
398 cp
.srcname
= strdata(s
);
400 cp
.mode
= CPARSE_MODE_MULTI
|CPARSE_MODE_DIRECT
;
401 errcode
= lj_cparse(&cp
);
402 if (errcode
) lj_err_throw(L
, errcode
); /* Propagate errors. */
407 LJLIB_CF(ffi_new
) LJLIB_REC(.)
409 CTState
*cts
= ctype_cts(L
);
410 CTypeID id
= ffi_checkctype(L
, cts
);
411 CType
*ct
= ctype_raw(cts
, id
);
413 CTInfo info
= lj_ctype_info(cts
, id
, &sz
);
414 TValue
*o
= L
->base
+1;
416 if ((info
& CTF_VLA
)) {
418 sz
= lj_ctype_vlsize(cts
, ct
, (CTSize
)ffi_checkint(L
, 2));
420 if (sz
== CTSIZE_INVALID
)
421 lj_err_arg(L
, 1, LJ_ERR_FFI_INVSIZE
);
422 if (!(info
& CTF_VLA
) && ctype_align(info
) <= CT_MEMALIGN
)
423 cd
= lj_cdata_new(cts
, id
, sz
);
425 cd
= lj_cdata_newv(cts
, id
, sz
, ctype_align(info
));
426 setcdataV(L
, o
-1, cd
); /* Anchor the uninitialized cdata. */
427 lj_cconv_ct_init(cts
, ct
, sz
, cdataptr(cd
),
428 o
, (MSize
)(L
->top
- o
)); /* Initialize cdata. */
429 if (ctype_isstruct(ct
->info
)) {
430 /* Handle ctype __gc metamethod. Use the fast lookup here. */
431 cTValue
*tv
= lj_tab_getint(cts
->metatype
, (int32_t)id
);
432 if (tv
&& tvistab(tv
) && (tv
= lj_meta_fast(L
, tabV(tv
), MM_gc
))) {
433 GCtab
*t
= cts
->finalizer
;
434 if (gcref(t
->metatable
)) {
435 /* Add to finalizer table, if still enabled. */
436 copyTV(L
, lj_tab_set(L
, t
, o
-1), tv
);
437 lj_gc_anybarriert(L
, t
);
438 cd
->marked
|= LJ_GC_CDATA_FIN
;
442 L
->top
= o
; /* Only return the cdata itself. */
447 LJLIB_CF(ffi_cast
) LJLIB_REC(ffi_new
)
449 CTState
*cts
= ctype_cts(L
);
450 CTypeID id
= ffi_checkctype(L
, cts
);
451 CType
*d
= ctype_raw(cts
, id
);
452 TValue
*o
= lj_lib_checkany(L
, 2);
453 L
->top
= o
+1; /* Make sure this is the last item on the stack. */
454 if (!(ctype_isnum(d
->info
) || ctype_isptr(d
->info
) || ctype_isenum(d
->info
)))
455 lj_err_arg(L
, 1, LJ_ERR_FFI_INVTYPE
);
456 if (!(tviscdata(o
) && cdataV(o
)->typeid == id
)) {
457 GCcdata
*cd
= lj_cdata_new(cts
, id
, d
->size
);
458 lj_cconv_ct_tv(cts
, d
, cdataptr(cd
), o
, CCF_CAST
);
467 CTState
*cts
= ctype_cts(L
);
468 CTypeID id
= ffi_checkctype(L
, cts
);
469 GCcdata
*cd
= lj_cdata_new(cts
, CTID_CTYPEID
, 4);
470 *(CTypeID
*)cdataptr(cd
) = id
;
471 setcdataV(L
, L
->top
-1, cd
);
476 LJLIB_CF(ffi_istype
) LJLIB_REC(ffi_istype
)
478 CTState
*cts
= ctype_cts(L
);
479 CTypeID id1
= ffi_checkctype(L
, cts
);
480 TValue
*o
= lj_lib_checkany(L
, 2);
483 GCcdata
*cd
= cdataV(o
);
484 CTypeID id2
= cd
->typeid == CTID_CTYPEID
? *(CTypeID
*)cdataptr(cd
) :
486 CType
*ct1
= lj_ctype_rawref(cts
, id1
);
487 CType
*ct2
= lj_ctype_rawref(cts
, id2
);
490 } else if (ctype_type(ct1
->info
) == ctype_type(ct2
->info
) &&
491 ct1
->size
== ct2
->size
) {
492 if (ctype_ispointer(ct1
->info
))
493 b
= lj_cconv_compatptr(cts
, ct1
, ct2
, CCF_IGNQUAL
);
494 else if (ctype_isnum(ct1
->info
) || ctype_isvoid(ct1
->info
))
495 b
= (((ct1
->info
^ ct2
->info
) & ~CTF_QUAL
) == 0);
496 } else if (ctype_isstruct(ct1
->info
) && ctype_isptr(ct2
->info
) &&
497 ct1
== ctype_rawchild(cts
, ct2
)) {
501 setboolV(L
->top
-1, b
);
502 setboolV(&G(L
)->tmptv2
, b
); /* Remember for trace recorder. */
508 CTState
*cts
= ctype_cts(L
);
509 CTypeID id
= ffi_checkctype(L
, cts
);
511 if (LJ_UNLIKELY(tviscdata(L
->base
) && cdataisv(cdataV(L
->base
)))) {
512 sz
= cdatavlen(cdataV(L
->base
));
514 CType
*ct
= lj_ctype_rawref(cts
, id
);
515 if (ctype_isvltype(ct
->info
))
516 sz
= lj_ctype_vlsize(cts
, ct
, (CTSize
)ffi_checkint(L
, 2));
518 sz
= ctype_hassize(ct
->info
) ? ct
->size
: CTSIZE_INVALID
;
519 if (LJ_UNLIKELY(sz
== CTSIZE_INVALID
)) {
524 setintV(L
->top
-1, (int32_t)sz
);
528 LJLIB_CF(ffi_alignof
)
530 CTState
*cts
= ctype_cts(L
);
531 CTypeID id
= ffi_checkctype(L
, cts
);
533 CTInfo info
= lj_ctype_info(cts
, id
, &sz
);
534 setintV(L
->top
-1, 1 << ctype_align(info
));
538 LJLIB_CF(ffi_offsetof
)
540 CTState
*cts
= ctype_cts(L
);
541 CTypeID id
= ffi_checkctype(L
, cts
);
542 GCstr
*name
= lj_lib_checkstr(L
, 2);
543 CType
*ct
= lj_ctype_rawref(cts
, id
);
545 if (ctype_isstruct(ct
->info
) && ct
->size
!= CTSIZE_INVALID
) {
546 CType
*fct
= lj_ctype_getfield(cts
, ct
, name
, &ofs
);
548 setintV(L
->top
-1, ofs
);
549 if (ctype_isfield(fct
->info
)) {
551 } else if (ctype_isbitfield(fct
->info
)) {
552 setintV(L
->top
++, ctype_bitpos(fct
->info
));
553 setintV(L
->top
++, ctype_bitbsz(fct
->info
));
564 if (L
->top
> L
->base
)
565 errno
= ffi_checkint(L
, 1);
566 setintV(L
->top
++, err
);
570 LJLIB_CF(ffi_string
) LJLIB_REC(.)
572 CTState
*cts
= ctype_cts(L
);
573 TValue
*o
= lj_lib_checkany(L
, 1);
577 len
= (size_t)ffi_checkint(L
, 2);
578 lj_cconv_ct_tv(cts
, ctype_get(cts
, CTID_P_CVOID
), (uint8_t *)&p
, o
,
581 lj_cconv_ct_tv(cts
, ctype_get(cts
, CTID_P_CCHAR
), (uint8_t *)&p
, o
,
585 L
->top
= o
+1; /* Make sure this is the last item on the stack. */
586 setstrV(L
, o
, lj_str_new(L
, p
, len
));
591 LJLIB_CF(ffi_copy
) LJLIB_REC(.)
593 void *dp
= ffi_checkptr(L
, 1, CTID_P_VOID
);
594 void *sp
= ffi_checkptr(L
, 2, CTID_P_CVOID
);
595 TValue
*o
= L
->base
+1;
597 if (tvisstr(o
) && o
+1 >= L
->top
)
598 len
= strV(o
)->len
+1; /* Copy Lua string including trailing '\0'. */
600 len
= (CTSize
)ffi_checkint(L
, 3);
605 LJLIB_CF(ffi_fill
) LJLIB_REC(.)
607 void *dp
= ffi_checkptr(L
, 1, CTID_P_VOID
);
608 CTSize len
= (CTSize
)ffi_checkint(L
, 2);
610 if (L
->base
+2 < L
->top
&& !tvisnil(L
->base
+2)) fill
= ffi_checkint(L
, 3);
611 memset(dp
, fill
, len
);
615 #define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be)
617 /* Test ABI string. */
618 LJLIB_CF(ffi_abi
) LJLIB_REC(.)
620 GCstr
*s
= lj_lib_checkstr(L
, 1);
624 case H_(849858eb
,ad35fd06
): b
= 1; break; /* 64bit */
626 case H_(662d3c79
,d0e22477
): b
= 1; break; /* 32bit */
629 case H_(e33ee463
,e33ee463
): b
= 1; break; /* fpu */
632 case H_(61211a23
,c2e8c81c
): b
= 1; break; /* softfp */
634 case H_(539417a8
,8ce0812f
): b
= 1; break; /* hardfp */
637 case H_(2182df8f
,f2ed1152
): b
= 1; break; /* eabi */
640 case H_(4ab624a8
,4ab624a8
): b
= 1; break; /* win */
642 case H_(3af93066
,1f001464
): b
= 1; break; /* le/be */
646 setboolV(L
->top
-1, b
);
647 setboolV(&G(L
)->tmptv2
, b
); /* Remember for trace recorder. */
653 LJLIB_PUSH(top
-8) LJLIB_SET(!) /* Store reference to metatype table. */
655 LJLIB_CF(ffi_metatype
)
657 CTState
*cts
= ctype_cts(L
);
658 CTypeID id
= ffi_checkctype(L
, cts
);
659 GCtab
*mt
= lj_lib_checktab(L
, 2);
660 GCtab
*t
= cts
->metatype
;
661 CType
*ct
= ctype_get(cts
, id
); /* Only allow raw types. */
664 if (!(ctype_isstruct(ct
->info
) || ctype_iscomplex(ct
->info
) ||
665 ctype_isvector(ct
->info
)))
666 lj_err_arg(L
, 1, LJ_ERR_FFI_INVTYPE
);
667 tv
= lj_tab_setint(L
, t
, (int32_t)id
);
669 lj_err_caller(L
, LJ_ERR_PROTMT
);
671 lj_gc_anybarriert(L
, t
);
672 cd
= lj_cdata_new(cts
, CTID_CTYPEID
, 4);
673 *(CTypeID
*)cdataptr(cd
) = id
;
674 setcdataV(L
, L
->top
-1, cd
);
679 LJLIB_PUSH(top
-7) LJLIB_SET(!) /* Store reference to finalizer table. */
683 GCcdata
*cd
= ffi_checkcdata(L
, 1);
684 TValue
*fin
= lj_lib_checkany(L
, 2);
685 CTState
*cts
= ctype_cts(L
);
686 GCtab
*t
= cts
->finalizer
;
687 CType
*ct
= ctype_raw(cts
, cd
->typeid);
688 if (!(ctype_isptr(ct
->info
) || ctype_isstruct(ct
->info
) ||
689 ctype_isrefarray(ct
->info
)))
690 lj_err_arg(L
, 1, LJ_ERR_FFI_INVTYPE
);
691 if (gcref(t
->metatable
)) { /* Update finalizer table, if still enabled. */
692 copyTV(L
, lj_tab_set(L
, t
, L
->base
), fin
);
693 lj_gc_anybarriert(L
, t
);
695 cd
->marked
|= LJ_GC_CDATA_FIN
;
697 cd
->marked
&= ~LJ_GC_CDATA_FIN
;
699 L
->top
= L
->base
+1; /* Pass through the cdata object. */
703 LJLIB_PUSH(top
-5) LJLIB_SET(!) /* Store clib metatable in func environment. */
707 GCstr
*name
= lj_lib_checkstr(L
, 1);
708 int global
= (L
->base
+1 < L
->top
&& tvistruecond(L
->base
+1));
709 lj_clib_load(L
, tabref(curr_func(L
)->c
.env
), name
, global
);
713 LJLIB_PUSH(top
-4) LJLIB_SET(C
)
714 LJLIB_PUSH(top
-3) LJLIB_SET(os
)
715 LJLIB_PUSH(top
-2) LJLIB_SET(arch
)
717 #include "lj_libdef.h"
719 /* ------------------------------------------------------------------------ */
721 /* Create special weak-keyed finalizer table. */
722 static GCtab
*ffi_finalizer(lua_State
*L
)
724 /* NOBARRIER: The table is new (marked white). */
725 GCtab
*t
= lj_tab_new(L
, 0, 1);
726 settabV(L
, L
->top
++, t
);
727 setgcref(t
->metatable
, obj2gco(t
));
728 setstrV(L
, lj_tab_setstr(L
, t
, lj_str_newlit(L
, "__mode")),
729 lj_str_newlit(L
, "K"));
730 t
->nomm
= (uint8_t)(~(1u<<MM_mode
));
734 /* Register FFI module as loaded. */
735 static void ffi_register_module(lua_State
*L
)
737 cTValue
*tmp
= lj_tab_getstr(tabV(registry(L
)), lj_str_newlit(L
, "_LOADED"));
738 if (tmp
&& tvistab(tmp
)) {
739 GCtab
*t
= tabV(tmp
);
740 copyTV(L
, lj_tab_setstr(L
, t
, lj_str_newlit(L
, LUA_FFILIBNAME
)), L
->top
-1);
741 lj_gc_anybarriert(L
, t
);
745 LUALIB_API
int luaopen_ffi(lua_State
*L
)
747 CTState
*cts
= lj_ctype_init(L
);
748 settabV(L
, L
->top
++, (cts
->metatype
= lj_tab_new(L
, 0, 0)));
749 cts
->finalizer
= ffi_finalizer(L
);
750 LJ_LIB_REG(L
, NULL
, ffi_meta
);
751 /* NOBARRIER: basemt is a GC root. */
752 setgcref(basemt_it(G(L
), LJ_TCDATA
), obj2gco(tabV(L
->top
-1)));
753 LJ_LIB_REG(L
, NULL
, ffi_clib
);
754 lj_clib_default(L
, tabV(L
->top
-1)); /* Create ffi.C default namespace. */
755 lua_pushliteral(L
, LJ_OS_NAME
);
756 lua_pushliteral(L
, LJ_ARCH_NAME
);
757 LJ_LIB_REG(L
, NULL
, ffi
); /* Note: no global "ffi" created! */
758 ffi_register_module(L
);