From 1b7171c339a8d33cb1fd332e31787ebc23266f10 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Thu, 3 Jun 2021 03:22:58 +0200 Subject: [PATCH] FFI: Support FFI numbers in string.format() and buf:putf(). --- src/lj_crecord.c | 9 +++++++++ src/lj_crecord.h | 1 + src/lj_ffrecord.c | 11 ++++++++++- src/lj_strfmt.c | 32 +++++++++++++++++++++++++++----- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/lj_crecord.c b/src/lj_crecord.c index b0de5423..aa4c5842 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -1913,6 +1913,15 @@ void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd) } } +TRef lj_crecord_loadiu64(jit_State *J, TRef tr, cTValue *o) +{ + CTypeID id = argv2cdata(J, tr, o)->ctypeid; + if (!(id == CTID_INT64 || id == CTID_UINT64)) + lj_trace_err(J, LJ_TRERR_BADTYPE); + return emitir(IRT(IR_FLOAD, id == CTID_INT64 ? IRT_I64 : IRT_U64), tr, + IRFL_CDATA_INT64); +} + #undef IR #undef emitir #undef emitconv diff --git a/src/lj_crecord.h b/src/lj_crecord.h index c6f39a67..1a3427bd 100644 --- a/src/lj_crecord.h +++ b/src/lj_crecord.h @@ -33,6 +33,7 @@ LJ_FUNC int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd); LJ_FUNC TRef recff_bit64_tohex(jit_State *J, RecordFFData *rd, TRef hdr); LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); +LJ_FUNC TRef lj_crecord_loadiu64(jit_State *J, TRef tr, cTValue *o); #endif #endif diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index 844fc497..d050d12d 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c @@ -961,8 +961,17 @@ static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd) case STRFMT_INT: id = IRCALL_lj_strfmt_putfnum_int; handle_int: - if (!tref_isinteger(tra)) + if (!tref_isinteger(tra)) { +#if LJ_HASFFI + if (tref_iscdata(tra)) { + tra = lj_crecord_loadiu64(J, tra, &rd->argv[arg-1]); + tr = lj_ir_call(J, IRCALL_lj_strfmt_putfxint, tr, trsf, tra); + lj_needsplit(J); + break; + } +#endif goto handle_num; + } if (sf == STRFMT_INT) { /* Shortcut for plain %d. */ tr = emitir(IRTG(IR_BUFPUT, IRT_PGC), tr, emitir(IRT(IR_TOSTR, IRT_STR), tra, IRTOSTR_INT)); diff --git a/src/lj_strfmt.c b/src/lj_strfmt.c index 5826b539..7b073470 100644 --- a/src/lj_strfmt.c +++ b/src/lj_strfmt.c @@ -16,6 +16,9 @@ #include "lj_state.h" #include "lj_char.h" #include "lj_strfmt.h" +#if LJ_HASFFI +#include "lj_ctype.h" +#endif #include "lj_lib.h" /* -- Format parser ------------------------------------------------------- */ @@ -392,15 +395,34 @@ int lj_strfmt_putarg(lua_State *L, SBuf *sb, int arg, int retry) lj_strfmt_putint(sb, k); /* Shortcut for plain %d. */ else lj_strfmt_putfxint(sb, sf, k); - } else { - lj_strfmt_putfnum_int(sb, sf, lj_lib_checknum(L, arg)); + break; } +#if LJ_HASFFI + if (tviscdata(o)) { + GCcdata *cd = cdataV(o); + if (cd->ctypeid == CTID_INT64 || cd->ctypeid == CTID_UINT64) { + lj_strfmt_putfxint(sb, sf, *(uint64_t *)cdataptr(cd)); + break; + } + } +#endif + lj_strfmt_putfnum_int(sb, sf, lj_lib_checknum(L, arg)); break; case STRFMT_UINT: - if (tvisint(o)) + if (tvisint(o)) { lj_strfmt_putfxint(sb, sf, intV(o)); - else - lj_strfmt_putfnum_uint(sb, sf, lj_lib_checknum(L, arg)); + break; + } +#if LJ_HASFFI + if (tviscdata(o)) { + GCcdata *cd = cdataV(o); + if (cd->ctypeid == CTID_INT64 || cd->ctypeid == CTID_UINT64) { + lj_strfmt_putfxint(sb, sf, *(uint64_t *)cdataptr(cd)); + break; + } + } +#endif + lj_strfmt_putfnum_uint(sb, sf, lj_lib_checknum(L, arg)); break; case STRFMT_NUM: lj_strfmt_putfnum(sb, sf, lj_lib_checknum(L, arg));