diff --git a/src/lib_base.c b/src/lib_base.c index c52f9191..52fbeb09 100644 --- a/src/lib_base.c +++ b/src/lib_base.c @@ -198,7 +198,7 @@ LJLIB_ASM(tonumber) LJLIB_REC(.) if (tviscdata(o)) { CTState *cts = ctype_cts(L); lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE), - (uint8_t *)&(L->base-1)->n, o, CCF_CAST); + (uint8_t *)&(L->base-1)->n, o, 0); return FFH_RES(1); } #endif diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 791c177c..b474a6b9 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -569,6 +569,34 @@ void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd) crec_alloc(J, rd, argv2ctype(J, J->base[0], &rd->argv[0])); } +/* -- Miscellaneous library functions ------------------------------------- */ + +void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd) +{ + CTypeID sid = argv2cdata(J, J->base[0], &rd->argv[0])->typeid; + CTState *cts = ctype_ctsG(J2G(J)); + CType *s = ctype_raw(cts, sid); + TRef sp = J->base[0]; + if (ctype_isref(s->info)) { + sp = emitir(IRT(IR_FLOAD, IRT_PTR), sp, IRFL_CDATA_PTR); + s = ctype_rawchild(cts, s); + } else { + sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCcdata))); + } + if (ctype_isenum(s->info)) s = ctype_child(cts, s); + if (ctype_isnum(s->info) || ctype_iscomplex(s->info)) { + IRType t = crec_ct2irt(s); + if (t != IRT_CDATA) { + TRef tr = emitir(IRT(IR_XLOAD, t), sp, 0); /* Load number value. */ + if (t == IRT_FLOAT || t == IRT_U32 || t == IRT_I64 || t == IRT_U64) + tr = emitconv(tr, IRT_NUM, t, 0); + J->base[0] = tr; + return; + } + } + lj_trace_err(J, LJ_TRERR_BADTYPE); +} + #undef IR #undef emitir #undef emitconv diff --git a/src/lj_crecord.h b/src/lj_crecord.h index af98bde5..05ef6110 100644 --- a/src/lj_crecord.h +++ b/src/lj_crecord.h @@ -14,6 +14,7 @@ LJ_FUNC void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd); LJ_FUNC void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd); LJ_FUNC void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd); +LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); #else #define recff_cdata_index recff_nyi #define recff_cdata_call recff_nyi diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index ca9f6ceb..c10e38fe 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c @@ -268,7 +268,8 @@ static void LJ_FASTCALL recff_tonumber(jit_State *J, RecordFFData *rd) } #if LJ_HASFFI } else if (tref_iscdata(tr)) { - recff_nyiu(J); + lj_crecord_tonumber(J, rd); + return; #endif } else { tr = TREF_NIL;