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