Browse Source

FFI: Record 64 bit integer arithmetic.

Currently NYI in the x86 backend.
Mike Pall 14 năm trước cách đây
mục cha
commit
eaf88dfb3a
3 tập tin đã thay đổi với 40 bổ sung8 xóa
  1. 0 6
      src/lj_cdata.c
  2. 33 2
      src/lj_crecord.c
  3. 7 0
      src/lj_ir.h

+ 0 - 6
src/lj_cdata.c

@@ -235,7 +235,6 @@ void lj_cdata_set(CTState *cts, CType *d, uint8_t *dp, TValue *o, CTInfo qual)
 uint64_t lj_cdata_powi64(uint64_t x, uint64_t k, int isunsigned)
 {
   uint64_t y = 0;
-  int sign = 0;
   if (k == 0)
     return 1;
   if (!isunsigned) {
@@ -249,10 +248,6 @@ uint64_t lj_cdata_powi64(uint64_t x, uint64_t k, int isunsigned)
       else
 	return 0;
     }
-    if ((int64_t)x < 0) {
-      x = -x;
-      sign = (k & 1);
-    }
   }
   for (; (k & 1) == 0; k >>= 1) x *= x;
   y = x;
@@ -265,7 +260,6 @@ uint64_t lj_cdata_powi64(uint64_t x, uint64_t k, int isunsigned)
     }
     y *= x;
   }
-  if (sign) y = (uint64_t)-(int64_t)y;
   return y;
 }
 

+ 33 - 2
src/lj_crecord.c

@@ -564,8 +564,39 @@ void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd)
 
 static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm)
 {
-  UNUSED(J); UNUSED(sp); UNUSED(s); UNUSED(mm);
-  return 0;  /* NYI: 64 bit integer arithmetic. */
+  if (ctype_isnum(s[0]->info) && ctype_isnum(s[1]->info)) {
+    IRType dt;
+    CTypeID id;
+    TRef tr, dp, ptr;
+    MSize i;
+    if (((s[0]->info & CTF_UNSIGNED) && s[0]->size == 8) ||
+	((s[1]->info & CTF_UNSIGNED) && s[1]->size == 8)) {
+      dt = IRT_U64; id = CTID_UINT64;
+    } else {
+      dt = IRT_I64; id = CTID_INT64;
+    }
+    for (i = 0; i < 2; i++) {
+      IRType st = tref_type(sp[i]);
+      if (st == IRT_NUM || st == IRT_FLOAT)
+	sp[i] = emitconv(sp[i], dt, st, IRCONV_TRUNC|IRCONV_ANY);
+      else if (!(st == IRT_I64 || st == IRT_U64))
+	sp[i] = emitconv(sp[i], dt, IRT_INT,
+			 ((st - IRT_I8) & 1) ? 0 : IRCONV_SEXT);
+    }
+    if (mm == MM_pow) {
+      tr = lj_ir_call(J, IRCALL_lj_cdata_powi64, sp[0], sp[1],
+		      lj_ir_kint(J, (int)dt-(int)IRT_I64));
+    } else {
+      if (mm == MM_div || mm == MM_mod)
+	return 0;  /* NYI: integer div, mod. */
+      tr = emitir(IRT(mm+(int)IR_ADD-(int)MM_add, dt), sp[0], sp[1]);
+    }
+    dp = emitir(IRTG(IR_CNEW, IRT_CDATA), lj_ir_kint(J, id), TREF_NIL);
+    ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, sizeof(GCcdata)));
+    emitir(IRT(IR_XSTORE, dt), ptr, tr);
+    return dp;
+  }
+  return 0;
 }
 
 static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm)

+ 7 - 0
src/lj_ir.h

@@ -251,6 +251,12 @@ typedef struct CCallInfo {
 #define CCI_FASTCALL		0x0800	/* Fastcall convention. */
 
 /* Function definitions for CALL* instructions. */
+#if LJ_HASFFI
+#define IRCALLDEF_FFI(_) \
+  _(lj_cdata_powi64,	3,   N, U64, CCI_NOFPRCLOBBER)
+#else
+#define IRCALLDEF_FFI(_)
+#endif
 #define IRCALLDEF(_) \
   _(lj_str_cmp,		2,  FN, INT, CCI_NOFPRCLOBBER) \
   _(lj_str_new,		3,   S, STR, CCI_L) \
@@ -265,6 +271,7 @@ typedef struct CCallInfo {
   _(lj_gc_barrieruv,	2,  FS, NIL, 0) \
   _(lj_mem_newgco,	2,  FS, P32, CCI_L) \
   _(lj_math_random_step, 1, FS, NUM, CCI_CASTU64|CCI_NOFPRCLOBBER) \
+  IRCALLDEF_FFI(_) \
   _(sinh,		1,  N, NUM, 0) \
   _(cosh,		1,  N, NUM, 0) \
   _(tanh,		1,  N, NUM, 0) \