浏览代码

FFI: Support FFI numbers in string.format() and buf:putf().

Mike Pall 4 年之前
父节点
当前提交
1b7171c339
共有 4 个文件被更改,包括 47 次插入6 次删除
  1. 9 0
      src/lj_crecord.c
  2. 1 0
      src/lj_crecord.h
  3. 10 1
      src/lj_ffrecord.c
  4. 27 5
      src/lj_strfmt.c

+ 9 - 0
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

+ 1 - 0
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

+ 10 - 1
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));

+ 27 - 5
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));