3 ** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
21 #include "lj_cparse.h"
24 #include "lj_carith.h"
30 /* -- C type checks ------------------------------------------------------- */
32 /* Check first argument for a C type and returns its ID. */
33 static CTypeID
ffi_checkctype(lua_State
*L
, CTState
*cts
)
38 lj_err_argtype(L
, 1, "C type");
40 if (tvisstr(o
)) { /* Parse an abstract C type declaration. */
46 cp
.srcname
= strdata(s
);
48 cp
.mode
= CPARSE_MODE_ABSTRACT
|CPARSE_MODE_NOIMPLICIT
;
49 errcode
= lj_cparse(&cp
);
50 if (errcode
) lj_err_throw(L
, errcode
); /* Propagate errors. */
54 if (!tviscdata(o
)) goto err_argtype
;
56 return cd
->typeid == CTID_CTYPEID
? *(CTypeID
*)cdataptr(cd
) : cd
->typeid;
60 /* Check argument for C data and return it. */
61 static GCcdata
*ffi_checkcdata(lua_State
*L
, int narg
)
63 TValue
*o
= L
->base
+ narg
-1;
64 if (!(o
< L
->top
&& tviscdata(o
)))
65 lj_err_argt(L
, narg
, LUA_TCDATA
);
69 /* Convert argument to C pointer. */
70 static void *ffi_checkptr(lua_State
*L
, int narg
, CTypeID id
)
72 CTState
*cts
= ctype_cts(L
);
73 TValue
*o
= L
->base
+ narg
-1;
76 lj_err_arg(L
, narg
, LJ_ERR_NOVAL
);
77 lj_cconv_ct_tv(cts
, ctype_get(cts
, id
), (uint8_t *)&p
, o
, 0);
81 /* -- C type metamethods -------------------------------------------------- */
83 #define LJLIB_MODULE_ffi_meta
85 LJLIB_CF(ffi_meta___index
) LJLIB_REC(cdata_index
0)
87 CTState
*cts
= ctype_cts(L
);
92 if (!(o
+1 < L
->top
&& tviscdata(o
))) /* Also checks for presence of key. */
93 lj_err_argt(L
, 1, LUA_TCDATA
);
94 ct
= lj_cdata_index(cts
, cdataV(o
), o
+1, &p
, &qual
);
95 if (lj_cdata_get(cts
, ct
, L
->top
-1, p
))
100 LJLIB_CF(ffi_meta___newindex
) LJLIB_REC(cdata_index
1)
102 CTState
*cts
= ctype_cts(L
);
107 if (!(o
+2 < L
->top
&& tviscdata(o
))) /* Also checks for key and value. */
108 lj_err_argt(L
, 1, LUA_TCDATA
);
109 ct
= lj_cdata_index(cts
, cdataV(o
), o
+1, &p
, &qual
);
110 lj_cdata_set(cts
, ct
, p
, o
+2, qual
);
114 /* Common handler for cdata arithmetic. */
115 static int ffi_arith(lua_State
*L
)
117 MMS mm
= (MMS
)(curr_func(L
)->c
.ffid
- (int)FF_ffi_meta___eq
+ (int)MM_eq
);
118 return lj_carith_op(L
, mm
);
121 /* The following functions must be in contiguous ORDER MM. */
122 LJLIB_CF(ffi_meta___eq
) LJLIB_REC(cdata_arith MM_eq
)
127 LJLIB_CF(ffi_meta___len
)
132 LJLIB_CF(ffi_meta___lt
) LJLIB_REC(cdata_arith MM_lt
)
137 LJLIB_CF(ffi_meta___le
) LJLIB_REC(cdata_arith MM_le
)
142 LJLIB_CF(ffi_meta___concat
)
147 /* Forward declaration. */
148 static int lj_cf_ffi_new(lua_State
*L
);
150 LJLIB_CF(ffi_meta___call
) LJLIB_REC(cdata_call
)
152 GCcdata
*cd
= ffi_checkcdata(L
, 1);
154 if (cd
->typeid == CTID_CTYPEID
)
155 return lj_cf_ffi_new(L
);
156 if ((ret
= lj_ccall_func(L
, cd
)) < 0)
157 lj_err_callerv(L
, LJ_ERR_FFI_BADCALL
,
158 strdata(lj_ctype_repr(L
, cd
->typeid, NULL
)));
162 LJLIB_CF(ffi_meta___add
) LJLIB_REC(cdata_arith MM_add
)
167 LJLIB_CF(ffi_meta___sub
) LJLIB_REC(cdata_arith MM_sub
)
172 LJLIB_CF(ffi_meta___mul
) LJLIB_REC(cdata_arith MM_mul
)
177 LJLIB_CF(ffi_meta___div
) LJLIB_REC(cdata_arith MM_div
)
182 LJLIB_CF(ffi_meta___mod
) LJLIB_REC(cdata_arith MM_mod
)
187 LJLIB_CF(ffi_meta___pow
) LJLIB_REC(cdata_arith MM_pow
)
192 LJLIB_CF(ffi_meta___unm
) LJLIB_REC(cdata_arith MM_unm
)
196 /* End of contiguous ORDER MM. */
198 LJLIB_CF(ffi_meta___tostring
)
200 GCcdata
*cd
= ffi_checkcdata(L
, 1);
201 const char *msg
= "cdata<%s>: %p";
202 CTypeID id
= cd
->typeid;
203 if (id
== CTID_CTYPEID
) {
205 id
= *(CTypeID
*)cdataptr(cd
);
207 CType
*ct
= ctype_raw(ctype_cts(L
), id
);
208 if (ctype_iscomplex(ct
->info
)) {
209 setstrV(L
, L
->top
-1, lj_ctype_repr_complex(L
, cdataptr(cd
), ct
->size
));
211 } else if (ct
->size
== 8 && ctype_isinteger(ct
->info
)) {
212 setstrV(L
, L
->top
-1, lj_ctype_repr_int64(L
, *(uint64_t *)cdataptr(cd
),
213 (ct
->info
& CTF_UNSIGNED
)));
217 lj_str_pushf(L
, msg
, strdata(lj_ctype_repr(L
, id
, NULL
)), cdataptr(cd
));
223 #include "lj_libdef.h"
225 /* -- C library metamethods ----------------------------------------------- */
227 #define LJLIB_MODULE_ffi_clib
229 /* Index C library by a name. */
230 static TValue
*ffi_clib_index(lua_State
*L
)
234 if (!(o
< L
->top
&& tvisudata(o
) && udataV(o
)->udtype
== UDTYPE_FFI_CLIB
))
235 lj_err_argt(L
, 1, LUA_TUSERDATA
);
236 cl
= (CLibrary
*)uddata(udataV(o
));
237 if (!(o
+1 < L
->top
&& tvisstr(o
+1)))
238 lj_err_argt(L
, 2, LUA_TSTRING
);
239 return lj_clib_index(L
, cl
, strV(o
+1));
242 LJLIB_CF(ffi_clib___index
)
244 TValue
*tv
= ffi_clib_index(L
);
246 CTState
*cts
= ctype_cts(L
);
247 GCcdata
*cd
= cdataV(tv
);
248 CType
*s
= ctype_get(cts
, cd
->typeid);
249 if (ctype_isextern(s
->info
)) {
250 CTypeID sid
= ctype_cid(s
->info
);
251 void *sp
= *(void **)cdataptr(cd
);
252 if (lj_cconv_tv_ct(cts
, ctype_raw(cts
, sid
), sid
, L
->top
-1, sp
))
257 copyTV(L
, L
->top
-1, tv
);
261 LJLIB_CF(ffi_clib___newindex
)
263 TValue
*tv
= ffi_clib_index(L
);
264 TValue
*o
= L
->base
+2;
265 if (o
< L
->top
&& tviscdata(tv
)) {
266 CTState
*cts
= ctype_cts(L
);
267 GCcdata
*cd
= cdataV(tv
);
268 CType
*d
= ctype_get(cts
, cd
->typeid);
269 if (ctype_isextern(d
->info
)) {
271 for (;;) { /* Skip attributes and collect qualifiers. */
272 d
= ctype_child(cts
, d
);
273 if (!ctype_isattrib(d
->info
)) break;
274 if (ctype_attrib(d
->info
) == CTA_QUAL
) qual
|= d
->size
;
276 if (!((d
->info
|qual
) & CTF_CONST
)) {
277 lj_cconv_ct_tv(cts
, d
, *(void **)cdataptr(cd
), o
, 0);
282 lj_err_caller(L
, LJ_ERR_FFI_WRCONST
);
283 return 0; /* unreachable */
286 LJLIB_CF(ffi_clib___gc
)
289 if (o
< L
->top
&& tvisudata(o
) && udataV(o
)->udtype
== UDTYPE_FFI_CLIB
)
290 lj_clib_unload((CLibrary
*)uddata(udataV(o
)));
294 #include "lj_libdef.h"
296 /* -- FFI library functions ----------------------------------------------- */
298 #define LJLIB_MODULE_ffi
302 GCstr
*s
= lj_lib_checkstr(L
, 1);
306 cp
.cts
= ctype_cts(L
);
307 cp
.srcname
= strdata(s
);
309 cp
.mode
= CPARSE_MODE_MULTI
|CPARSE_MODE_DIRECT
;
310 errcode
= lj_cparse(&cp
);
311 if (errcode
) lj_err_throw(L
, errcode
); /* Propagate errors. */
316 LJLIB_CF(ffi_new
) LJLIB_REC(.)
318 CTState
*cts
= ctype_cts(L
);
319 CTypeID id
= ffi_checkctype(L
, cts
);
321 CTInfo info
= lj_ctype_info(cts
, id
, &sz
);
322 TValue
*o
= L
->base
+1;
324 if ((info
& CTF_VLA
)) {
326 sz
= lj_ctype_vlsize(cts
, ctype_raw(cts
, id
),
327 (CTSize
)lj_lib_checkint(L
, 2));
329 if (sz
== CTSIZE_INVALID
)
330 lj_err_arg(L
, 1, LJ_ERR_FFI_INVSIZE
);
331 if (!(info
& CTF_VLA
) && ctype_align(info
) <= CT_MEMALIGN
)
332 cd
= lj_cdata_new(cts
, id
, sz
);
334 cd
= lj_cdata_newv(cts
, id
, sz
, ctype_align(info
));
335 setcdataV(L
, o
-1, cd
); /* Anchor the uninitialized cdata. */
336 lj_cconv_ct_init(cts
, ctype_raw(cts
, id
), sz
, cdataptr(cd
),
337 o
, (MSize
)(L
->top
- o
)); /* Initialize cdata. */
338 L
->top
= o
; /* Only return the cdata itself. */
345 CTState
*cts
= ctype_cts(L
);
346 CTypeID id
= ffi_checkctype(L
, cts
);
347 GCcdata
*cd
= lj_cdata_new(cts
, CTID_CTYPEID
, 4);
348 *(CTypeID
*)cdataptr(cd
) = id
;
349 setcdataV(L
, L
->top
-1, cd
);
356 CTState
*cts
= ctype_cts(L
);
357 CTypeID id
= ffi_checkctype(L
, cts
);
359 if (LJ_UNLIKELY(tviscdata(L
->base
) && cdataisv(cdataV(L
->base
)))) {
360 sz
= cdatavlen(cdataV(L
->base
));
362 CType
*ct
= lj_ctype_rawref(cts
, id
);
363 if (ctype_isvltype(ct
->info
))
364 sz
= lj_ctype_vlsize(cts
, ct
, (CTSize
)lj_lib_checkint(L
, 2));
366 sz
= ctype_hassize(ct
->info
) ? ct
->size
: CTSIZE_INVALID
;
367 if (LJ_UNLIKELY(sz
== CTSIZE_INVALID
)) {
372 setintV(L
->top
-1, (int32_t)sz
);
376 LJLIB_CF(ffi_alignof
)
378 CTState
*cts
= ctype_cts(L
);
379 CTypeID id
= ffi_checkctype(L
, cts
);
381 CTInfo info
= lj_ctype_info(cts
, id
, &sz
);
382 setintV(L
->top
-1, 1 << ctype_align(info
));
386 LJLIB_CF(ffi_offsetof
)
388 CTState
*cts
= ctype_cts(L
);
389 CTypeID id
= ffi_checkctype(L
, cts
);
390 GCstr
*name
= lj_lib_checkstr(L
, 2);
391 CType
*ct
= lj_ctype_rawref(cts
, id
);
393 if (ctype_isstruct(ct
->info
) && ct
->size
!= CTSIZE_INVALID
) {
394 CType
*fct
= lj_ctype_getfield(cts
, ct
, name
, &ofs
);
396 setintV(L
->top
-1, ofs
);
397 if (ctype_isfield(fct
->info
)) {
399 } else if (ctype_isbitfield(fct
->info
)) {
400 setintV(L
->top
++, ctype_bitpos(fct
->info
));
401 setintV(L
->top
++, ctype_bitbsz(fct
->info
));
411 CTState
*cts
= ctype_cts(L
);
412 CTypeID id
= ffi_checkctype(L
, cts
);
413 TValue
*o
= lj_lib_checkany(L
, 2);
414 L
->top
= o
+1; /* Make sure this is the last item on the stack. */
415 if (!(tviscdata(o
) && cdataV(o
)->typeid == id
)) {
416 CTSize sz
= lj_ctype_size(cts
, id
);
418 if (sz
== CTSIZE_INVALID
)
419 lj_err_caller(L
, LJ_ERR_FFI_INVSIZE
);
420 cd
= lj_cdata_new(cts
, id
, sz
); /* Create destination cdata. */
421 lj_cconv_ct_tv(cts
, ctype_raw(cts
, id
), cdataptr(cd
), o
, CCF_CAST
);
430 CTState
*cts
= ctype_cts(L
);
431 TValue
*o
= lj_lib_checkany(L
, 1);
432 size_t sz
= (size_t)(CTSize
)lj_lib_optint(L
, 2, (int32_t)CTSIZE_INVALID
);
433 CType
*ct
= ctype_get(cts
, sz
==CTSIZE_INVALID
? CTID_P_CVOID
: CTID_P_CCHAR
);
435 L
->top
= o
+1; /* Make sure this is the last item on the stack. */
436 lj_cconv_ct_tv(cts
, ct
, (uint8_t *)&p
, o
, 0);
437 if (sz
== CTSIZE_INVALID
) sz
= strlen(p
);
438 setstrV(L
, o
, lj_str_new(L
, p
, sz
));
445 void *dp
= ffi_checkptr(L
, 1, CTID_P_VOID
);
446 void *sp
= ffi_checkptr(L
, 2, CTID_P_CVOID
);
447 TValue
*o
= L
->base
+1;
449 if (tvisstr(o
) && o
+1 >= L
->top
) {
450 sz
= strV(o
)->len
+1; /* Copy Lua string including trailing '\0'. */
452 sz
= (CTSize
)lj_lib_checkint(L
, 3);
453 if (tvisstr(o
) && sz
> strV(o
)->len
+1)
454 sz
= strV(o
)->len
+1; /* Max. copy length is string length. */
462 void *dp
= ffi_checkptr(L
, 1, CTID_P_VOID
);
463 CTSize sz
= (CTSize
)lj_lib_checkint(L
, 2);
464 int32_t fill
= lj_lib_optint(L
, 3, 0);
465 memset(dp
, fill
, sz
);
469 #define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be)
471 /* Test ABI string. */
474 GCstr
*s
= lj_lib_checkstr(L
, 1);
478 case H_(849858eb
,ad35fd06
): b
= 1; break; /* 64bit */
480 case H_(662d3c79
,d0e22477
): b
= 1; break; /* 32bit */
483 case H_(e33ee463
,e33ee463
): b
= 1; break; /* fpu */
486 case H_(61211a23
,c2e8c81c
): b
= 1; break; /* softfp */
488 case H_(539417a8
,8ce0812f
): b
= 1; break; /* hardfp */
491 case H_(2182df8f
,f2ed1152
): b
= 1; break; /* eabi */
494 case H_(4ab624a8
,4ab624a8
): b
= 1; break; /* win */
496 case H_(3af93066
,1f001464
): b
= 1; break; /* le/be */
500 setboolV(L
->top
-1, b
);
506 LJLIB_PUSH(top
-5) LJLIB_SET(!) /* Store clib metatable in func environment. */
510 GCstr
*name
= lj_lib_checkstr(L
, 1);
511 int global
= (L
->base
+1 < L
->top
&& tvistruecond(L
->base
+1));
512 lj_clib_load(L
, tabref(curr_func(L
)->c
.env
), name
, global
);
516 LJLIB_PUSH(top
-4) LJLIB_SET(C
)
517 LJLIB_PUSH(top
-3) LJLIB_SET(os
)
518 LJLIB_PUSH(top
-2) LJLIB_SET(arch
)
520 #include "lj_libdef.h"
522 /* ------------------------------------------------------------------------ */
524 LUALIB_API
int luaopen_ffi(lua_State
*L
)
527 LJ_LIB_REG(L
, NULL
, ffi_meta
);
528 /* NOBARRIER: basemt is a GC root. */
529 setgcref(basemt_it(G(L
), LJ_TCDATA
), obj2gco(tabV(L
->top
-1)));
530 LJ_LIB_REG(L
, NULL
, ffi_clib
);
531 lj_clib_default(L
, tabV(L
->top
-1)); /* Create ffi.C default namespace. */
532 lua_pushliteral(L
, LJ_OS_NAME
);
533 lua_pushliteral(L
, LJ_ARCH_NAME
);
534 LJ_LIB_REG(L
, NULL
, ffi
); /* Note: no global "ffi" created! */