diff --git a/doc/ext_ffi_semantics.html b/doc/ext_ffi_semantics.html index d9aa27c8..b612dbc5 100644 --- a/doc/ext_ffi_semantics.html +++ b/doc/ext_ffi_semantics.html @@ -980,8 +980,6 @@ two.
  • Calls to non-cdecl or vararg C functions.
  • Calls to C functions with aggregates passed or returned by value.
  • -
  • Calls to C functions with 64 bit arguments or return values -on 32 bit CPUs.
  • Calls to ctype metamethods which are not plain functions.
  • ctype __newindex tables and non-string lookups in ctype __index tables.
  • diff --git a/src/lj_asm.c b/src/lj_asm.c index d5e74185..46142f5c 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c @@ -3346,6 +3346,7 @@ static void asm_hiop(ASMState *as, IRIns *ir) break; } case IR_CALLN: + case IR_CALLXS: ra_destreg(as, ir, RID_RETHI); if (!uselo) ra_allocref(as, ir->op1, RID2RSET(RID_RET)); /* Mark call as used. */ diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 8330faaf..9c93a6f1 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -785,15 +785,16 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) #if LJ_TARGET_X86 ctype_cconv(ct->info) != CTCC_CDECL || #endif - t == IRT_CDATA || (LJ_32 && (t == IRT_I64 || t == IRT_U64))) + t == IRT_CDATA) lj_trace_err(J, LJ_TRERR_NYICALL); 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_PTR || (LJ_64 && t == IRT_P32) || - (LJ_64 && (t == IRT_I64 || t == IRT_U64))) { + (t == IRT_I64 || t == IRT_U64)) { TRef trid = lj_ir_kint(J, ctype_cid(ct->info)); tr = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, tr); + if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J); } J->base[0] = tr; J->needsnap = 1; diff --git a/src/lj_opt_split.c b/src/lj_opt_split.c index 90b2b49c..e52ddfd4 100644 --- a/src/lj_opt_split.c +++ b/src/lj_opt_split.c @@ -256,6 +256,8 @@ static void split_ir(jit_State *J) } break; } + case IR_CALLXS: + goto split_call; case IR_PHI: { IRRef hiref2; if ((irref_isk(nir->op1) && irref_isk(nir->op2)) || @@ -285,6 +287,42 @@ static void split_ir(jit_State *J) nir->op1 = nir->op2 = 0; } } + } else if (ir->o == IR_CALLXS) { + IRRef hiref; + split_call: + hiref = hisubst[ir->op1]; + if (hiref) { + IROpT ot = nir->ot; + IRRef op2 = nir->op2; + nir->ot = IRT(IR_CARG, IRT_NIL); +#if LJ_LE + nir->op2 = hiref; +#else + nir->op2 = nir->op1; nir->op1 = hiref; +#endif + ir->prev = nref = split_emit(J, ot, nref, op2); + } + if (irt_isint64(ir->t)) + hi = split_emit(J, IRTI(IR_HIOP), nref, nref); + } else if (ir->o == IR_CARG) { + IRRef hiref = hisubst[ir->op1]; + if (hiref) { + IRRef op2 = nir->op2; +#if LJ_LE + nir->op2 = hiref; +#else + nir->op2 = nir->op1; nir->op1 = hiref; +#endif + ir->prev = nref = split_emit(J, IRT(IR_CARG, IRT_NIL), nref, op2); + nir = IR(nref); + } + hiref = hisubst[ir->op2]; + if (hiref) { +#if LJ_BE + IRRef tmp = nir->op2; nir->op2 = hiref; hiref = tmp; +#endif + ir->prev = split_emit(J, IRT(IR_CARG, IRT_NIL), nref, hiref); + } } else if (ir->o == IR_CNEWI) { if (hisubst[ir->op2]) split_emit(J, IRT(IR_HIOP, IRT_NIL), nref, hisubst[ir->op2]);