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

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