]> git.ipfire.org Git - thirdparty/LuaJIT.git/commitdiff
FFI: Resolve __call metamethod for pointers, too.
authorMike Pall <mike>
Mon, 14 Nov 2011 11:01:48 +0000 (12:01 +0100)
committerMike Pall <mike>
Mon, 14 Nov 2011 11:01:48 +0000 (12:01 +0100)
src/lib_ffi.c
src/lj_crecord.c

index 82942e44c3616af5c668170a1a45b12775c93715..af5001188c978c6c5c23b57897413e670a478abc 100644 (file)
@@ -207,7 +207,10 @@ LJLIB_CF(ffi_meta___concat)        LJLIB_REC(cdata_arith MM_concat)
 static int ffi_call_meta(lua_State *L, CTypeID id)
 {
   CTState *cts = ctype_cts(L);
-  cTValue *tv = lj_ctype_meta(cts, id, MM_call);
+  CType *ct = ctype_raw(cts, id);
+  cTValue *tv;
+  if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
+  tv = lj_ctype_meta(cts, id, MM_call);
   if (!tv)
     lj_err_callerv(L, LJ_ERR_FFI_BADCALL, strdata(lj_ctype_repr(L, id, NULL)));
   return lj_meta_tailcall(L, tv);
index 3dd6f4958637d536a8258a80a8683f23cca6cb29..2c63e8a64cbea1dd202b0c0bb56450c36c0f9ba4 100644 (file)
@@ -890,13 +890,30 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd)
   return 0;
 }
 
+/* Record ctype call metamethod. */
+static void crec_call_meta(jit_State *J, RecordFFData *rd, CTypeID id)
+{
+  CTState *cts = ctype_ctsG(J2G(J));
+  CType *ct = ctype_raw(cts, id);
+  cTValue *tv;
+  if (ctype_isptr(ct->info)) id = ctype_cid(ct->info);
+  tv = lj_ctype_meta(cts, id, MM_call);
+  if (tv && tvisfunc(tv)) {
+    J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME;
+    rd->nres = -1;  /* Pending tailcall. */
+  } else {
+    /* NYI: non-function metamethods. */
+    lj_trace_err(J, LJ_TRERR_BADTYPE);
+  }
+}
+
 void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd)
 {
   GCcdata *cd = argv2cdata(J, J->base[0], &rd->argv[0]);
   if (cd->typeid == CTID_CTYPEID)
     crec_alloc(J, rd, crec_constructor(J, cd, J->base[0]));
   else if (!crec_call(J, rd, cd))
-    lj_trace_err(J, LJ_TRERR_BADTYPE);
+    crec_call_meta(J, rd, cd->typeid);
 }
 
 static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm)