[PATCH] compile tonumber(enum) and ffi.typeof(cdata)

  • From: "Robert G. Jakabosky" <bobby@xxxxxxxxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Mon, 6 Aug 2012 16:28:31 -0700

The two patches add support for compiling a few NYI cases.
Patch 1:
* tonumber(enum) or tonumber(ctype)
* Initializing a enum field in a structure.
Patch 2:
* ffi.typeof(cdata)

Also attached are two test scripts that showcase the NYI cases.

-- 
Robert G. Jakabosky
From 5f322731e633cc8d0f273a3476662c27b4830513 Mon Sep 17 00:00:00 2001
From: "Robert G. Jakabosky" <bobby@xxxxxxxxxxxxxxx>
Date: Mon, 6 Aug 2012 09:59:42 -0700
Subject: [PATCH 1/2] FFI: compile tonumber(enum) and enum field
 initialization.


Signed-off-by: Robert G. Jakabosky <bobby@xxxxxxxxxxxxxxx>
---
 src/lj_crecord.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index 2a47503..100319d 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -431,6 +431,7 @@ static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, 
TRef sp, cTValue *sval)
       lj_needsplit(J);
       goto doconv;
     } else if (t == IRT_INT || t == IRT_U32) {
+      if (ctype_isenum(s->info)) s = ctype_child(cts, s);
       sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_INT);
       goto doconv;
     } else {
@@ -691,7 +692,7 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, 
CTypeID id)
          setintV(&tv, 0);
          if (!gcref(df->name)) continue;  /* Ignore unnamed fields. */
          dc = ctype_rawchild(cts, df);  /* Field type. */
-         if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info)))
+         if (!(ctype_isnum(dc->info) || ctype_isenum(dc->info) || 
ctype_isptr(dc->info)))
            lj_trace_err(J, LJ_TRERR_NYICONV);  /* NYI: init aggregates. */
          if (J->base[i]) {
            sp = J->base[i];
-- 
1.7.8.6

From 672249ffdb2438dc227d1e20ae8b98a0e8529040 Mon Sep 17 00:00:00 2001
From: "Robert G. Jakabosky" <bobby@xxxxxxxxxxxxxxx>
Date: Mon, 6 Aug 2012 10:04:34 -0700
Subject: [PATCH 2/2] FFI: compile ffi.typeof(cdata).


Signed-off-by: Robert G. Jakabosky <bobby@xxxxxxxxxxxxxxx>
---
 src/lib_ffi.c    |    2 +-
 src/lj_crecord.c |   14 ++++++++++++++
 src/lj_crecord.h |    1 +
 3 files changed, 16 insertions(+), 1 deletions(-)

diff --git a/src/lib_ffi.c b/src/lib_ffi.c
index 5cb9086..2ba7051 100644
--- a/src/lib_ffi.c
+++ b/src/lib_ffi.c
@@ -518,7 +518,7 @@ LJLIB_CF(ffi_cast)  LJLIB_REC(ffi_new)
   return 1;
 }
 
-LJLIB_CF(ffi_typeof)
+LJLIB_CF(ffi_typeof)   LJLIB_REC(.)
 {
   CTState *cts = ctype_cts(L);
   CTypeID id = ffi_checkctype(L, cts, L->base+1);
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index 100319d..bce85ec 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -1314,6 +1314,20 @@ void LJ_FASTCALL recff_ffi_fill(jit_State *J, 
RecordFFData *rd)
   }  /* else: interpreter will throw. */
 }
 
+void LJ_FASTCALL recff_ffi_typeof(jit_State *J, RecordFFData *rd)
+{
+  CTypeID id;
+  TRef trctype;
+  TRef trid;
+  if (!tref_iscdata(J->base[0]))
+    lj_trace_err(J, LJ_TRERR_NYICALL);
+  /* get cdata's ctype id */
+  id = argv2ctype(J, J->base[0], &rd->argv[0]);
+  trctype = lj_ir_kint(J, CTID_CTYPEID);
+  trid = lj_ir_kint(J, id);
+  J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trctype, trid);
+}
+
 void LJ_FASTCALL recff_ffi_istype(jit_State *J, RecordFFData *rd)
 {
   argv2ctype(J, J->base[0], &rd->argv[0]);
diff --git a/src/lj_crecord.h b/src/lj_crecord.h
index 0f93e14..595a84b 100644
--- a/src/lj_crecord.h
+++ b/src/lj_crecord.h
@@ -20,6 +20,7 @@ LJ_FUNC void LJ_FASTCALL recff_ffi_errno(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_typeof(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);
-- 
1.7.8.6

local ffi = require"ffi"
ffi.cdef[[
typedef enum {
        EnumVal1,
        EnumVal2,
        EnumVal3,
        EnumVal4,
        EnumVal5,
} TestEnum;
typedef struct TestCData {
        TestEnum enum_val;
} TestCData;
]]

local N = tonumber(arg[1]) or 100000

local TestEnum = ffi.typeof("TestEnum")
local TestCData = ffi.typeof("TestCData")

print("Test init. enum field.")
local cds = {}
for i=1,N do
        cds[i] = TestCData("EnumVal5")
end
print("Test init. enum field with default value.")
for i=1,N do
        cds[i] = TestCData()
end
cds = nil
collectgarbage("collect")

print("create some enum values for testing.")
local enums = {}
local val = tonumber(ffi.cast("TestEnum", "EnumVal5"))
print("enum val = ", val)
for i=1,N do
        enums[i] = TestEnum(val)
end

print("test trace of: tonumber(enum) call")
local vals = {}
for i=1,N do
        vals[i] = tonumber(enums[i])
end

local ffi = require"ffi"
ffi.cdef[[
typedef struct TestCData {
        size_t value;
} TestCData;
]]

local function cd_dump(cd)
        local ctype = ffi.typeof(cd)
        print("cd:", cd.value, tonumber(ctype), ctype)
end

local N = tonumber(arg[1]) or 100000

local TestCData = ffi.typeof("TestCData")

local cd1 = ffi.new("TestCData", 1)

cd_dump(cd1)

print("test NYI: ffi.typeof('TestCData') call")
for i=1,N do
        ffi.typeof("TestCData")
end

print("create some cdata values for testing.")
local cds = {}
for i=1,N do
        cds[i] = TestCData(i)
end
local ctypes = {}
print("test trace of: ffi.typeof() call")
for i=1,N do
        ctypes[i] = ffi.typeof(cds[i])
end
print("Validate ctype returned from ffi.typeof()")
local ctype = ffi.typeof(cd1)
for i=1,N do
        assert(ctype == ctypes[i], "Bad value returned from ffi.typeof()")
end

print("test trace of: tonumber(ffi.typeof()) call")
local ids = {}
for i=1,N do
        ids[i] = tonumber(ffi.typeof(cds[i]))
end

Other related posts:

  • » [PATCH] compile tonumber(enum) and ffi.typeof(cdata) - Robert G. Jakabosky