aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/ext_ffi_api.html18
-rw-r--r--src/lib_ffi.c30
-rw-r--r--src/lj_crecord.c39
-rw-r--r--src/lj_crecord.h2
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
316the position and the field size (in bits) for bit fields. 316the 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>
321Returns <tt>true</tt> if <tt>obj</tt> has the C&nbsp;type given by
322<tt>ct</tt>. Returns <tt>false</tt> otherwise.
323</p>
324<p>
325C&nbsp;type qualifiers (<tt>const</tt> etc.) are ignored. Pointers are
326checked with the standard pointer compatibility rules, but without any
327special treatment for <tt>void&nbsp;*</tt>. If <tt>ct</tt> specifies a
328<tt>struct</tt>/<tt>union</tt>, then a pointer to this type is accepted,
329too. Otherwise the types must match exactly.
330</p>
331<p>
332Note: this function accepts all kinds of Lua objects for the
333<tt>obj</tt> argument, but always returns <tt>false</tt> for non-cdata
334objects.
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
459LJLIB_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
459LJLIB_CF(ffi_sizeof) 489LJLIB_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. */
55static 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
54static CTypeID argv2ctype(jit_State *J, TRef tr, cTValue *o) 66static 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. */
431static 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
1104void 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
1103void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd) 1116void 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);
19LJ_FUNC void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd); 19LJ_FUNC void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd);
20LJ_FUNC void LJ_FASTCALL recff_ffi_copy(jit_State *J, RecordFFData *rd); 20LJ_FUNC void LJ_FASTCALL recff_ffi_copy(jit_State *J, RecordFFData *rd);
21LJ_FUNC void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd); 21LJ_FUNC void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd);
22LJ_FUNC void LJ_FASTCALL recff_ffi_istype(jit_State *J, RecordFFData *rd);
22LJ_FUNC void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd); 23LJ_FUNC void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd);
23LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); 24LJ_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