root/lib_ffi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ffi_checkctype
  2. ffi_checkcdata
  3. ffi_checkptr
  4. ffi_checkint
  5. ffi_index_meta
  6. LJLIB_CF
  7. LJLIB_CF
  8. ffi_arith
  9. LJLIB_CF
  10. LJLIB_CF
  11. LJLIB_CF
  12. LJLIB_CF
  13. LJLIB_CF
  14. LJLIB_CF
  15. LJLIB_CF
  16. LJLIB_CF
  17. LJLIB_CF
  18. LJLIB_CF
  19. LJLIB_CF
  20. LJLIB_CF
  21. LJLIB_CF
  22. LJLIB_CF
  23. ffi_pairs
  24. LJLIB_CF
  25. LJLIB_CF
  26. LJLIB_PUSH
  27. LJLIB_CF
  28. LJLIB_CF
  29. LJLIB_CF
  30. ffi_callback_set
  31. LJLIB_CF
  32. LJLIB_CF
  33. LJLIB_PUSH
  34. LJLIB_CF
  35. LJLIB_CF
  36. LJLIB_CF
  37. LJLIB_CF
  38. LJLIB_CF
  39. LJLIB_CF
  40. LJLIB_CF
  41. LJLIB_CF
  42. LJLIB_CF
  43. LJLIB_CF
  44. LJLIB_CF
  45. LJLIB_CF
  46. LJLIB_PUSH
  47. LJLIB_PUSH
  48. LJLIB_PUSH
  49. LJLIB_PUSH
  50. ffi_register_module
  51. luaopen_ffi

   1 /*
   2 ** FFI library.
   3 ** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
   4 */
   5 
   6 #define lib_ffi_c
   7 #define LUA_LIB
   8 
   9 #include <errno.h>
  10 
  11 #include "lua.h"
  12 #include "lauxlib.h"
  13 #include "lualib.h"
  14 
  15 #include "lj_obj.h"
  16 
  17 #if LJ_HASFFI
  18 
  19 #include "lj_gc.h"
  20 #include "lj_err.h"
  21 #include "lj_str.h"
  22 #include "lj_tab.h"
  23 #include "lj_meta.h"
  24 #include "lj_ctype.h"
  25 #include "lj_cparse.h"
  26 #include "lj_cdata.h"
  27 #include "lj_cconv.h"
  28 #include "lj_carith.h"
  29 #include "lj_ccall.h"
  30 #include "lj_ccallback.h"
  31 #include "lj_clib.h"
  32 #include "lj_ff.h"
  33 #include "lj_lib.h"
  34 
  35 /* -- C type checks ------------------------------------------------------- */
  36 
  37 /* Check first argument for a C type and returns its ID. */
  38 static CTypeID ffi_checkctype(lua_State *L, CTState *cts, TValue *param)
  39 {
  40   TValue *o = L->base;
  41   if (!(o < L->top)) {
  42   err_argtype:
  43     lj_err_argtype(L, 1, "C type");
  44   }
  45   if (tvisstr(o)) {  /* Parse an abstract C type declaration. */
  46     GCstr *s = strV(o);
  47     CPState cp;
  48     int errcode;
  49     cp.L = L;
  50     cp.cts = cts;
  51     cp.srcname = strdata(s);
  52     cp.p = strdata(s);
  53     cp.param = param;
  54     cp.mode = CPARSE_MODE_ABSTRACT|CPARSE_MODE_NOIMPLICIT;
  55     errcode = lj_cparse(&cp);
  56     if (errcode) lj_err_throw(L, errcode);  /* Propagate errors. */
  57     return cp.val.id;
  58   } else {
  59     GCcdata *cd;
  60     if (!tviscdata(o)) goto err_argtype;
  61     if (param && param < L->top) lj_err_arg(L, 1, LJ_ERR_FFI_NUMPARAM);
  62     cd = cdataV(o);
  63     return cd->ctypeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : cd->ctypeid;
  64   }
  65 }
  66 
  67 /* Check argument for C data and return it. */
  68 static GCcdata *ffi_checkcdata(lua_State *L, int narg)
  69 {
  70   TValue *o = L->base + narg-1;
  71   if (!(o < L->top && tviscdata(o)))
  72     lj_err_argt(L, narg, LUA_TCDATA);
  73   return cdataV(o);
  74 }
  75 
  76 /* Convert argument to C pointer. */
  77 static void *ffi_checkptr(lua_State *L, int narg, CTypeID id)
  78 {
  79   CTState *cts = ctype_cts(L);
  80   TValue *o = L->base + narg-1;
  81   void *p;
  82   if (o >= L->top)
  83     lj_err_arg(L, narg, LJ_ERR_NOVAL);
  84   lj_cconv_ct_tv(cts, ctype_get(cts, id), (uint8_t *)&p, o, CCF_ARG(narg));
  85   return p;
  86 }
  87 
  88 /* Convert argument to int32_t. */
  89 static int32_t ffi_checkint(lua_State *L, int narg)
  90 {
  91   CTState *cts = ctype_cts(L);
  92   TValue *o = L->base + narg-1;
  93   int32_t i;
  94   if (o >= L->top)
  95     lj_err_arg(L, narg, LJ_ERR_NOVAL);
  96   lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o,
  97                  CCF_ARG(narg));
  98   return i;
  99 }
 100 
 101 /* -- C type metamethods -------------------------------------------------- */
 102 
 103 #define LJLIB_MODULE_ffi_meta
 104 
 105 /* Handle ctype __index/__newindex metamethods. */
 106 static int ffi_index_meta(lua_State *L, CTState *cts, CType *ct, MMS mm)
 107 {
 108   CTypeID id = ctype_typeid(cts, ct);
 109   cTValue *tv = lj_ctype_meta(cts, id, mm);
 110   TValue *base = L->base;
 111   if (!tv) {
 112     const char *s;
 113   err_index:
 114     s = strdata(lj_ctype_repr(L, id, NULL));
 115     if (tvisstr(L->base+1)) {
 116       lj_err_callerv(L, LJ_ERR_FFI_BADMEMBER, s, strVdata(L->base+1));
 117     } else {
 118       const char *key = tviscdata(L->base+1) ?
 119         strdata(lj_ctype_repr(L, cdataV(L->base+1)->ctypeid, NULL)) :
 120         lj_typename(L->base+1);
 121       lj_err_callerv(L, LJ_ERR_FFI_BADIDXW, s, key);
 122     }
 123   }
 124   if (!tvisfunc(tv)) {
 125     if (mm == MM_index) {
 126       cTValue *o = lj_meta_tget(L, tv, base+1);
 127       if (o) {
 128         if (tvisnil(o)) goto err_index;
 129         copyTV(L, L->top-1, o);
 130         return 1;
 131       }
 132     } else {
 133       TValue *o = lj_meta_tset(L, tv, base+1);
 134       if (o) {
 135         copyTV(L, o, base+2);
 136         return 0;
 137       }
 138     }
 139     copyTV(L, base, L->top);
 140     tv = L->top-1;
 141   }
 142   return lj_meta_tailcall(L, tv);
 143 }
 144 
 145 LJLIB_CF(ffi_meta___index)      LJLIB_REC(cdata_index 0)
 146 {
 147   CTState *cts = ctype_cts(L);
 148   CTInfo qual = 0;
 149   CType *ct;
 150   uint8_t *p;
 151   TValue *o = L->base;
 152   if (!(o+1 < L->top && tviscdata(o)))  /* Also checks for presence of key. */
 153     lj_err_argt(L, 1, LUA_TCDATA);
 154   ct = lj_cdata_index(cts, cdataV(o), o+1, &p, &qual);
 155   if ((qual & 1))
 156     return ffi_index_meta(L, cts, ct, MM_index);
 157   if (lj_cdata_get(cts, ct, L->top-1, p))
 158     lj_gc_check(L);
 159   return 1;
 160 }
 161 
 162 LJLIB_CF(ffi_meta___newindex)   LJLIB_REC(cdata_index 1)
 163 {
 164   CTState *cts = ctype_cts(L);
 165   CTInfo qual = 0;
 166   CType *ct;
 167   uint8_t *p;
 168   TValue *o = L->base;
 169   if (!(o+2 < L->top && tviscdata(o)))  /* Also checks for key and value. */
 170     lj_err_argt(L, 1, LUA_TCDATA);
 171   ct = lj_cdata_index(cts, cdataV(o), o+1, &p, &qual);
 172   if ((qual & 1)) {
 173     if ((qual & CTF_CONST))
 174       lj_err_caller(L, LJ_ERR_FFI_WRCONST);
 175     return ffi_index_meta(L, cts, ct, MM_newindex);
 176   }
 177   lj_cdata_set(cts, ct, p, o+2, qual);
 178   return 0;
 179 }
 180 
 181 /* Common handler for cdata arithmetic. */
 182 static int ffi_arith(lua_State *L)
 183 {
 184   MMS mm = (MMS)(curr_func(L)->c.ffid - (int)FF_ffi_meta___eq + (int)MM_eq);
 185   return lj_carith_op(L, mm);
 186 }
 187 
 188 /* The following functions must be in contiguous ORDER MM. */
 189 LJLIB_CF(ffi_meta___eq)         LJLIB_REC(cdata_arith MM_eq)
 190 {
 191   return ffi_arith(L);
 192 }
 193 
 194 LJLIB_CF(ffi_meta___len)        LJLIB_REC(cdata_arith MM_len)
 195 {
 196   return ffi_arith(L);
 197 }
 198 
 199 LJLIB_CF(ffi_meta___lt)         LJLIB_REC(cdata_arith MM_lt)
 200 {
 201   return ffi_arith(L);
 202 }
 203 
 204 LJLIB_CF(ffi_meta___le)         LJLIB_REC(cdata_arith MM_le)
 205 {
 206   return ffi_arith(L);
 207 }
 208 
 209 LJLIB_CF(ffi_meta___concat)     LJLIB_REC(cdata_arith MM_concat)
 210 {
 211   return ffi_arith(L);
 212 }
 213 
 214 /* Forward declaration. */
 215 static int lj_cf_ffi_new(lua_State *L);
 216 
 217 LJLIB_CF(ffi_meta___call)       LJLIB_REC(cdata_call)
 218 {
 219   CTState *cts = ctype_cts(L);
 220   GCcdata *cd = ffi_checkcdata(L, 1);
 221   CTypeID id = cd->ctypeid;
 222   CType *ct;
 223   cTValue *tv;
 224   MMS mm = MM_call;
 225   if (cd->ctypeid == CTID_CTYPEID) {
 226     id = *(CTypeID *)cdataptr(cd);
 227     mm = MM_new;
 228   } else {
 229     int ret = lj_ccall_func(L, cd);
 230     if (ret >= 0)
 231       return ret;
 232   }
 233   /* Handle ctype __call/__new metamethod. */
 234   ct = ctype_raw(cts, id);
 235   if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
 236   tv = lj_ctype_meta(cts, id, mm);
 237   if (tv)
 238     return lj_meta_tailcall(L, tv);
 239   else if (mm == MM_call)
 240     lj_err_callerv(L, LJ_ERR_FFI_BADCALL, strdata(lj_ctype_repr(L, id, NULL)));
 241   return lj_cf_ffi_new(L);
 242 }
 243 
 244 LJLIB_CF(ffi_meta___add)        LJLIB_REC(cdata_arith MM_add)
 245 {
 246   return ffi_arith(L);
 247 }
 248 
 249 LJLIB_CF(ffi_meta___sub)        LJLIB_REC(cdata_arith MM_sub)
 250 {
 251   return ffi_arith(L);
 252 }
 253 
 254 LJLIB_CF(ffi_meta___mul)        LJLIB_REC(cdata_arith MM_mul)
 255 {
 256   return ffi_arith(L);
 257 }
 258 
 259 LJLIB_CF(ffi_meta___div)        LJLIB_REC(cdata_arith MM_div)
 260 {
 261   return ffi_arith(L);
 262 }
 263 
 264 LJLIB_CF(ffi_meta___mod)        LJLIB_REC(cdata_arith MM_mod)
 265 {
 266   return ffi_arith(L);
 267 }
 268 
 269 LJLIB_CF(ffi_meta___pow)        LJLIB_REC(cdata_arith MM_pow)
 270 {
 271   return ffi_arith(L);
 272 }
 273 
 274 LJLIB_CF(ffi_meta___unm)        LJLIB_REC(cdata_arith MM_unm)
 275 {
 276   return ffi_arith(L);
 277 }
 278 /* End of contiguous ORDER MM. */
 279 
 280 LJLIB_CF(ffi_meta___tostring)
 281 {
 282   GCcdata *cd = ffi_checkcdata(L, 1);
 283   const char *msg = "cdata<%s>: %p";
 284   CTypeID id = cd->ctypeid;
 285   void *p = cdataptr(cd);
 286   if (id == CTID_CTYPEID) {
 287     msg = "ctype<%s>";
 288     id = *(CTypeID *)p;
 289   } else {
 290     CTState *cts = ctype_cts(L);
 291     CType *ct = ctype_raw(cts, id);
 292     if (ctype_isref(ct->info)) {
 293       p = *(void **)p;
 294       ct = ctype_rawchild(cts, ct);
 295     }
 296     if (ctype_iscomplex(ct->info)) {
 297       setstrV(L, L->top-1, lj_ctype_repr_complex(L, cdataptr(cd), ct->size));
 298       goto checkgc;
 299     } else if (ct->size == 8 && ctype_isinteger(ct->info)) {
 300       setstrV(L, L->top-1, lj_ctype_repr_int64(L, *(uint64_t *)cdataptr(cd),
 301                                                (ct->info & CTF_UNSIGNED)));
 302       goto checkgc;
 303     } else if (ctype_isfunc(ct->info)) {
 304       p = *(void **)p;
 305     } else if (ctype_isenum(ct->info)) {
 306       msg = "cdata<%s>: %d";
 307       p = (void *)(uintptr_t)*(uint32_t **)p;
 308     } else {
 309       if (ctype_isptr(ct->info)) {
 310         p = cdata_getptr(p, ct->size);
 311         ct = ctype_rawchild(cts, ct);
 312       }
 313       if (ctype_isstruct(ct->info) || ctype_isvector(ct->info)) {
 314         /* Handle ctype __tostring metamethod. */
 315         cTValue *tv = lj_ctype_meta(cts, ctype_typeid(cts, ct), MM_tostring);
 316         if (tv)
 317           return lj_meta_tailcall(L, tv);
 318       }
 319     }
 320   }
 321   lj_str_pushf(L, msg, strdata(lj_ctype_repr(L, id, NULL)), p);
 322 checkgc:
 323   lj_gc_check(L);
 324   return 1;
 325 }
 326 
 327 static int ffi_pairs(lua_State *L, MMS mm)
 328 {
 329   CTState *cts = ctype_cts(L);
 330   CTypeID id = ffi_checkcdata(L, 1)->ctypeid;
 331   CType *ct = ctype_raw(cts, id);
 332   cTValue *tv;
 333   if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
 334   tv = lj_ctype_meta(cts, id, mm);
 335   if (!tv)
 336     lj_err_callerv(L, LJ_ERR_FFI_BADMM, strdata(lj_ctype_repr(L, id, NULL)),
 337                    strdata(mmname_str(G(L), mm)));
 338   return lj_meta_tailcall(L, tv);
 339 }
 340 
 341 LJLIB_CF(ffi_meta___pairs)
 342 {
 343   return ffi_pairs(L, MM_pairs);
 344 }
 345 
 346 LJLIB_CF(ffi_meta___ipairs)
 347 {
 348   return ffi_pairs(L, MM_ipairs);
 349 }
 350 
 351 LJLIB_PUSH("ffi") LJLIB_SET(__metatable)
 352 
 353 #include "lj_libdef.h"
 354 
 355 /* -- C library metamethods ----------------------------------------------- */
 356 
 357 #define LJLIB_MODULE_ffi_clib
 358 
 359 /* Index C library by a name. */
 360 static TValue *ffi_clib_index(lua_State *L)
 361 {
 362   TValue *o = L->base;
 363   CLibrary *cl;
 364   if (!(o < L->top && tvisudata(o) && udataV(o)->udtype == UDTYPE_FFI_CLIB))
 365     lj_err_argt(L, 1, LUA_TUSERDATA);
 366   cl = (CLibrary *)uddata(udataV(o));
 367   if (!(o+1 < L->top && tvisstr(o+1)))
 368     lj_err_argt(L, 2, LUA_TSTRING);
 369   return lj_clib_index(L, cl, strV(o+1));
 370 }
 371 
 372 LJLIB_CF(ffi_clib___index)      LJLIB_REC(clib_index 1)
 373 {
 374   TValue *tv = ffi_clib_index(L);
 375   if (tviscdata(tv)) {
 376     CTState *cts = ctype_cts(L);
 377     GCcdata *cd = cdataV(tv);
 378     CType *s = ctype_get(cts, cd->ctypeid);
 379     if (ctype_isextern(s->info)) {
 380       CTypeID sid = ctype_cid(s->info);
 381       void *sp = *(void **)cdataptr(cd);
 382       CType *ct = ctype_raw(cts, sid);
 383       if (lj_cconv_tv_ct(cts, ct, sid, L->top-1, sp))
 384         lj_gc_check(L);
 385       return 1;
 386     }
 387   }
 388   copyTV(L, L->top-1, tv);
 389   return 1;
 390 }
 391 
 392 LJLIB_CF(ffi_clib___newindex)   LJLIB_REC(clib_index 0)
 393 {
 394   TValue *tv = ffi_clib_index(L);
 395   TValue *o = L->base+2;
 396   if (o < L->top && tviscdata(tv)) {
 397     CTState *cts = ctype_cts(L);
 398     GCcdata *cd = cdataV(tv);
 399     CType *d = ctype_get(cts, cd->ctypeid);
 400     if (ctype_isextern(d->info)) {
 401       CTInfo qual = 0;
 402       for (;;) {  /* Skip attributes and collect qualifiers. */
 403         d = ctype_child(cts, d);
 404         if (!ctype_isattrib(d->info)) break;
 405         if (ctype_attrib(d->info) == CTA_QUAL) qual |= d->size;
 406       }
 407       if (!((d->info|qual) & CTF_CONST)) {
 408         lj_cconv_ct_tv(cts, d, *(void **)cdataptr(cd), o, 0);
 409         return 0;
 410       }
 411     }
 412   }
 413   lj_err_caller(L, LJ_ERR_FFI_WRCONST);
 414   return 0;  /* unreachable */
 415 }
 416 
 417 LJLIB_CF(ffi_clib___gc)
 418 {
 419   TValue *o = L->base;
 420   if (o < L->top && tvisudata(o) && udataV(o)->udtype == UDTYPE_FFI_CLIB)
 421     lj_clib_unload((CLibrary *)uddata(udataV(o)));
 422   return 0;
 423 }
 424 
 425 #include "lj_libdef.h"
 426 
 427 /* -- Callback function metamethods --------------------------------------- */
 428 
 429 #define LJLIB_MODULE_ffi_callback
 430 
 431 static int ffi_callback_set(lua_State *L, GCfunc *fn)
 432 {
 433   GCcdata *cd = ffi_checkcdata(L, 1);
 434   CTState *cts = ctype_cts(L);
 435   CType *ct = ctype_raw(cts, cd->ctypeid);
 436   if (ctype_isptr(ct->info) && (LJ_32 || ct->size == 8)) {
 437     MSize slot = lj_ccallback_ptr2slot(cts, *(void **)cdataptr(cd));
 438     if (slot < cts->cb.sizeid && cts->cb.cbid[slot] != 0) {
 439       GCtab *t = cts->miscmap;
 440       TValue *tv = lj_tab_setint(L, t, (int32_t)slot);
 441       if (fn) {
 442         setfuncV(L, tv, fn);
 443         lj_gc_anybarriert(L, t);
 444       } else {
 445         setnilV(tv);
 446         cts->cb.cbid[slot] = 0;
 447         cts->cb.topid = slot < cts->cb.topid ? slot : cts->cb.topid;
 448       }
 449       return 0;
 450     }
 451   }
 452   lj_err_caller(L, LJ_ERR_FFI_BADCBACK);
 453   return 0;
 454 }
 455 
 456 LJLIB_CF(ffi_callback_free)
 457 {
 458   return ffi_callback_set(L, NULL);
 459 }
 460 
 461 LJLIB_CF(ffi_callback_set)
 462 {
 463   GCfunc *fn = lj_lib_checkfunc(L, 2);
 464   return ffi_callback_set(L, fn);
 465 }
 466 
 467 LJLIB_PUSH(top-1) LJLIB_SET(__index)
 468 
 469 #include "lj_libdef.h"
 470 
 471 /* -- FFI library functions ----------------------------------------------- */
 472 
 473 #define LJLIB_MODULE_ffi
 474 
 475 LJLIB_CF(ffi_cdef)
 476 {
 477   GCstr *s = lj_lib_checkstr(L, 1);
 478   CPState cp;
 479   int errcode;
 480   cp.L = L;
 481   cp.cts = ctype_cts(L);
 482   cp.srcname = strdata(s);
 483   cp.p = strdata(s);
 484   cp.param = L->base+1;
 485   cp.mode = CPARSE_MODE_MULTI|CPARSE_MODE_DIRECT;
 486   errcode = lj_cparse(&cp);
 487   if (errcode) lj_err_throw(L, errcode);  /* Propagate errors. */
 488   lj_gc_check(L);
 489   return 0;
 490 }
 491 
 492 LJLIB_CF(ffi_new)       LJLIB_REC(.)
 493 {
 494   CTState *cts = ctype_cts(L);
 495   CTypeID id = ffi_checkctype(L, cts, NULL);
 496   CType *ct = ctype_raw(cts, id);
 497   CTSize sz;
 498   CTInfo info = lj_ctype_info(cts, id, &sz);
 499   TValue *o = L->base+1;
 500   GCcdata *cd;
 501   if ((info & CTF_VLA)) {
 502     o++;
 503     sz = lj_ctype_vlsize(cts, ct, (CTSize)ffi_checkint(L, 2));
 504   }
 505   if (sz == CTSIZE_INVALID)
 506     lj_err_arg(L, 1, LJ_ERR_FFI_INVSIZE);
 507   if (!(info & CTF_VLA) && ctype_align(info) <= CT_MEMALIGN)
 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. */
 512   lj_cconv_ct_init(cts, ct, sz, cdataptr(cd),
 513                    o, (MSize)(L->top - o));  /* Initialize cdata. */
 514   if (ctype_isstruct(ct->info)) {
 515     /* Handle ctype __gc metamethod. Use the fast lookup here. */
 516     cTValue *tv = lj_tab_getinth(cts->miscmap, -(int32_t)id);
 517     if (tv && tvistab(tv) && (tv = lj_meta_fast(L, tabV(tv), MM_gc))) {
 518       GCtab *t = cts->finalizer;
 519       if (gcref(t->metatable)) {
 520         /* Add to finalizer table, if still enabled. */
 521         copyTV(L, lj_tab_set(L, t, o-1), tv);
 522         lj_gc_anybarriert(L, t);
 523         cd->marked |= LJ_GC_CDATA_FIN;
 524       }
 525     }
 526   }
 527   L->top = o;  /* Only return the cdata itself. */
 528   lj_gc_check(L);
 529   return 1;
 530 }
 531 
 532 LJLIB_CF(ffi_cast)      LJLIB_REC(ffi_new)
 533 {
 534   CTState *cts = ctype_cts(L);
 535   CTypeID id = ffi_checkctype(L, cts, NULL);
 536   CType *d = ctype_raw(cts, id);
 537   TValue *o = lj_lib_checkany(L, 2);
 538   L->top = o+1;  /* Make sure this is the last item on the stack. */
 539   if (!(ctype_isnum(d->info) || ctype_isptr(d->info) || ctype_isenum(d->info)))
 540     lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE);
 541   if (!(tviscdata(o) && cdataV(o)->ctypeid == id)) {
 542     GCcdata *cd = lj_cdata_new(cts, id, d->size);
 543     lj_cconv_ct_tv(cts, d, cdataptr(cd), o, CCF_CAST);
 544     setcdataV(L, o, cd);
 545     lj_gc_check(L);
 546   }
 547   return 1;
 548 }
 549 
 550 LJLIB_CF(ffi_typeof)    LJLIB_REC(.)
 551 {
 552   CTState *cts = ctype_cts(L);
 553   CTypeID id = ffi_checkctype(L, cts, L->base+1);
 554   GCcdata *cd = lj_cdata_new(cts, CTID_CTYPEID, 4);
 555   *(CTypeID *)cdataptr(cd) = id;
 556   setcdataV(L, L->top-1, cd);
 557   lj_gc_check(L);
 558   return 1;
 559 }
 560 
 561 LJLIB_CF(ffi_istype)    LJLIB_REC(.)
 562 {
 563   CTState *cts = ctype_cts(L);
 564   CTypeID id1 = ffi_checkctype(L, cts, NULL);
 565   TValue *o = lj_lib_checkany(L, 2);
 566   int b = 0;
 567   if (tviscdata(o)) {
 568     GCcdata *cd = cdataV(o);
 569     CTypeID id2 = cd->ctypeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) :
 570                                                 cd->ctypeid;
 571     CType *ct1 = lj_ctype_rawref(cts, id1);
 572     CType *ct2 = lj_ctype_rawref(cts, id2);
 573     if (ct1 == ct2) {
 574       b = 1;
 575     } else if (ctype_type(ct1->info) == ctype_type(ct2->info) &&
 576                ct1->size == ct2->size) {
 577       if (ctype_ispointer(ct1->info))
 578         b = lj_cconv_compatptr(cts, ct1, ct2, CCF_IGNQUAL);
 579       else if (ctype_isnum(ct1->info) || ctype_isvoid(ct1->info))
 580         b = (((ct1->info ^ ct2->info) & ~(CTF_QUAL|CTF_LONG)) == 0);
 581     } else if (ctype_isstruct(ct1->info) && ctype_isptr(ct2->info) &&
 582                ct1 == ctype_rawchild(cts, ct2)) {
 583       b = 1;
 584     }
 585   }
 586   setboolV(L->top-1, b);
 587   setboolV(&G(L)->tmptv2, b);  /* Remember for trace recorder. */
 588   return 1;
 589 }
 590 
 591 LJLIB_CF(ffi_sizeof)    LJLIB_REC(ffi_xof FF_ffi_sizeof)
 592 {
 593   CTState *cts = ctype_cts(L);
 594   CTypeID id = ffi_checkctype(L, cts, NULL);
 595   CTSize sz;
 596   if (LJ_UNLIKELY(tviscdata(L->base) && cdataisv(cdataV(L->base)))) {
 597     sz = cdatavlen(cdataV(L->base));
 598   } else {
 599     CType *ct = lj_ctype_rawref(cts, id);
 600     if (ctype_isvltype(ct->info))
 601       sz = lj_ctype_vlsize(cts, ct, (CTSize)ffi_checkint(L, 2));
 602     else
 603       sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_INVALID;
 604     if (LJ_UNLIKELY(sz == CTSIZE_INVALID)) {
 605       setnilV(L->top-1);
 606       return 1;
 607     }
 608   }
 609   setintV(L->top-1, (int32_t)sz);
 610   return 1;
 611 }
 612 
 613 LJLIB_CF(ffi_alignof)   LJLIB_REC(ffi_xof FF_ffi_alignof)
 614 {
 615   CTState *cts = ctype_cts(L);
 616   CTypeID id = ffi_checkctype(L, cts, NULL);
 617   CTSize sz = 0;
 618   CTInfo info = lj_ctype_info(cts, id, &sz);
 619   setintV(L->top-1, 1 << ctype_align(info));
 620   return 1;
 621 }
 622 
 623 LJLIB_CF(ffi_offsetof)  LJLIB_REC(ffi_xof FF_ffi_offsetof)
 624 {
 625   CTState *cts = ctype_cts(L);
 626   CTypeID id = ffi_checkctype(L, cts, NULL);
 627   GCstr *name = lj_lib_checkstr(L, 2);
 628   CType *ct = lj_ctype_rawref(cts, id);
 629   CTSize ofs;
 630   if (ctype_isstruct(ct->info) && ct->size != CTSIZE_INVALID) {
 631     CType *fct = lj_ctype_getfield(cts, ct, name, &ofs);
 632     if (fct) {
 633       setintV(L->top-1, ofs);
 634       if (ctype_isfield(fct->info)) {
 635         return 1;
 636       } else if (ctype_isbitfield(fct->info)) {
 637         setintV(L->top++, ctype_bitpos(fct->info));
 638         setintV(L->top++, ctype_bitbsz(fct->info));
 639         return 3;
 640       }
 641     }
 642   }
 643   return 0;
 644 }
 645 
 646 LJLIB_CF(ffi_errno)     LJLIB_REC(.)
 647 {
 648   int err = errno;
 649   if (L->top > L->base)
 650     errno = ffi_checkint(L, 1);
 651   setintV(L->top++, err);
 652   return 1;
 653 }
 654 
 655 LJLIB_CF(ffi_string)    LJLIB_REC(.)
 656 {
 657   CTState *cts = ctype_cts(L);
 658   TValue *o = lj_lib_checkany(L, 1);
 659   const char *p;
 660   size_t len;
 661   if (o+1 < L->top && !tvisnil(o+1)) {
 662     len = (size_t)ffi_checkint(L, 2);
 663     lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p, o,
 664                    CCF_ARG(1));
 665   } else {
 666     lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CCHAR), (uint8_t *)&p, o,
 667                    CCF_ARG(1));
 668     len = strlen(p);
 669   }
 670   L->top = o+1;  /* Make sure this is the last item on the stack. */
 671   setstrV(L, o, lj_str_new(L, p, len));
 672   lj_gc_check(L);
 673   return 1;
 674 }
 675 
 676 LJLIB_CF(ffi_copy)      LJLIB_REC(.)
 677 {
 678   void *dp = ffi_checkptr(L, 1, CTID_P_VOID);
 679   void *sp = ffi_checkptr(L, 2, CTID_P_CVOID);
 680   TValue *o = L->base+1;
 681   CTSize len;
 682   if (tvisstr(o) && o+1 >= L->top)
 683     len = strV(o)->len+1;  /* Copy Lua string including trailing '\0'. */
 684   else
 685     len = (CTSize)ffi_checkint(L, 3);
 686   memcpy(dp, sp, len);
 687   return 0;
 688 }
 689 
 690 LJLIB_CF(ffi_fill)      LJLIB_REC(.)
 691 {
 692   void *dp = ffi_checkptr(L, 1, CTID_P_VOID);
 693   CTSize len = (CTSize)ffi_checkint(L, 2);
 694   int32_t fill = 0;
 695   if (L->base+2 < L->top && !tvisnil(L->base+2)) fill = ffi_checkint(L, 3);
 696   memset(dp, fill, len);
 697   return 0;
 698 }
 699 
 700 #define H_(le, be)      LJ_ENDIAN_SELECT(0x##le, 0x##be)
 701 
 702 /* Test ABI string. */
 703 LJLIB_CF(ffi_abi)       LJLIB_REC(.)
 704 {
 705   GCstr *s = lj_lib_checkstr(L, 1);
 706   int b = 0;
 707   switch (s->hash) {
 708 #if LJ_64
 709   case H_(849858eb,ad35fd06): b = 1; break;  /* 64bit */
 710 #else
 711   case H_(662d3c79,d0e22477): b = 1; break;  /* 32bit */
 712 #endif
 713 #if LJ_ARCH_HASFPU
 714   case H_(e33ee463,e33ee463): b = 1; break;  /* fpu */
 715 #endif
 716 #if LJ_ABI_SOFTFP
 717   case H_(61211a23,c2e8c81c): b = 1; break;  /* softfp */
 718 #else
 719   case H_(539417a8,8ce0812f): b = 1; break;  /* hardfp */
 720 #endif
 721 #if LJ_ABI_EABI
 722   case H_(2182df8f,f2ed1152): b = 1; break;  /* eabi */
 723 #endif
 724 #if LJ_ABI_WIN
 725   case H_(4ab624a8,4ab624a8): b = 1; break;  /* win */
 726 #endif
 727   case H_(3af93066,1f001464): b = 1; break;  /* le/be */
 728   default:
 729     break;
 730   }
 731   setboolV(L->top-1, b);
 732   setboolV(&G(L)->tmptv2, b);  /* Remember for trace recorder. */
 733   return 1;
 734 }
 735 
 736 #undef H_
 737 
 738 LJLIB_PUSH(top-8) LJLIB_SET(!)  /* Store reference to miscmap table. */
 739 
 740 LJLIB_CF(ffi_metatype)
 741 {
 742   CTState *cts = ctype_cts(L);
 743   CTypeID id = ffi_checkctype(L, cts, NULL);
 744   GCtab *mt = lj_lib_checktab(L, 2);
 745   GCtab *t = cts->miscmap;
 746   CType *ct = ctype_get(cts, id);  /* Only allow raw types. */
 747   TValue *tv;
 748   GCcdata *cd;
 749   if (!(ctype_isstruct(ct->info) || ctype_iscomplex(ct->info) ||
 750         ctype_isvector(ct->info)))
 751     lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE);
 752   tv = lj_tab_setinth(L, t, -(int32_t)id);
 753   if (!tvisnil(tv))
 754     lj_err_caller(L, LJ_ERR_PROTMT);
 755   settabV(L, tv, mt);
 756   lj_gc_anybarriert(L, t);
 757   cd = lj_cdata_new(cts, CTID_CTYPEID, 4);
 758   *(CTypeID *)cdataptr(cd) = id;
 759   setcdataV(L, L->top-1, cd);
 760   lj_gc_check(L);
 761   return 1;
 762 }
 763 
 764 LJLIB_PUSH(top-7) LJLIB_SET(!)  /* Store reference to finalizer table. */
 765 
 766 LJLIB_CF(ffi_gc)        LJLIB_REC(.)
 767 {
 768   GCcdata *cd = ffi_checkcdata(L, 1);
 769   TValue *fin = lj_lib_checkany(L, 2);
 770   CTState *cts = ctype_cts(L);
 771   GCtab *t = cts->finalizer;
 772   CType *ct = ctype_raw(cts, cd->ctypeid);
 773   if (!(ctype_isptr(ct->info) || ctype_isstruct(ct->info) ||
 774         ctype_isrefarray(ct->info)))
 775     lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE);
 776   if (gcref(t->metatable)) {  /* Update finalizer table, if still enabled. */
 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. */
 785   return 1;
 786 }
 787 
 788 LJLIB_PUSH(top-5) LJLIB_SET(!)  /* Store clib metatable in func environment. */
 789 
 790 LJLIB_CF(ffi_load)
 791 {
 792   GCstr *name = lj_lib_checkstr(L, 1);
 793   int global = (L->base+1 < L->top && tvistruecond(L->base+1));
 794   lj_clib_load(L, tabref(curr_func(L)->c.env), name, global);
 795   return 1;
 796 }
 797 
 798 LJLIB_PUSH(top-4) LJLIB_SET(C)
 799 LJLIB_PUSH(top-3) LJLIB_SET(os)
 800 LJLIB_PUSH(top-2) LJLIB_SET(arch)
 801 
 802 #include "lj_libdef.h"
 803 
 804 /* ------------------------------------------------------------------------ */
 805 
 806 /* Create special weak-keyed finalizer table. */
 807 static 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. */
 820 static void ffi_register_module(lua_State *L)
 821 {
 822   cTValue *tmp = lj_tab_getstr(tabV(registry(L)), lj_str_newlit(L, "_LOADED"));
 823   if (tmp && tvistab(tmp)) {
 824     GCtab *t = tabV(tmp);
 825     copyTV(L, lj_tab_setstr(L, t, lj_str_newlit(L, LUA_FFILIBNAME)), L->top-1);
 826     lj_gc_anybarriert(L, t);
 827   }
 828 }
 829 
 830 LUALIB_API int luaopen_ffi(lua_State *L)
 831 {
 832   CTState *cts = lj_ctype_init(L);
 833   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);
 836   /* NOBARRIER: basemt is a GC root. */
 837   setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1)));
 838   LJ_LIB_REG(L, NULL, ffi_clib);
 839   LJ_LIB_REG(L, NULL, ffi_callback);
 840   /* NOBARRIER: the key is new and lj_tab_newkey() handles the barrier. */
 841   settabV(L, lj_tab_setstr(L, cts->miscmap, &cts->g->strempty), tabV(L->top-1));
 842   L->top--;
 843   lj_clib_default(L, tabV(L->top-1));  /* Create ffi.C default namespace. */
 844   lua_pushliteral(L, LJ_OS_NAME);
 845   lua_pushliteral(L, LJ_ARCH_NAME);
 846   LJ_LIB_REG(L, NULL, ffi);  /* Note: no global "ffi" created! */
 847   ffi_register_module(L);
 848   return 1;
 849 }
 850 
 851 #endif

/* [<][>][^][v][top][bottom][index][help] */