diff options
| author | Mike Pall <mike> | 2011-04-20 01:53:26 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2011-04-20 01:53:26 +0200 |
| commit | 5d096dcfdef5ddb0e6dd67e155adf893df7d7809 (patch) | |
| tree | 9bdbd2852738e761b1b2f0f1858eb91f22a8e638 | |
| parent | 9ea679410c8061741a49350b3fc969365ffe5547 (diff) | |
| download | luajit-5d096dcfdef5ddb0e6dd67e155adf893df7d7809.tar.gz luajit-5d096dcfdef5ddb0e6dd67e155adf893df7d7809.tar.bz2 luajit-5d096dcfdef5ddb0e6dd67e155adf893df7d7809.zip | |
FFI: Add ffi.istype() function.
| -rw-r--r-- | doc/ext_ffi_api.html | 18 | ||||
| -rw-r--r-- | src/lib_ffi.c | 30 | ||||
| -rw-r--r-- | src/lj_crecord.c | 39 | ||||
| -rw-r--r-- | src/lj_crecord.h | 2 |
4 files changed, 76 insertions, 13 deletions
diff --git a/doc/ext_ffi_api.html b/doc/ext_ffi_api.html index 2b6d1d86..b1b42878 100644 --- a/doc/ext_ffi_api.html +++ b/doc/ext_ffi_api.html | |||
| @@ -316,6 +316,24 @@ of <tt>ct</tt>, which must be a <tt>struct</tt>. Additionally returns | |||
| 316 | the position and the field size (in bits) for bit fields. | 316 | the position and the field size (in bits) for bit fields. |
| 317 | </p> | 317 | </p> |
| 318 | 318 | ||
| 319 | <h3 id="ffi_istype"><tt>status = ffi.istype(ct, obj)</tt></h3> | ||
| 320 | <p> | ||
| 321 | Returns <tt>true</tt> if <tt>obj</tt> has the C type given by | ||
| 322 | <tt>ct</tt>. Returns <tt>false</tt> otherwise. | ||
| 323 | </p> | ||
| 324 | <p> | ||
| 325 | C type qualifiers (<tt>const</tt> etc.) are ignored. Pointers are | ||
| 326 | checked with the standard pointer compatibility rules, but without any | ||
| 327 | special treatment for <tt>void *</tt>. If <tt>ct</tt> specifies a | ||
| 328 | <tt>struct</tt>/<tt>union</tt>, then a pointer to this type is accepted, | ||
| 329 | too. Otherwise the types must match exactly. | ||
| 330 | </p> | ||
| 331 | <p> | ||
| 332 | Note: this function accepts all kinds of Lua objects for the | ||
| 333 | <tt>obj</tt> argument, but always returns <tt>false</tt> for non-cdata | ||
| 334 | objects. | ||
| 335 | </p> | ||
| 336 | |||
| 319 | <h2 id="util">Utility Functions</h2> | 337 | <h2 id="util">Utility Functions</h2> |
| 320 | 338 | ||
| 321 | <h3 id="ffi_string"><tt>str = ffi.string(ptr [,len])</tt></h3> | 339 | <h3 id="ffi_string"><tt>str = ffi.string(ptr [,len])</tt></h3> |
diff --git a/src/lib_ffi.c b/src/lib_ffi.c index fe84ca7d..27996f0e 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c | |||
| @@ -456,6 +456,36 @@ LJLIB_CF(ffi_typeof) | |||
| 456 | return 1; | 456 | return 1; |
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | LJLIB_CF(ffi_istype) LJLIB_REC(ffi_istype) | ||
| 460 | { | ||
| 461 | CTState *cts = ctype_cts(L); | ||
| 462 | CTypeID id1 = ffi_checkctype(L, cts); | ||
| 463 | TValue *o = lj_lib_checkany(L, 2); | ||
| 464 | int b = 0; | ||
| 465 | if (tviscdata(o)) { | ||
| 466 | GCcdata *cd = cdataV(o); | ||
| 467 | CTypeID id2 = cd->typeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : | ||
| 468 | cd->typeid; | ||
| 469 | CType *ct1 = lj_ctype_rawref(cts, id1); | ||
| 470 | CType *ct2 = lj_ctype_rawref(cts, id2); | ||
| 471 | if (ct1 == ct2) { | ||
| 472 | b = 1; | ||
| 473 | } else if (ctype_type(ct1->info) == ctype_type(ct2->info) && | ||
| 474 | ct1->size == ct2->size) { | ||
| 475 | if (ctype_ispointer(ct1->info)) | ||
| 476 | b = lj_cconv_compatptr(cts, ct1, ct2, CCF_IGNQUAL); | ||
| 477 | else if (ctype_isnum(ct1->info) || ctype_isvoid(ct1->info)) | ||
| 478 | b = (((ct1->info ^ ct2->info) & ~CTF_QUAL) == 0); | ||
| 479 | } else if (ctype_isstruct(ct1->info) && ctype_isptr(ct2->info) && | ||
| 480 | ct1 == ctype_rawchild(cts, ct2)) { | ||
| 481 | b = 1; | ||
| 482 | } | ||
| 483 | } | ||
| 484 | setboolV(L->top-1, b); | ||
| 485 | setboolV(&G(L)->tmptv2, b); /* Remember for trace recorder. */ | ||
| 486 | return 1; | ||
| 487 | } | ||
| 488 | |||
| 459 | LJLIB_CF(ffi_sizeof) | 489 | LJLIB_CF(ffi_sizeof) |
| 460 | { | 490 | { |
| 461 | CTState *cts = ctype_cts(L); | 491 | CTState *cts = ctype_cts(L); |
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 83c57063..8330faaf 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c | |||
| @@ -51,6 +51,18 @@ static GCcdata *argv2cdata(jit_State *J, TRef tr, cTValue *o) | |||
| 51 | return cd; | 51 | return cd; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | /* Specialize to the CTypeID held by a cdata constructor. */ | ||
| 55 | static CTypeID crec_constructor(jit_State *J, GCcdata *cd, TRef tr) | ||
| 56 | { | ||
| 57 | CTypeID id; | ||
| 58 | lua_assert(tref_iscdata(tr) && cd->typeid == CTID_CTYPEID); | ||
| 59 | id = *(CTypeID *)cdataptr(cd); | ||
| 60 | tr = emitir(IRT(IR_ADD, IRT_PTR), tr, lj_ir_kintp(J, sizeof(GCcdata))); | ||
| 61 | tr = emitir(IRT(IR_XLOAD, IRT_INT), tr, 0); | ||
| 62 | emitir(IRTG(IR_EQ, IRT_INT), tr, lj_ir_kint(J, (int32_t)id)); | ||
| 63 | return id; | ||
| 64 | } | ||
| 65 | |||
| 54 | static CTypeID argv2ctype(jit_State *J, TRef tr, cTValue *o) | 66 | static CTypeID argv2ctype(jit_State *J, TRef tr, cTValue *o) |
| 55 | { | 67 | { |
| 56 | if (tref_isstr(tr)) { | 68 | if (tref_isstr(tr)) { |
| @@ -70,7 +82,8 @@ static CTypeID argv2ctype(jit_State *J, TRef tr, cTValue *o) | |||
| 70 | return cp.val.id; | 82 | return cp.val.id; |
| 71 | } else { | 83 | } else { |
| 72 | GCcdata *cd = argv2cdata(J, tr, o); | 84 | GCcdata *cd = argv2cdata(J, tr, o); |
| 73 | return cd->typeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : cd->typeid; | 85 | return cd->typeid == CTID_CTYPEID ? crec_constructor(J, cd, tr) : |
| 86 | cd->typeid; | ||
| 74 | } | 87 | } |
| 75 | } | 88 | } |
| 76 | 89 | ||
| @@ -427,18 +440,6 @@ doconv: | |||
| 427 | 440 | ||
| 428 | /* -- C data metamethods -------------------------------------------------- */ | 441 | /* -- C data metamethods -------------------------------------------------- */ |
| 429 | 442 | ||
| 430 | /* Specialize to the CTypeID held by a cdata constructor. */ | ||
| 431 | static CTypeID crec_constructor(jit_State *J, GCcdata *cd, TRef tr) | ||
| 432 | { | ||
| 433 | CTypeID id; | ||
| 434 | lua_assert(tref_iscdata(tr) && cd->typeid == CTID_CTYPEID); | ||
| 435 | id = *(CTypeID *)cdataptr(cd); | ||
| 436 | tr = emitir(IRT(IR_ADD, IRT_PTR), tr, lj_ir_kintp(J, sizeof(GCcdata))); | ||
| 437 | tr = emitir(IRT(IR_XLOAD, IRT_INT), tr, 0); | ||
| 438 | emitir(IRTG(IR_EQ, IRT_INT), tr, lj_ir_kint(J, (int32_t)id)); | ||
| 439 | return id; | ||
| 440 | } | ||
| 441 | |||
| 442 | /* This would be rather difficult in FOLD, so do it here: | 443 | /* This would be rather difficult in FOLD, so do it here: |
| 443 | ** (base+k)+(idx*sz)+ofs ==> (base+idx*sz)+(ofs+k) | 444 | ** (base+k)+(idx*sz)+ofs ==> (base+idx*sz)+(ofs+k) |
| 444 | ** (base+(idx+k)*sz)+ofs ==> (base+idx*sz)+(ofs+k*sz) | 445 | ** (base+(idx+k)*sz)+ofs ==> (base+idx*sz)+(ofs+k*sz) |
| @@ -1100,6 +1101,18 @@ void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd) | |||
| 1100 | } /* else: interpreter will throw. */ | 1101 | } /* else: interpreter will throw. */ |
| 1101 | } | 1102 | } |
| 1102 | 1103 | ||
| 1104 | void LJ_FASTCALL recff_ffi_istype(jit_State *J, RecordFFData *rd) | ||
| 1105 | { | ||
| 1106 | argv2ctype(J, J->base[0], &rd->argv[0]); | ||
| 1107 | if (tref_iscdata(J->base[1])) { | ||
| 1108 | argv2ctype(J, J->base[1], &rd->argv[1]); | ||
| 1109 | J->postproc = LJ_POST_FIXBOOL; | ||
| 1110 | J->base[0] = TREF_TRUE; | ||
| 1111 | } else { | ||
| 1112 | J->base[0] = TREF_FALSE; | ||
| 1113 | } | ||
| 1114 | } | ||
| 1115 | |||
| 1103 | void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd) | 1116 | void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd) |
| 1104 | { | 1117 | { |
| 1105 | if (tref_isstr(J->base[0])) { | 1118 | if (tref_isstr(J->base[0])) { |
diff --git a/src/lj_crecord.h b/src/lj_crecord.h index 0199e0eb..fce45afe 100644 --- a/src/lj_crecord.h +++ b/src/lj_crecord.h | |||
| @@ -19,6 +19,7 @@ LJ_FUNC void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd); | |||
| 19 | LJ_FUNC void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd); | 19 | LJ_FUNC void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd); |
| 20 | LJ_FUNC void LJ_FASTCALL recff_ffi_copy(jit_State *J, RecordFFData *rd); | 20 | LJ_FUNC void LJ_FASTCALL recff_ffi_copy(jit_State *J, RecordFFData *rd); |
| 21 | LJ_FUNC void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd); | 21 | LJ_FUNC void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd); |
| 22 | LJ_FUNC void LJ_FASTCALL recff_ffi_istype(jit_State *J, RecordFFData *rd); | ||
| 22 | LJ_FUNC void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd); | 23 | LJ_FUNC void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd); |
| 23 | LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); | 24 | LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); |
| 24 | #else | 25 | #else |
| @@ -30,6 +31,7 @@ LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); | |||
| 30 | #define recff_ffi_string recff_nyi | 31 | #define recff_ffi_string recff_nyi |
| 31 | #define recff_ffi_copy recff_nyi | 32 | #define recff_ffi_copy recff_nyi |
| 32 | #define recff_ffi_fill recff_nyi | 33 | #define recff_ffi_fill recff_nyi |
| 34 | #define recff_ffi_istype recff_nyi | ||
| 33 | #define recff_ffi_abi recff_nyi | 35 | #define recff_ffi_abi recff_nyi |
| 34 | #endif | 36 | #endif |
| 35 | 37 | ||
