From 22946f268b1b25820c1d026779c147db314f7135 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Mon, 6 Jun 2011 19:56:55 +0200 Subject: [PATCH] FFI: Change tonumber(cdata) semantics. Return nil for non-numbers. --- src/lib_base.c | 25 ++++++++++++------------- src/lj_crecord.c | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/lib_base.c b/src/lib_base.c index fd7279af..8c71ae32 100644 --- a/src/lib_base.c +++ b/src/lib_base.c @@ -197,21 +197,20 @@ LJLIB_ASM(tonumber) LJLIB_REC(.) #if LJ_HASFFI if (tviscdata(o)) { CTState *cts = ctype_cts(L); - if (LJ_DUALNUM) { - CType *ct = ctype_raw(cts, cdataV(o)->typeid); - if (ctype_isinteger_or_bool(ct->info)) { - int64_t i; - lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT64), (uint8_t *)&i, o, 0); - if ((ct->size == 8 && (ct->info & CTF_UNSIGNED)) ? - (uint64_t)i <= 0x7fffffffu : checki32(i)) { - setintV(L->base-1, (int32_t)i); - return FFH_RES(1); - } /* else: retry and convert to double. */ + CType *ct = lj_ctype_rawref(cts, cdataV(o)->typeid); + if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); + if (ctype_isnum(ct->info) || ctype_iscomplex(ct->info)) { + if (LJ_DUALNUM && ctype_isinteger_or_bool(ct->info) && + ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) { + int32_t i; + lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0); + setintV(L->base-1, i); + return FFH_RES(1); } + lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE), + (uint8_t *)&(L->base-1)->n, o, 0); + return FFH_RES(1); } - lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE), - (uint8_t *)&(L->base-1)->n, o, 0); - return FFH_RES(1); } #endif } else { diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 8373faaa..743137de 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -1138,10 +1138,18 @@ void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd) void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd) { CTState *cts = ctype_ctsG(J2G(J)); - IRType st = crec_ct2irt(ctype_raw(cts, cdataV(&rd->argv[0])->typeid)); - CTypeID did = (st >= IRT_I8 && st <= IRT_INT) ? CTID_INT32 : CTID_DOUBLE; - CType *d = ctype_get(cts, did); - J->base[0] = crec_ct_tv(J, d, 0, J->base[0], &rd->argv[0]); + CType *d, *ct = lj_ctype_rawref(cts, cdataV(&rd->argv[0])->typeid); + if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); + if (ctype_isnum(ct->info) || ctype_iscomplex(ct->info)) { + if (ctype_isinteger_or_bool(ct->info) && ct->size <= 4 && + !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) + d = ctype_get(cts, CTID_INT32); + else + d = ctype_get(cts, CTID_DOUBLE); + J->base[0] = crec_ct_tv(J, d, 0, J->base[0], &rd->argv[0]); + } else { + J->base[0] = TREF_NIL; + } } #undef IR