]> git.ipfire.org Git - thirdparty/LuaJIT.git/commitdiff
FFI: Support FFI numbers in string.format() and buf:putf().
authorMike Pall <mike>
Thu, 3 Jun 2021 01:22:58 +0000 (03:22 +0200)
committerMike Pall <mike>
Thu, 3 Jun 2021 01:22:58 +0000 (03:22 +0200)
src/lj_crecord.c
src/lj_crecord.h
src/lj_ffrecord.c
src/lj_strfmt.c

index b0de5423cfc57cfde3c0d7bca49234525889bf11..aa4c5842a9ac96d0730b6060d5ad088a1b85f8b3 100644 (file)
@@ -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
index c6f39a67317d9762a8d3a6df7f67813725744b82..1a3427bd214dc0cb6f24536a34afaa5df32b2ab9 100644 (file)
@@ -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
index 844fc497c2f25cc1a2bf7ad8e6f209d1c54383e0..d050d12d752cdead4a5389b2ac39ad8f95e2bf88 100644 (file)
@@ -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));
index 5826b539425331fec8b282570c438a061fc4cda4..7b0734708a6f950cd9c5f973d0fc6d8d5a4fb57c 100644 (file)
@@ -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));