]> git.ipfire.org Git - thirdparty/LuaJIT.git/commitdiff
FFI: Add ffi.istype() function.
authorMike Pall <mike>
Tue, 19 Apr 2011 23:53:26 +0000 (01:53 +0200)
committerMike Pall <mike>
Tue, 19 Apr 2011 23:53:26 +0000 (01:53 +0200)
doc/ext_ffi_api.html
src/lib_ffi.c
src/lj_crecord.c
src/lj_crecord.h

index 2b6d1d867e6bc971eb546627124d4f2919ef60cc..b1b428783f6a64db0346a23dddc57539752d5819 100644 (file)
@@ -316,6 +316,24 @@ of <tt>ct</tt>, which must be a <tt>struct</tt>. Additionally returns
 the position and the field size (in bits) for bit fields.
 </p>
 
+<h3 id="ffi_istype"><tt>status = ffi.istype(ct, obj)</tt></h3>
+<p>
+Returns <tt>true</tt> if <tt>obj</tt> has the C&nbsp;type given by
+<tt>ct</tt>. Returns <tt>false</tt> otherwise.
+</p>
+<p>
+C&nbsp;type qualifiers (<tt>const</tt> etc.) are ignored. Pointers are
+checked with the standard pointer compatibility rules, but without any
+special treatment for <tt>void&nbsp;*</tt>. If <tt>ct</tt> specifies a
+<tt>struct</tt>/<tt>union</tt>, then a pointer to this type is accepted,
+too. Otherwise the types must match exactly.
+</p>
+<p>
+Note: this function accepts all kinds of Lua objects for the
+<tt>obj</tt> argument, but always returns <tt>false</tt> for non-cdata
+objects.
+</p>
+
 <h2 id="util">Utility Functions</h2>
 
 <h3 id="ffi_string"><tt>str = ffi.string(ptr [,len])</tt></h3>
index fe84ca7d8d472107f27917bb2136ae0d9efdcb67..27996f0e42afebd3bd49c6582a74482168ece818 100644 (file)
@@ -456,6 +456,36 @@ LJLIB_CF(ffi_typeof)
   return 1;
 }
 
+LJLIB_CF(ffi_istype)   LJLIB_REC(ffi_istype)
+{
+  CTState *cts = ctype_cts(L);
+  CTypeID id1 = ffi_checkctype(L, cts);
+  TValue *o = lj_lib_checkany(L, 2);
+  int b = 0;
+  if (tviscdata(o)) {
+    GCcdata *cd = cdataV(o);
+    CTypeID id2 = cd->typeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) :
+                                              cd->typeid;
+    CType *ct1 = lj_ctype_rawref(cts, id1);
+    CType *ct2 = lj_ctype_rawref(cts, id2);
+    if (ct1 == ct2) {
+      b = 1;
+    } else if (ctype_type(ct1->info) == ctype_type(ct2->info) &&
+              ct1->size == ct2->size) {
+      if (ctype_ispointer(ct1->info))
+       b = lj_cconv_compatptr(cts, ct1, ct2, CCF_IGNQUAL);
+      else if (ctype_isnum(ct1->info) || ctype_isvoid(ct1->info))
+       b = (((ct1->info ^ ct2->info) & ~CTF_QUAL) == 0);
+    } else if (ctype_isstruct(ct1->info) && ctype_isptr(ct2->info) &&
+              ct1 == ctype_rawchild(cts, ct2)) {
+      b = 1;
+    }
+  }
+  setboolV(L->top-1, b);
+  setboolV(&G(L)->tmptv2, b);  /* Remember for trace recorder. */
+  return 1;
+}
+
 LJLIB_CF(ffi_sizeof)
 {
   CTState *cts = ctype_cts(L);
index 83c57063c2923b9fca45cd0b41133773c1d1d7a8..8330faaf1aacf1a3dcd81997f05613c83d81b54c 100644 (file)
@@ -51,6 +51,18 @@ static GCcdata *argv2cdata(jit_State *J, TRef tr, cTValue *o)
   return cd;
 }
 
