mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 23:24:09 +00:00
FFI: Add 64 bit integer comparisons and pointer comparisons.
This commit is contained in:
parent
e7b08b2361
commit
0ec7f5ed92
1857
src/buildvm_x64.h
1857
src/buildvm_x64.h
File diff suppressed because it is too large
Load Diff
1977
src/buildvm_x64win.h
1977
src/buildvm_x64win.h
File diff suppressed because it is too large
Load Diff
@ -1042,6 +1042,19 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
|
||||
| call extern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne)
|
||||
| // 0/1 or TValue * (metamethod) returned in eax (RC).
|
||||
| jmp <3
|
||||
|
|
||||
|->vmeta_equal_cd:
|
||||
#if LJ_HASFFI
|
||||
| sub PC, 4
|
||||
| mov L:RB, SAVE_L
|
||||
| mov L:RB->base, BASE
|
||||
| mov FCARG1, L:RB
|
||||
| mov FCARG2, dword [PC-4]
|
||||
| mov SAVE_PC, PC
|
||||
| call extern lj_meta_equal_cd@8 // (lua_State *L, BCIns op)
|
||||
| // 0/1 or TValue * (metamethod) returned in eax (RC).
|
||||
| jmp <3
|
||||
#endif
|
||||
|
|
||||
|//-- Arithmetic metamethods ---------------------------------------------
|
||||
|
|
||||
@ -3593,7 +3606,13 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
|
||||
| movzx RD, PC_RD
|
||||
| branchPC RD
|
||||
|2: // NE: Fallthrough to next instruction.
|
||||
if (!LJ_HASFFI) {
|
||||
|3:
|
||||
}
|
||||
} else {
|
||||
if (!LJ_HASFFI) {
|
||||
|3:
|
||||
}
|
||||
|2: // NE: Branch to the target.
|
||||
| movzx RD, PC_RD
|
||||
| branchPC RD
|
||||
@ -3603,6 +3622,10 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
|
||||
|
|
||||
if (op == BC_ISEQV || op == BC_ISNEV) {
|
||||
|5: // Either or both types are not numbers.
|
||||
if (LJ_HASFFI) {
|
||||
| cmp RB, LJ_TCDATA; je ->vmeta_equal_cd
|
||||
| checktp RA, LJ_TCDATA; je ->vmeta_equal_cd
|
||||
}
|
||||
| checktp RA, RB // Compare types.
|
||||
| jne <2 // Not the same type?
|
||||
| cmp RB, LJ_TISPRI
|
||||
@ -3629,13 +3652,18 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
|
||||
| mov RB, 1 // ne = 1
|
||||
}
|
||||
| jmp ->vmeta_equal // Handle __eq metamethod.
|
||||
} else if (LJ_HASFFI) {
|
||||
|3:
|
||||
| cmp RB, LJ_TCDATA; jne <2
|
||||
| jmp ->vmeta_equal_cd
|
||||
}
|
||||
break;
|
||||
case BC_ISEQS: case BC_ISNES:
|
||||
vk = op == BC_ISEQS;
|
||||
| ins_AND // RA = src, RD = str const, JMP with RD = target
|
||||
| mov RB, [BASE+RA*8+4]
|
||||
| add PC, 4
|
||||
| checkstr RA, >2
|
||||
| cmp RB, LJ_TSTR; jne >3
|
||||
| mov RA, [BASE+RA*8]
|
||||
| cmp RA, [KBASE+RD*4]
|
||||
iseqne_test:
|
||||
@ -3648,8 +3676,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
|
||||
case BC_ISEQN: case BC_ISNEN:
|
||||
vk = op == BC_ISEQN;
|
||||
| ins_AD // RA = src, RD = num const, JMP with RD = target
|
||||
| mov RB, [BASE+RA*8+4]
|
||||
| add PC, 4
|
||||
| checknum RA, >2
|
||||
| cmp RB, LJ_TISNUM; ja >3
|
||||
if (sse) {
|
||||
| movsd xmm0, qword [KBASE+RD*8]
|
||||
| ucomisd xmm0, qword [BASE+RA*8]
|
||||
@ -3662,9 +3691,28 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
|
||||
case BC_ISEQP: case BC_ISNEP:
|
||||
vk = op == BC_ISEQP;
|
||||
| ins_AND // RA = src, RD = primitive type (~), JMP with RD = target
|
||||
| mov RB, [BASE+RA*8+4]
|
||||
| add PC, 4
|
||||
| checktp RA, RD
|
||||
goto iseqne_test;
|
||||
| cmp RB, RD
|
||||
if (!LJ_HASFFI) goto iseqne_test;
|
||||
if (vk) {
|
||||
| jne >3
|
||||
| movzx RD, PC_RD
|
||||
| branchPC RD
|
||||
|2:
|
||||
| ins_next
|
||||
|3:
|
||||
| cmp RB, LJ_TCDATA; jne <2
|
||||
| jmp ->vmeta_equal_cd
|
||||
} else {
|
||||
| je >2
|
||||
| cmp RB, LJ_TCDATA; je ->vmeta_equal_cd
|
||||
| movzx RD, PC_RD
|
||||
| branchPC RD
|
||||
|2:
|
||||
| ins_next
|
||||
}
|
||||
break;
|
||||
|
||||
/* -- Unary test and copy ops ------------------------------------------- */
|
||||
|
||||
|
2264
src/buildvm_x86.h
2264
src/buildvm_x86.h
File diff suppressed because it is too large
Load Diff
110
src/lib_ffi.c
110
src/lib_ffi.c
@ -85,9 +85,10 @@ typedef struct FFIArith {
|
||||
} FFIArith;
|
||||
|
||||
/* Check arguments for arithmetic metamethods. */
|
||||
static void ffi_checkarith(lua_State *L, CTState *cts, FFIArith *fa)
|
||||
static int ffi_checkarith(lua_State *L, CTState *cts, FFIArith *fa)
|
||||
{
|
||||
TValue *o = L->base;
|
||||
int ok = 1;
|
||||
MSize i;
|
||||
if (o+1 >= L->top)
|
||||
lj_err_argt(L, 1, LUA_TCDATA);
|
||||
@ -105,10 +106,16 @@ static void ffi_checkarith(lua_State *L, CTState *cts, FFIArith *fa)
|
||||
} else if (tvisnum(o)) {
|
||||
fa->ct[i] = ctype_get(cts, CTID_DOUBLE);
|
||||
fa->p[i] = (uint8_t *)&o->n;
|
||||
} else if (tvisnil(o)) {
|
||||
fa->ct[i] = ctype_get(cts, CTID_P_VOID);
|
||||
fa->p[i] = (uint8_t *)0;
|
||||
} else {
|
||||
lj_err_optype(L, o, LJ_ERR_OPARITH);
|
||||
fa->ct[i] = NULL;
|
||||
fa->p[i] = NULL;
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* Pointer arithmetic. */
|
||||
@ -120,26 +127,38 @@ static int ffi_arith_ptr(lua_State *L, CTState *cts, FFIArith *fa, MMS mm)
|
||||
CTSize sz;
|
||||
CTypeID id;
|
||||
GCcdata *cd;
|
||||
if (!(mm == MM_add || mm == MM_sub))
|
||||
return 0;
|
||||
if (ctype_isptr(ctp->info) || ctype_isrefarray(ctp->info)) {
|
||||
if (mm == MM_sub &&
|
||||
if ((mm == MM_sub || mm == MM_eq || mm == MM_lt || mm == MM_le) &&
|
||||
(ctype_isptr(fa->ct[1]->info) || ctype_isrefarray(fa->ct[1]->info))) {
|
||||
/* Pointer difference. */
|
||||
intptr_t diff;
|
||||
uint8_t *pp2 = fa->p[1];
|
||||
if (mm == MM_eq) { /* Pointer equality. Incompatible pointers are ok. */
|
||||
setboolV(L->top-1, (pp == pp2));
|
||||
return 1;
|
||||
}
|
||||
if (!lj_cconv_compatptr(cts, ctp, fa->ct[1], CCF_IGNQUAL))
|
||||
lj_err_caller(L, LJ_ERR_FFI_INVTYPE);
|
||||
return 0;
|
||||
if (mm == MM_sub) { /* Pointer difference. */
|
||||
intptr_t diff;
|
||||
sz = lj_ctype_size(cts, ctype_cid(ctp->info)); /* Element size. */
|
||||
if (sz == 0 || sz == CTSIZE_INVALID)
|
||||
lj_err_caller(L, LJ_ERR_FFI_INVSIZE);
|
||||
diff = ((intptr_t)pp - (intptr_t)fa->p[1]) / (int32_t)sz;
|
||||
return 0;
|
||||
diff = ((intptr_t)pp - (intptr_t)pp2) / (int32_t)sz;
|
||||
/* All valid pointer differences on x64 are in (-2^47, +2^47),
|
||||
** which fits into a double without loss of precision.
|
||||
*/
|
||||
setnumV(L->top-1, (lua_Number)diff);
|
||||
return 1;
|
||||
} else if (mm == MM_lt) { /* Pointer comparison (unsigned). */
|
||||
setboolV(L->top-1, ((uintptr_t)pp < (uintptr_t)pp2));
|
||||
return 1;
|
||||
} else {
|
||||
lua_assert(mm == MM_le);
|
||||
setboolV(L->top-1, ((uintptr_t)pp <= (uintptr_t)pp2));
|
||||
return 1;
|
||||
}
|
||||
if (!ctype_isnum(fa->ct[1]->info)) return 0;
|
||||
}
|
||||
if (!((mm == MM_add || mm == MM_sub) &&
|
||||
ctype_isnum(fa->ct[1]->info))) return 0;
|
||||
lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), fa->ct[1],
|
||||
(uint8_t *)&idx, fa->p[1], 0);
|
||||
if (mm == MM_sub) idx = -idx;
|
||||
@ -155,7 +174,7 @@ static int ffi_arith_ptr(lua_State *L, CTState *cts, FFIArith *fa, MMS mm)
|
||||
}
|
||||
sz = lj_ctype_size(cts, ctype_cid(ctp->info)); /* Element size. */
|
||||
if (sz == CTSIZE_INVALID)
|
||||
lj_err_caller(L, LJ_ERR_FFI_INVSIZE);
|
||||
return 0;
|
||||
pp += idx*(int32_t)sz; /* Compute pointer + index. */
|
||||
id = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ctp->info)),
|
||||
CTSIZE_PTR);
|
||||
@ -180,7 +199,19 @@ static int ffi_arith_int64(lua_State *L, CTState *cts, FFIArith *fa, MMS mm)
|
||||
lj_cconv_ct_ct(cts, ct, fa->ct[0], (uint8_t *)&u0, fa->p[0], 0);
|
||||
if (mm != MM_unm)
|
||||
lj_cconv_ct_ct(cts, ct, fa->ct[1], (uint8_t *)&u1, fa->p[1], 0);
|
||||
if ((mm == MM_div || mm == MM_mod)) {
|
||||
switch (mm) {
|
||||
case MM_eq:
|
||||
setboolV(L->top-1, (u0 == u1));
|
||||
return 1;
|
||||
case MM_lt:
|
||||
setboolV(L->top-1,
|
||||
id == CTID_INT64 ? ((int64_t)u0 < (int64_t)u1) : (u0 < u1));
|
||||
return 1;
|
||||
case MM_le:
|
||||
setboolV(L->top-1,
|
||||
id == CTID_INT64 ? ((int64_t)u0 <= (int64_t)u1) : (u0 <= u1));
|
||||
return 1;
|
||||
case MM_div: case MM_mod:
|
||||
if (u1 == 0) { /* Division by zero. */
|
||||
if (u0 == 0)
|
||||
setnanV(L->top-1);
|
||||
@ -194,6 +225,8 @@ static int ffi_arith_int64(lua_State *L, CTState *cts, FFIArith *fa, MMS mm)
|
||||
if (mm == MM_div) id = CTID_UINT64; else u0 = 0;
|
||||
mm = MM_unm; /* Result is 0x8000000000000000ULL or 0LL. */
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
cd = lj_cdata_new(cts, id, 8);
|
||||
up = (uint64_t *)cdataptr(cd);
|
||||
@ -229,17 +262,27 @@ static int ffi_arith(lua_State *L)
|
||||
{
|
||||
CTState *cts = ctype_cts(L);
|
||||
FFIArith fa;
|
||||
MMS mm = (MMS)(curr_func(L)->c.ffid - (int)FF_ffi_meta___add + (int)MM_add);
|
||||
ffi_checkarith(L, cts, &fa);
|
||||
if (!ffi_arith_int64(L, cts, &fa, mm) &&
|
||||
!ffi_arith_ptr(L, cts, &fa, mm)) {
|
||||
MMS mm = (MMS)(curr_func(L)->c.ffid - (int)FF_ffi_meta___eq + (int)MM_eq);
|
||||
if (ffi_checkarith(L, cts, &fa)) {
|
||||
if (ffi_arith_int64(L, cts, &fa, mm) || ffi_arith_ptr(L, cts, &fa, mm))
|
||||
return 1;
|
||||
}
|
||||
/* NYI: per-cdata metamethods. */
|
||||
{
|
||||
const char *repr[2];
|
||||
int i;
|
||||
for (i = 0; i < 2; i++)
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (fa.ct[i])
|
||||
repr[i] = strdata(lj_ctype_repr(L, ctype_typeid(cts, fa.ct[i]), NULL));
|
||||
lj_err_callerv(L, LJ_ERR_FFI_BADARITH, repr[0], repr[1]);
|
||||
else
|
||||
repr[i] = typename(&L->base[i]);
|
||||
}
|
||||
return 1;
|
||||
lj_err_callerv(L, mm == MM_len ? LJ_ERR_FFI_BADLEN :
|
||||
mm == MM_concat ? LJ_ERR_FFI_BADCONCAT :
|
||||
mm < MM_add ? LJ_ERR_FFI_BADCOMP : LJ_ERR_FFI_BADARITH,
|
||||
repr[0], repr[1]);
|
||||
}
|
||||
return 0; /* unreachable */
|
||||
}
|
||||
|
||||
/* -- C type metamethods -------------------------------------------------- */
|
||||
@ -275,6 +318,32 @@ LJLIB_CF(ffi_meta___newindex) LJLIB_REC(cdata_index 1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The following functions must be in contiguous ORDER MM. */
|
||||
LJLIB_CF(ffi_meta___eq)
|
||||
{
|
||||
return ffi_arith(L);
|
||||
}
|
||||
|
||||
LJLIB_CF(ffi_meta___len)
|
||||
{
|
||||
return ffi_arith(L);
|
||||
}
|
||||
|
||||
LJLIB_CF(ffi_meta___lt)
|
||||
{
|
||||
return ffi_arith(L);
|
||||
}
|
||||
|
||||
LJLIB_CF(ffi_meta___le)
|
||||
{
|
||||
return ffi_arith(L);
|
||||
}
|
||||
|
||||
LJLIB_CF(ffi_meta___concat)
|
||||
{
|
||||
return ffi_arith(L);
|
||||
}
|
||||
|
||||
/* Forward declaration. */
|
||||
static int lj_cf_ffi_new(lua_State *L);
|
||||
|
||||
@ -324,6 +393,7 @@ LJLIB_CF(ffi_meta___unm) LJLIB_REC(cdata_arith MM_unm)
|
||||
{
|
||||
return ffi_arith(L);
|
||||
}
|
||||
/* End of contiguous ORDER MM. */
|
||||
|
||||
LJLIB_CF(ffi_meta___tostring)
|
||||
{
|
||||
|
@ -19,6 +19,7 @@ LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd);
|
||||
#else
|
||||
#define recff_cdata_index recff_nyi
|
||||
#define recff_cdata_call recff_nyi
|
||||
#define recff_cdata_arith recff_nyi
|
||||
#define recff_ffi_new recff_nyi
|
||||
#endif
|
||||
|
||||
|
@ -147,7 +147,10 @@ ERRDEF(FFI_BADTAG, "undeclared or implicit tag " LUA_QS)
|
||||
ERRDEF(FFI_REDEF, "attempt to redefine " LUA_QS)
|
||||
ERRDEF(FFI_INITOV, "too many initializers for " LUA_QS)
|
||||
ERRDEF(FFI_BADCONV, "cannot convert " LUA_QS " to " LUA_QS)
|
||||
ERRDEF(FFI_BADLEN, "attempt to get length of " LUA_QS)
|
||||
ERRDEF(FFI_BADCONCAT, "attempt to concatenate " LUA_QS " and " LUA_QS)
|
||||
ERRDEF(FFI_BADARITH, "attempt to perform arithmetic on " LUA_QS " and " LUA_QS)
|
||||
ERRDEF(FFI_BADCOMP, "attempt to compare " LUA_QS " with " LUA_QS)
|
||||
ERRDEF(FFI_BADCALL, LUA_QS " is not callable")
|
||||
ERRDEF(FFI_NUMARG, "wrong number of arguments for function call")
|
||||
ERRDEF(FFI_BADMEMBER, LUA_QS " has no member named " LUA_QS)
|
||||
|
@ -302,10 +302,48 @@ TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne)
|
||||
return cast(TValue *, (intptr_t)ne);
|
||||
}
|
||||
|
||||
#if LJ_HASFFI
|
||||
TValue * LJ_FASTCALL lj_meta_equal_cd(lua_State *L, BCIns ins)
|
||||
{
|
||||
ASMFunction cont = (bc_op(ins) & 1) ? lj_cont_condf : lj_cont_condt;
|
||||
int op = (int)bc_op(ins) & ~1;
|
||||
TValue tv;
|
||||
cTValue *mo, *o2, *o1 = &L->base[bc_a(ins)];
|
||||
if (op == BC_ISEQV) {
|
||||
cTValue *o = &L->base[bc_d(ins)];
|
||||
if (tviscdata(o1)) {
|
||||
o2 = o;
|
||||
} else {
|
||||
o2 = o1; o1 = o;
|
||||
}
|
||||
} else if (op == BC_ISEQS) {
|
||||
setstrV(L, &tv, gco2str(proto_kgc(curr_proto(L), ~(ptrdiff_t)bc_d(ins))));
|
||||
o2 = &tv;
|
||||
} else if (op == BC_ISEQN) {
|
||||
o2 = &mref(curr_proto(L)->k, cTValue)[bc_d(ins)];
|
||||
} else {
|
||||
lua_assert(op == BC_ISEQP);
|
||||
setitype(&tv, ~bc_d(ins));
|
||||
o2 = &tv;
|
||||
}
|
||||
mo = lj_meta_lookup(L, o1, MM_eq);
|
||||
if (LJ_LIKELY(!tvisnil(mo)))
|
||||
return mmcall(L, cont, mo, o1, o2);
|
||||
else
|
||||
return cast(TValue *, (intptr_t)(bc_op(ins) & 1));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Helper for ordered comparisons. String compare, __lt/__le metamethods. */
|
||||
TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op)
|
||||
{
|
||||
if (itype(o1) == itype(o2)) { /* Never called with two numbers. */
|
||||
if (LJ_HASFFI && (tviscdata(o1) || tviscdata(o2))) {
|
||||
ASMFunction cont = (op & 1) ? lj_cont_condf : lj_cont_condt;
|
||||
MMS mm = (op & 2) ? MM_le : MM_lt;
|
||||
cTValue *mo = lj_meta_lookup(L, tviscdata(o1) ? o1 : o2, mm);
|
||||
if (LJ_UNLIKELY(tvisnil(mo))) goto err;
|
||||
return mmcall(L, cont, mo, o1, o2);
|
||||
} else if (itype(o1) == itype(o2)) { /* Never called with two numbers. */
|
||||
if (tvisstr(o1) && tvisstr(o2)) {
|
||||
int32_t res = lj_str_cmp(strV(o1), strV(o2));
|
||||
return cast(TValue *, (intptr_t)(((op&2) ? res <= 0 : res < 0) ^ (op&1)));
|
||||
|
@ -26,6 +26,7 @@ LJ_FUNCA TValue *lj_meta_arith(lua_State *L, TValue *ra, cTValue *rb,
|
||||
LJ_FUNCA TValue *lj_meta_cat(lua_State *L, TValue *top, int left);
|
||||
LJ_FUNCA TValue * LJ_FASTCALL lj_meta_len(lua_State *L, cTValue *o);
|
||||
LJ_FUNCA TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne);
|
||||
LJ_FUNCA TValue * LJ_FASTCALL lj_meta_equal_cd(lua_State *L, BCIns ins);
|
||||
LJ_FUNCA TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op);
|
||||
LJ_FUNCA void lj_meta_call(lua_State *L, TValue *func, TValue *top);
|
||||
LJ_FUNCA void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *base);
|
||||
|
@ -434,7 +434,7 @@ enum {
|
||||
|
||||
#define setvmstate(g, st) ((g)->vmstate = ~LJ_VMST_##st)
|
||||
|
||||
/* Metamethods. */
|
||||
/* Metamethods. ORDER MM */
|
||||
#ifdef LUAJIT_ENABLE_LUA52COMPAT
|
||||
#define MMDEF_52(_) _(pairs) _(ipairs)
|
||||
#else
|
||||
|
@ -812,6 +812,23 @@ static void rec_mm_comp(jit_State *J, RecordIndex *ix, int op)
|
||||
}
|
||||
}
|
||||
|
||||
#if LJ_HASFFI
|
||||
/* Setup call to cdata comparison metamethod. */
|
||||
static void rec_mm_comp_cdata(jit_State *J, RecordIndex *ix, int op, MMS mm)
|
||||
{
|
||||
if (tref_iscdata(ix->val)) {
|
||||
ix->tab = ix->val;
|
||||
copyTV(J->L, &ix->tabv, &ix->valv);
|
||||
} else {
|
||||
lua_assert(tref_iscdata(ix->key));
|
||||
ix->tab = ix->key;
|
||||
copyTV(J->L, &ix->tabv, &ix->keyv);
|
||||
}
|
||||
lj_record_mm_lookup(J, ix, mm);
|
||||
rec_mm_callcomp(J, ix, op);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -- Indexed access ------------------------------------------------------ */
|
||||
|
||||
/* Record bounds-check. */
|
||||
@ -1410,6 +1427,12 @@ void lj_record_ins(jit_State *J)
|
||||
/* -- Comparison ops ---------------------------------------------------- */
|
||||
|
||||
case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT:
|
||||
#if LJ_HASFFI
|
||||
if (tref_iscdata(ra) || tref_iscdata(rc)) {
|
||||
rec_mm_comp_cdata(J, &ix, op, ((int)op & 2) ? MM_le : MM_lt);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* Emit nothing for two numeric or string consts. */
|
||||
if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) {
|
||||
IRType ta = tref_isinteger(ra) ? IRT_INT : tref_type(ra);
|
||||
@ -1452,6 +1475,12 @@ void lj_record_ins(jit_State *J)
|
||||
case BC_ISEQS: case BC_ISNES:
|
||||
case BC_ISEQN: case BC_ISNEN:
|
||||
case BC_ISEQP: case BC_ISNEP:
|
||||
#if LJ_HASFFI
|
||||
if (tref_iscdata(ra) || tref_iscdata(rc)) {
|
||||
rec_mm_comp_cdata(J, &ix, op, MM_eq);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* Emit nothing for two non-table, non-udata consts. */
|
||||
if (!(tref_isk2(ra, rc) && !(tref_istab(ra) || tref_isudata(ra)))) {
|
||||
int diff;
|
||||
|
Loading…
Reference in New Issue
Block a user