2
0
Эх сурвалжийг харах

FFI: Fix call argument and return handling for I8/U8/I16/U16 types.

Mike Pall 14 жил өмнө
parent
commit
bc95d54ec9
2 өөрчлөгдсөн 27 нэмэгдсэн , 8 устгасан
  1. 15 7
      src/lj_ccall.c
  2. 12 1
      src/lj_crecord.c

+ 15 - 7
src/lj_ccall.c

@@ -515,11 +515,8 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
     /* Find out how (by value/ref) and where (GPR/FPR) to pass an argument. */
     if (ctype_isnum(d->info)) {
       if (sz > 8) goto err_nyi;
-      if ((d->info & CTF_FP)) {
+      if ((d->info & CTF_FP))
 	isfp = 1;
-      } else if (sz < CTSIZE_PTR) {
-	d = ctype_get(cts, CTID_INT_PSZ);
-      }
     } else if (ctype_isvector(d->info)) {
       if (CCALL_VECTOR_REG && (sz == 8 || sz == 16))
 	isfp = 1;
@@ -557,6 +554,15 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
       dp = rp;
     }
     lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg));
+    /* Extend passed integers to 32 bits at least. */
+    if (ctype_isinteger_or_bool(d->info) && d->size < 4) {
+      if (d->info & CTF_UNSIGNED)
+	*(uint32_t *)dp = d->size == 1 ? (uint32_t)*(uint8_t *)dp :
+					 (uint32_t)*(uint16_t *)dp;
+      else
+	*(int32_t *)dp = d->size == 1 ? (int32_t)*(int8_t *)dp :
+					(int32_t)*(int16_t *)dp;
+    }
 #if LJ_TARGET_X64 && LJ_ABI_WIN
     if (isva) {  /* Windows/x64 mirrors varargs in both register sets. */
       if (nfpr == ngpr)
@@ -593,7 +599,7 @@ static int ccall_get_results(lua_State *L, CTState *cts, CType *ct,
 			     CCallState *cc, int *ret)
 {
   CType *ctr = ctype_rawchild(cts, ct);
-  void *sp = &cc->gpr[0];
+  uint8_t *sp = (uint8_t *)&cc->gpr[0];
   if (ctype_isvoid(ctr->info)) {
     *ret = 0;  /* Zero results. */
     return 0;  /* No additional GC step. */
@@ -613,17 +619,19 @@ static int ccall_get_results(lua_State *L, CTState *cts, CType *ct,
     CCALL_HANDLE_COMPLEXRET2
     return 1;  /* One GC step. */
   }
+  if (LJ_BE && ctype_isinteger_or_bool(ctr->info) && ctr->size < CTSIZE_PTR)
+    sp += (CTSIZE_PTR - ctr->size);
 #ifdef CCALL_HANDLE_RET
   CCALL_HANDLE_RET
 #endif
 #if CCALL_NUM_FPR
   if (ctype_isfp(ctr->info) || ctype_isvector(ctr->info))
-    sp = &cc->fpr[0];
+    sp = (uint8_t *)&cc->fpr[0];
 #endif
   /* No reference types end up here, so there's no need for the CTypeID. */
   lua_assert(!(ctype_isrefarray(ctr->info) || ctype_isstruct(ctr->info)));
   if (ctype_isenum(ctr->info)) ctr = ctype_child(cts, ctr);
-  return lj_cconv_tv_ct(cts, ctr, 0, L->top-1, (uint8_t *)sp);
+  return lj_cconv_tv_ct(cts, ctr, 0, L->top-1, sp);
 }
 
 /* Call C function. */

+ 12 - 1
src/lj_crecord.c

@@ -759,7 +759,14 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd,
     if (!(ctype_isnum(d->info) || ctype_isptr(d->info) ||
 	  ctype_isenum(d->info)))
       lj_trace_err(J, LJ_TRERR_NYICALL);
-    args[n] = crec_ct_tv(J, d, 0, J->base[n+1], &rd->argv[n+1]);
+    tr = crec_ct_tv(J, d, 0, J->base[n+1], &rd->argv[n+1]);
+    if (ctype_isinteger_or_bool(d->info) && d->size < 4) {
+      if ((d->info & CTF_UNSIGNED))
+	tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_U8 : IRT_U16, 0);
+      else
+	tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_I8 : IRT_I16, IRCONV_SEXT);
+    }
+    args[n] = tr;
   }
   tr = args[0];
   for (i = 1; i < n; i++)
@@ -799,6 +806,10 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd)
     tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func);
     if (t == IRT_FLOAT || t == IRT_U32) {
       tr = emitconv(tr, IRT_NUM, t, 0);
+    } else if (t == IRT_I8 || t == IRT_I16) {
+      tr = emitconv(tr, IRT_INT, t, IRCONV_SEXT);
+    } else if (t == IRT_U8 || t == IRT_U16) {
+      tr = emitconv(tr, IRT_INT, t, 0);
     } else if (t == IRT_PTR || (LJ_64 && t == IRT_P32) ||
 	       (t == IRT_I64 || t == IRT_U64)) {
       TRef trid = lj_ir_kint(J, ctype_cid(ct->info));