+/* Specialize to the CTypeID held by a cdata constructor. */
+static CTypeID crec_constructor(jit_State *J, GCcdata *cd, TRef tr)
+{
+  CTypeID id;
+  lua_assert(tref_iscdata(tr) && cd->typeid == CTID_CTYPEID);
+  id = *(CTypeID *)cdataptr(cd);
+  tr = emitir(IRT(IR_ADD, IRT_PTR), tr, lj_ir_kintp(J, sizeof(GCcdata)));
+  tr = emitir(IRT(IR_XLOAD, IRT_INT), tr, 0);
+  emitir(IRTG(IR_EQ, IRT_INT), tr, lj_ir_kint(J, (int32_t)id));
+  return id;
+}
+
 static CTypeID argv2ctype(jit_State *J, TRef tr, cTValue *o)
 {
   if (tref_isstr(tr)) {
@@ -70,7 +82,8 @@ static CTypeID argv2ctype(jit_State *J, TRef tr, cTValue *o)
     return cp.val.id;
   } else {
     GCcdata *cd = argv2cdata(J, tr, o);
-    return cd->typeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : cd->typeid;
+    return cd->typeid == CTID_CTYPEID ? crec_constructor(J, cd, tr) :
+                                       cd->typeid;
   }
 }
 
@@ -427,18 +440,6 @@ doconv:
 
 /* -- C data metamethods -------------------------------------------------- */
 
-/* Specialize to the CTypeID held by a cdata constructor. */
-static CTypeID crec_constructor(jit_State *J, GCcdata *cd, TRef tr)
-{
-  CTypeID id;
-  lua_assert(tref_iscdata(tr) && cd->typeid == CTID_CTYPEID);
-  id = *(CTypeID *)cdataptr(cd);
-  tr = emitir(IRT(IR_ADD, IRT_PTR), tr, lj_ir_kintp(J, sizeof(GCcdata)));
-  tr = emitir(IRT(IR_XLOAD, IRT_INT), tr, 0);
-  emitir(IRTG(IR_EQ, IRT_INT), tr, lj_ir_kint(J, (int32_t)id));
-  return id;
-}
-
 /* This would be rather difficult in FOLD, so do it here:
 ** (base+k)+(idx*sz)+ofs ==> (base+idx*sz)+(ofs+k)
 ** (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)
   }  /* else: interpreter will throw. */
 }
 
+void LJ_FASTCALL recff_ffi_istype(jit_State *J, RecordFFData *rd)
+{
+  argv2ctype(J, J->base[0], &rd->argv[0]);
+  if (tref_iscdata(J->base[1])) {
+    argv2ctype(J, J->base[1], &rd->argv[1]);
+    J->postproc = LJ_POST_FIXBOOL;
+    J->base[0] = TREF_TRUE;
+  } else {
+    J->base[0] = TREF_FALSE;
+  }
+}
+
 void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd)
 {
   if (tref_isstr(J->base[0])) {
index 0199e0ebaa573988dbc41b8cad1cb157b8f10c60..fce45afed4e56e866839dadf8f5a9a1bbba89c00 100644 (file)
@@ -19,6 +19,7 @@ LJ_FUNC void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd);
 LJ_FUNC void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd);
 LJ_FUNC void LJ_FASTCALL recff_ffi_copy(jit_State *J, RecordFFData *rd);
 LJ_FUNC void LJ_FASTCALL recff_ffi_fill(jit_State *J, RecordFFData *rd);
+LJ_FUNC void LJ_FASTCALL recff_ffi_istype(jit_State *J, RecordFFData *rd);
 LJ_FUNC void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd);
 LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd);
 #else
@@ -30,6 +31,7 @@ LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd);
 #define recff_ffi_string       recff_nyi
 #define recff_ffi_copy         recff_nyi
 #define recff_ffi_fill         recff_nyi
+#define recff_ffi_istype       recff_nyi
 #define recff_ffi_abi          recff_nyi
 #endif