lib_ffi.c (24638B)
1 /* 2 ** FFI library. 3 ** Copyright (C) 2005-2016 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 280 LJLIB_CF(ffi_meta___bnot) LJLIB_REC(cdata_arith MM_bnot) 281 { 282 return ffi_arith(L); 283 } 284 285 LJLIB_CF(ffi_meta___idiv) LJLIB_REC(cdata_arith MM_idiv) 286 { 287 return ffi_arith(L); 288 } 289 290 LJLIB_CF(ffi_meta___band) LJLIB_REC(cdata_arith MM_band) 291 { 292 return ffi_arith(L); 293 } 294 295 LJLIB_CF(ffi_meta___bor) LJLIB_REC(cdata_arith MM_bor) 296 { 297 return ffi_arith(L); 298 } 299 300 LJLIB_CF(ffi_meta___bxor) LJLIB_REC(cdata_arith MM_bxor) 301 { 302 return ffi_arith(L); 303 } 304 305 LJLIB_CF(ffi_meta___shl) LJLIB_REC(cdata_arith MM_shl) 306 { 307 return ffi_arith(L); 308 } 309 310 LJLIB_CF(ffi_meta___shr) LJLIB_REC(cdata_arith MM_shr) 311 { 312 return ffi_arith(L); 313 } 314 315 /* End of contiguous ORDER MM. */ 316 317 LJLIB_CF(ffi_meta___tostring) 318 { 319 GCcdata *cd = ffi_checkcdata(L, 1); 320 const char *msg = "cdata<%s>: %p"; 321 CTypeID id = cd->ctypeid; 322 void *p = cdataptr(cd); 323 if (id == CTID_CTYPEID) { 324 msg = "ctype<%s>"; 325 id = *(CTypeID *)p; 326 } else { 327 CTState *cts = ctype_cts(L); 328 CType *ct = ctype_raw(cts, id); 329 if (ctype_isref(ct->info)) { 330 p = *(void **)p; 331 ct = ctype_rawchild(cts, ct); 332 } 333 if (ctype_iscomplex(ct->info)) { 334 setstrV(L, L->top-1, lj_ctype_repr_complex(L, cdataptr(cd), ct->size)); 335 goto checkgc; 336 } else if (ct->size == 8 && ctype_isinteger(ct->info)) { 337 setstrV(L, L->top-1, lj_ctype_repr_int64(L, *(uint64_t *)cdataptr(cd), 338 (ct->info & CTF_UNSIGNED))); 339 goto checkgc; 340 } else if (ctype_isfunc(ct->info)) { 341 p = *(void **)p; 342 } else if (ctype_isenum(ct->info)) { 343 msg = "cdata<%s>: %d"; 344 p = (void *)(uintptr_t)*(uint32_t **)p; 345 } else { 346 if (ctype_isptr(ct->info)) { 347 p = cdata_getptr(p, ct->size); 348 ct = ctype_rawchild(cts, ct); 349 } 350 if (ctype_isstruct(ct->info) || ctype_isvector(ct->info)) { 351 /* Handle ctype __tostring metamethod. */ 352 cTValue *tv = lj_ctype_meta(cts, ctype_typeid(cts, ct), MM_tostring); 353 if (tv) 354 return lj_meta_tailcall(L, tv); 355 } 356 } 357 } 358 lj_strfmt_pushf(L, msg, strdata(lj_ctype_repr(L, id, NULL)), p); 359 checkgc: 360 lj_gc_check(L); 361 return 1; 362 } 363 364 static int ffi_pairs(lua_State *L, MMS mm) 365 { 366 CTState *cts = ctype_cts(L); 367 CTypeID id = ffi_checkcdata(L, 1)->ctypeid; 368 CType *ct = ctype_raw(cts, id); 369 cTValue *tv; 370 if (ctype_isptr(ct->info)) id = ctype_cid(ct->info); 371 tv = lj_ctype_meta(cts, id, mm); 372 if (!tv) 373 lj_err_callerv(L, LJ_ERR_FFI_BADMM, strdata(lj_ctype_repr(L, id, NULL)), 374 strdata(mmname_str(G(L), mm))); 375 return lj_meta_tailcall(L, tv); 376 } 377 378 LJLIB_CF(ffi_meta___pairs) 379 { 380 return ffi_pairs(L, MM_pairs); 381 } 382 383 LJLIB_CF(ffi_meta___ipairs) 384 { 385 return ffi_pairs(L, MM_ipairs); 386 } 387 388 LJLIB_PUSH("ffi") LJLIB_SET(__metatable) 389 390 #include "lj_libdef.h" 391 392 /* -- C library metamethods ----------------------------------------------- */ 393 394 #define LJLIB_MODULE_ffi_clib 395 396 /* Index C library by a name. */ 397 static TValue *ffi_clib_index(lua_State *L) 398 { 399 TValue *o = L->base; 400 CLibrary *cl; 401 if (!(o < L->top && tvisudata(o) && udataV(o)->udtype == UDTYPE_FFI_CLIB)) 402 lj_err_argt(L, 1, LUA_TUSERDATA); 403 cl = (CLibrary *)uddata(udataV(o)); 404 if (!(o+1 < L->top && tvisstr(o+1))) 405 lj_err_argt(L, 2, LUA_TSTRING); 406 return lj_clib_index(L, cl, strV(o+1)); 407 } 408 409 LJLIB_CF(ffi_clib___index) LJLIB_REC(clib_index 1) 410 { 411 TValue *tv = ffi_clib_index(L); 412 if (tviscdata(tv)) { 413 CTState *cts = ctype_cts(L); 414 GCcdata *cd = cdataV(tv); 415 CType *s = ctype_get(cts, cd->ctypeid); 416 if (ctype_isextern(s->info)) { 417 CTypeID sid = ctype_cid(s->info); 418 void *sp = *(void **)cdataptr(cd); 419 CType *ct = ctype_raw(cts, sid); 420 if (lj_cconv_tv_ct(cts, ct, sid, L->top-1, sp)) 421 lj_gc_check(L); 422 return 1; 423 } 424 } 425 copyTV(L, L->top-1, tv); 426 return 1; 427 } 428 429 LJLIB_CF(ffi_clib___newindex) LJLIB_REC(clib_index 0) 430 { 431 TValue *tv = ffi_clib_index(L); 432 TValue *o = L->base+2; 433 if (o < L->top && tviscdata(tv)) { 434 CTState *cts = ctype_cts(L); 435 GCcdata *cd = cdataV(tv); 436 CType *d = ctype_get(cts, cd->ctypeid); 437 if (ctype_isextern(d->info)) { 438 CTInfo qual = 0; 439 for (;;) { /* Skip attributes and collect qualifiers. */ 440 d = ctype_child(cts, d); 441 if (!ctype_isattrib(d->info)) break; 442 if (ctype_attrib(d->info) == CTA_QUAL) qual |= d->size; 443 } 444 if (!((d->info|qual) & CTF_CONST)) { 445 lj_cconv_ct_tv(cts, d, *(void **)cdataptr(cd), o, 0); 446 return 0; 447 } 448 } 449 } 450 lj_err_caller(L, LJ_ERR_FFI_WRCONST); 451 return 0; /* unreachable */ 452 } 453 454 LJLIB_CF(ffi_clib___gc) 455 { 456 TValue *o = L->base; 457 if (o < L->top && tvisudata(o) && udataV(o)->udtype == UDTYPE_FFI_CLIB) 458 lj_clib_unload((CLibrary *)uddata(udataV(o))); 459 return 0; 460 } 461 462 #include "lj_libdef.h" 463 464 /* -- Callback function metamethods --------------------------------------- */ 465 466 #define LJLIB_MODULE_ffi_callback 467 468 static int ffi_callback_set(lua_State *L, GCfunc *fn) 469 { 470 GCcdata *cd = ffi_checkcdata(L, 1); 471 CTState *cts = ctype_cts(L); 472 CType *ct = ctype_raw(cts, cd->ctypeid); 473 if (ctype_isptr(ct->info) && (LJ_32 || ct->size == 8)) { 474 MSize slot = lj_ccallback_ptr2slot(cts, *(void **)cdataptr(cd)); 475 if (slot < cts->cb.sizeid && cts->cb.cbid[slot] != 0) { 476 GCtab *t = cts->miscmap; 477 TValue *tv = lj_tab_setint(L, t, (int32_t)slot); 478 if (fn) { 479 setfuncV(L, tv, fn); 480 lj_gc_anybarriert(L, t); 481 } else { 482 setnilV(tv); 483 cts->cb.cbid[slot] = 0; 484 cts->cb.topid = slot < cts->cb.topid ? slot : cts->cb.topid; 485 } 486 return 0; 487 } 488 } 489 lj_err_caller(L, LJ_ERR_FFI_BADCBACK); 490 return 0; 491 } 492 493 LJLIB_CF(ffi_callback_free) 494 { 495 return ffi_callback_set(L, NULL); 496 } 497 498 LJLIB_CF(ffi_callback_set) 499 { 500 GCfunc *fn = lj_lib_checkfunc(L, 2); 501 return ffi_callback_set(L, fn); 502 } 503 504 LJLIB_PUSH(top-1) LJLIB_SET(__index) 505 506 #include "lj_libdef.h" 507 508 /* -- FFI library functions ----------------------------------------------- */ 509 510 #define LJLIB_MODULE_ffi 511 512 LJLIB_CF(ffi_cdef) 513 { 514 GCstr *s = lj_lib_checkstr(L, 1); 515 CPState cp; 516 int errcode; 517 cp.L = L; 518 cp.cts = ctype_cts(L); 519 cp.srcname = strdata(s); 520 cp.p = strdata(s); 521 cp.param = L->base+1; 522 cp.mode = CPARSE_MODE_MULTI|CPARSE_MODE_DIRECT; 523 errcode = lj_cparse(&cp); 524 if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */ 525 lj_gc_check(L); 526 return 0; 527 } 528 529 LJLIB_CF(ffi_new) LJLIB_REC(.) 530 { 531 CTState *cts = ctype_cts(L); 532 CTypeID id = ffi_checkctype(L, cts, NULL); 533 CType *ct = ctype_raw(cts, id); 534 CTSize sz; 535 CTInfo info = lj_ctype_info(cts, id, &sz); 536 TValue *o = L->base+1; 537 GCcdata *cd; 538 if ((info & CTF_VLA)) { 539 o++; 540 sz = lj_ctype_vlsize(cts, ct, (CTSize)ffi_checkint(L, 2)); 541 } 542 if (sz == CTSIZE_INVALID) 543 lj_err_arg(L, 1, LJ_ERR_FFI_INVSIZE); 544 cd = lj_cdata_newx(cts, id, sz, info); 545 setcdataV(L, o-1, cd); /* Anchor the uninitialized cdata. */ 546 lj_cconv_ct_init(cts, ct, sz, cdataptr(cd), 547 o, (MSize)(L->top - o)); /* Initialize cdata. */ 548 if (ctype_isstruct(ct->info)) { 549 cTValue *tv = lj_tab_getinth(cts->miscmap, -(int32_t)id); 550 /* Handle ctype __gc metamethod. Use the fast lookup here. */ 551 if (tv && tvistab(tv) && (tv = lj_meta_fast(L, tabV(tv), MM_gc))) { 552 GCtab *t = cts->finalizer; 553 if (gcref(t->metatable)) { 554 /* Add to finalizer table, if still enabled. */ 555 copyTV(L, lj_tab_set(L, t, o-1), tv); 556 cd->marked |= LJ_GC_FINALIZED; 557 lj_gc_anybarriert(L, t); 558 } 559 } 560 } 561 L->top = o; /* Only return the cdata itself. */ 562 lj_gc_check(L); 563 return 1; 564 } 565 566 LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new) 567 { 568 CTState *cts = ctype_cts(L); 569 CTypeID id = ffi_checkctype(L, cts, NULL); 570 CType *d = ctype_raw(cts, id); 571 TValue *o = lj_lib_checkany(L, 2); 572 L->top = o+1; /* Make sure this is the last item on the stack. */ 573 if (!(ctype_isnum(d->info) || ctype_isptr(d->info) || ctype_isenum(d->info))) 574 lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); 575 if (!(tviscdata(o) && cdataV(o)->ctypeid == id)) { 576 GCcdata *cd = lj_cdata_new(cts, id, d->size); 577 lj_cconv_ct_tv(cts, d, cdataptr(cd), o, CCF_CAST); 578 setcdataV(L, o, cd); 579 lj_gc_check(L); 580 } 581 return 1; 582 } 583 584 LJLIB_CF(ffi_typeof) LJLIB_REC(.) 585 { 586 CTState *cts = ctype_cts(L); 587 CTypeID id = ffi_checkctype(L, cts, L->base+1); 588 GCcdata *cd = lj_cdata_new(cts, CTID_CTYPEID, 4); 589 *(CTypeID *)cdataptr(cd) = id; 590 setcdataV(L, L->top-1, cd); 591 lj_gc_check(L); 592 return 1; 593 } 594 595 /* Internal and unsupported API. */ 596 LJLIB_CF(ffi_typeinfo) 597 { 598 CTState *cts = ctype_cts(L); 599 CTypeID id = (CTypeID)ffi_checkint(L, 1); 600 if (id > 0 && id < cts->top) { 601 CType *ct = ctype_get(cts, id); 602 GCtab *t; 603 lua_createtable(L, 0, 4); /* Increment hash size if fields are added. */ 604 t = tabV(L->top-1); 605 setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "info")), (int32_t)ct->info); 606 if (ct->size != CTSIZE_INVALID) 607 setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "size")), (int32_t)ct->size); 608 if (ct->sib) 609 setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "sib")), (int32_t)ct->sib); 610 if (gcref(ct->name)) { 611 GCstr *s = gco2str(gcref(ct->name)); 612 setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "name")), s); 613 } 614 lj_gc_check(L); 615 return 1; 616 } 617 return 0; 618 } 619 620 LJLIB_CF(ffi_istype) LJLIB_REC(.) 621 { 622 CTState *cts = ctype_cts(L); 623 CTypeID id1 = ffi_checkctype(L, cts, NULL); 624 TValue *o = lj_lib_checkany(L, 2); 625 int b = 0; 626 if (tviscdata(o)) { 627 GCcdata *cd = cdataV(o); 628 CTypeID id2 = cd->ctypeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : 629 cd->ctypeid; 630 CType *ct1 = lj_ctype_rawref(cts, id1); 631 CType *ct2 = lj_ctype_rawref(cts, id2); 632 if (ct1 == ct2) { 633 b = 1; 634 } else if (ctype_type(ct1->info) == ctype_type(ct2->info) && 635 ct1->size == ct2->size) { 636 if (ctype_ispointer(ct1->info)) 637 b = lj_cconv_compatptr(cts, ct1, ct2, CCF_IGNQUAL); 638 else if (ctype_isnum(ct1->info) || ctype_isvoid(ct1->info)) 639 b = (((ct1->info ^ ct2->info) & ~(CTF_QUAL|CTF_LONG)) == 0); 640 } else if (ctype_isstruct(ct1->info) && ctype_isptr(ct2->info) && 641 ct1 == ctype_rawchild(cts, ct2)) { 642 b = 1; 643 } 644 } 645 setboolV(L->top-1, b); 646 setboolV(&G(L)->tmptv2, b); /* Remember for trace recorder. */ 647 return 1; 648 } 649 650 LJLIB_CF(ffi_sizeof) LJLIB_REC(ffi_xof FF_ffi_sizeof) 651 { 652 CTState *cts = ctype_cts(L); 653 CTypeID id = ffi_checkctype(L, cts, NULL); 654 CTSize sz; 655 if (LJ_UNLIKELY(tviscdata(L->base) && cdataisv(cdataV(L->base)))) { 656 sz = cdatavlen(cdataV(L->base)); 657 } else { 658 CType *ct = lj_ctype_rawref(cts, id); 659 if (ctype_isvltype(ct->info)) 660 sz = lj_ctype_vlsize(cts, ct, (CTSize)ffi_checkint(L, 2)); 661 else 662 sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_INVALID; 663 if (LJ_UNLIKELY(sz == CTSIZE_INVALID)) { 664 setnilV(L->top-1); 665 return 1; 666 } 667 } 668 setintV(L->top-1, (int32_t)sz); 669 return 1; 670 } 671 672 LJLIB_CF(ffi_alignof) LJLIB_REC(ffi_xof FF_ffi_alignof) 673 { 674 CTState *cts = ctype_cts(L); 675 CTypeID id = ffi_checkctype(L, cts, NULL); 676 CTSize sz = 0; 677 CTInfo info = lj_ctype_info(cts, id, &sz); 678 setintV(L->top-1, 1 << ctype_align(info)); 679 return 1; 680 } 681 682 LJLIB_CF(ffi_offsetof) LJLIB_REC(ffi_xof FF_ffi_offsetof) 683 { 684 CTState *cts = ctype_cts(L); 685 CTypeID id = ffi_checkctype(L, cts, NULL); 686 GCstr *name = lj_lib_checkstr(L, 2); 687 CType *ct = lj_ctype_rawref(cts, id); 688 CTSize ofs; 689 if (ctype_isstruct(ct->info) && ct->size != CTSIZE_INVALID) { 690 CType *fct = lj_ctype_getfield(cts, ct, name, &ofs); 691 if (fct) { 692 setintV(L->top-1, ofs); 693 if (ctype_isfield(fct->info)) { 694 return 1; 695 } else if (ctype_isbitfield(fct->info)) { 696 setintV(L->top++, ctype_bitpos(fct->info)); 697 setintV(L->top++, ctype_bitbsz(fct->info)); 698 return 3; 699 } 700 } 701 } 702 return 0; 703 } 704 705 LJLIB_CF(ffi_errno) LJLIB_REC(.) 706 { 707 int err = errno; 708 if (L->top > L->base) 709 errno = ffi_checkint(L, 1); 710 setintV(L->top++, err); 711 return 1; 712 } 713 714 LJLIB_CF(ffi_string) LJLIB_REC(.) 715 { 716 CTState *cts = ctype_cts(L); 717 TValue *o = lj_lib_checkany(L, 1); 718 const char *p; 719 size_t len; 720 if (o+1 < L->top && !tvisnil(o+1)) { 721 len = (size_t)ffi_checkint(L, 2); 722 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p, o, 723 CCF_ARG(1)); 724 } else { 725 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CCHAR), (uint8_t *)&p, o, 726 CCF_ARG(1)); 727 len = strlen(p); 728 } 729 L->top = o+1; /* Make sure this is the last item on the stack. */ 730 setstrV(L, o, lj_str_new(L, p, len)); 731 lj_gc_check(L); 732 return 1; 733 } 734 735 /* Pointer to GCstr followed by string contents is expected. */ 736 LJLIB_CF(ffi_strbuf) LJLIB_REC(.) 737 { 738 GCstr *s = ffi_checkptr(L, 1, CTID_P_CVOID); 739 TValue *o = L->top-1; 740 /* Caller is responsible for passing pointer fitting into 32 bits. */ 741 lua_assert(((ptrdiff_t)s) <= 0xffffffff); 742 s->marked = LJ_GC_FIXED | LJ_GC_SFIXED; 743 s->gct = ~LJ_TSTR; 744 /* NOBARRIER: not actually tracked by GC. */ 745 setgcrefnull(obj2gco(s)->gch.nextgc); 746 setstrV(L, o, s); 747 setitype(o, LJ_TSTR); 748 return 1; 749 } 750 751 LJLIB_CF(ffi_copy) LJLIB_REC(.) 752 { 753 void *dp = ffi_checkptr(L, 1, CTID_P_VOID); 754 void *sp = ffi_checkptr(L, 2, CTID_P_CVOID); 755 TValue *o = L->base+1; 756 CTSize len; 757 if (tvisstr(o) && o+1 >= L->top) 758 len = strV(o)->len+1; /* Copy Lua string including trailing '\0'. */ 759 else 760 len = (CTSize)ffi_checkint(L, 3); 761 memcpy(dp, sp, len); 762 return 0; 763 } 764 765 LJLIB_CF(ffi_fill) LJLIB_REC(.) 766 { 767 void *dp = ffi_checkptr(L, 1, CTID_P_VOID); 768 CTSize len = (CTSize)ffi_checkint(L, 2); 769 int32_t fill = 0; 770 if (L->base+2 < L->top && !tvisnil(L->base+2)) fill = ffi_checkint(L, 3); 771 memset(dp, fill, len); 772 return 0; 773 } 774 775 #define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be) 776 777 /* Test ABI string. */ 778 LJLIB_CF(ffi_abi) LJLIB_REC(.) 779 { 780 GCstr *s = lj_lib_checkstr(L, 1); 781 int b = 0; 782 switch (s->hash) { 783 #if LJ_64 784 case H_(849858eb,ad35fd06): b = 1; break; /* 64bit */ 785 #else 786 case H_(662d3c79,d0e22477): b = 1; break; /* 32bit */ 787 #endif 788 #if LJ_ARCH_HASFPU 789 case H_(e33ee463,e33ee463): b = 1; break; /* fpu */ 790 #endif 791 #if LJ_ABI_SOFTFP 792 case H_(61211a23,c2e8c81c): b = 1; break; /* softfp */ 793 #else 794 case H_(539417a8,8ce0812f): b = 1; break; /* hardfp */ 795 #endif 796 #if LJ_ABI_EABI 797 case H_(2182df8f,f2ed1152): b = 1; break; /* eabi */ 798 #endif 799 #if LJ_ABI_WIN 800 case H_(4ab624a8,4ab624a8): b = 1; break; /* win */ 801 #endif 802 case H_(3af93066,1f001464): b = 1; break; /* le/be */ 803 #if LJ_GC64 804 case H_(9e89d2c9,13c83c92): b = 1; break; /* gc64 */ 805 #endif 806 default: 807 break; 808 } 809 setboolV(L->top-1, b); 810 setboolV(&G(L)->tmptv2, b); /* Remember for trace recorder. */ 811 return 1; 812 } 813 814 #undef H_ 815 816 LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to miscmap table. */ 817 LJLIB_PUSH(top-8) LJLIB_SET(miscmap) /* Expose to user. */ 818 819 LJLIB_CF(ffi_metatype) 820 { 821 CTState *cts = ctype_cts(L); 822 CTypeID id = ffi_checkctype(L, cts, NULL); 823 GCtab *mt = lj_lib_checktab(L, 2); 824 GCtab *t = cts->miscmap; 825 CType *ct = ctype_get(cts, id); /* Only allow raw types. */ 826 TValue *tv; 827 GCcdata *cd; 828 if (!(ctype_isstruct(ct->info) || ctype_iscomplex(ct->info) || 829 ctype_isvector(ct->info) || ctype_isnum(ct->info))) 830 lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); 831 if (ctype_isnum(ct->info)) { /* Duplicate it. */ 832 CType *nct; 833 id = lj_ctype_new(cts, &nct); 834 /* Copy fields. */ 835 nct->info = ct->info; 836 nct->size = ct->size; 837 nct->sib = ct->sib; 838 nct->next = ct->next; 839 /* For repr; abstract name always refers to the original. */ 840 setgcrefr(nct->name, ct->name); 841 ct = nct; 842 } 843 tv = lj_tab_setinth(L, t, -(int32_t)id); 844 if (!tvisnil(tv)) 845 lj_err_caller(L, LJ_ERR_PROTMT); 846 settabV(L, tv, mt); 847 lj_gc_anybarriert(L, t); 848 cd = lj_cdata_new(cts, CTID_CTYPEID, 4); 849 *(CTypeID *)cdataptr(cd) = id; 850 setcdataV(L, L->top-1, cd); 851 lj_gc_check(L); 852 return 1; 853 } 854 855 LJLIB_PUSH(top-7) LJLIB_SET(!) /* Store reference to finalizer table. */ 856 857 LJLIB_CF(ffi_gc) LJLIB_REC(.) 858 { 859 GCcdata *cd = ffi_checkcdata(L, 1); 860 TValue *fin = lj_lib_checkany(L, 2); 861 CTState *cts = ctype_cts(L); 862 CType *ct = ctype_raw(cts, cd->ctypeid); 863 if (!(ctype_isptr(ct->info) || ctype_isstruct(ct->info) || 864 ctype_isrefarray(ct->info))) 865 lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); 866 lj_cdata_setfin(L, cd, gcval(fin), itype(fin)); 867 L->top = L->base+1; /* Pass through the cdata object. */ 868 return 1; 869 } 870 871 LJLIB_PUSH(top-5) LJLIB_SET(!) /* Store clib metatable in func environment. */ 872 873 LJLIB_CF(ffi_load) 874 { 875 GCstr *name = lj_lib_checkstr(L, 1); 876 int global = (L->base+1 < L->top && tvistruecond(L->base+1)); 877 lj_clib_load(L, tabref(curr_func(L)->c.env), name, global); 878 return 1; 879 } 880 881 LJLIB_PUSH(top-4) LJLIB_SET(C) 882 LJLIB_PUSH(top-3) LJLIB_SET(os) 883 LJLIB_PUSH(top-2) LJLIB_SET(arch) 884 885 #include "lj_libdef.h" 886 887 /* ------------------------------------------------------------------------ */ 888 889 /* Create special weak-keyed finalizer table. */ 890 static GCtab *ffi_finalizer(lua_State *L) 891 { 892 /* NOBARRIER: The table is new (marked white). */ 893 GCtab *t = lj_tab_new(L, 0, 1); 894 settabV(L, L->top++, t); 895 setgcref(t->metatable, obj2gco(t)); 896 setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")), 897 lj_str_newlit(L, "K")); 898 t->nomm = (uint8_t)(~(1u<<MM_mode)); 899 return t; 900 } 901 902 /* Register FFI module as loaded. */ 903 #if 0 904 static void ffi_register_module(lua_State *L) 905 { 906 cTValue *tmp = lj_tab_getstr(tabV(registry(L)), lj_str_newlit(L, "_LOADED")); 907 if (tmp && tvistab(tmp)) { 908 GCtab *t = tabV(tmp); 909 copyTV(L, lj_tab_setstr(L, t, lj_str_newlit(L, LUA_FFILIBNAME)), L->top-1); 910 lj_gc_anybarriert(L, t); 911 } 912 } 913 #endif 914 915 LUALIB_API int luaopen_ffi(lua_State *L) 916 { 917 CTState *cts = lj_ctype_init(L); 918 settabV(L, L->top++, (cts->miscmap = lj_tab_new(L, 0, 1))); 919 cts->finalizer = ffi_finalizer(L); 920 LJ_LIB_REG(L, NULL, ffi_meta); 921 /* NOBARRIER: basemt is a GC root. */ 922 setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1))); 923 LJ_LIB_REG(L, NULL, ffi_clib); 924 LJ_LIB_REG(L, NULL, ffi_callback); 925 /* NOBARRIER: the key is new and lj_tab_newkey() handles the barrier. */ 926 settabV(L, lj_tab_setstr(L, cts->miscmap, &cts->g->strempty), tabV(L->top-1)); 927 L->top--; 928 lj_clib_default(L, tabV(L->top-1)); /* Create ffi.C default namespace. */ 929 lua_pushliteral(L, LJ_OS_NAME); 930 lua_pushliteral(L, LJ_ARCH_NAME); 931 LJ_LIB_REG(L, NULL, ffi); /* Note: no global "ffi" created! */ 932 #if 0 933 ffi_register_module(L); 934 #endif 935 return 1; 936 } 937 938 #endif