diff --git a/src/lj_carith.c b/src/lj_carith.c index f1435e1e..a59665d8 100644 --- a/src/lj_carith.c +++ b/src/lj_carith.c @@ -41,6 +41,9 @@ static int carith_checkarg(lua_State *L, CTState *cts, CDArith *ca) } ca->ct[i] = ct; ca->p[i] = p; + } else if (tvisint(o)) { + ca->ct[i] = ctype_get(cts, CTID_INT32); + ca->p[i] = (uint8_t *)&o->i; } else if (tvisnum(o)) { ca->ct[i] = ctype_get(cts, CTID_DOUBLE); ca->p[i] = (uint8_t *)&o->n; @@ -84,7 +87,7 @@ static int carith_ptr(lua_State *L, CTState *cts, CDArith *ca, MMS mm) /* 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); + setintptrV(L->top-1, (int32_t)diff); return 1; } else if (mm == MM_lt) { /* Pointer comparison (unsigned). */ setboolV(L->top-1, ((uintptr_t)pp < (uintptr_t)pp2)); diff --git a/src/lj_ccall.c b/src/lj_ccall.c index 3f548c30..a3908e50 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c @@ -315,7 +315,7 @@ static void ccall_struct_ret(CCallState *cc, int *rcl, uint8_t *dp, CTSize sz) /* Infer the destination CTypeID for a vararg argument. */ static CTypeID ccall_ctid_vararg(CTState *cts, cTValue *o) { - if (tvisnum(o)) { + if (tvisnumber(o)) { return CTID_DOUBLE; } else if (tviscdata(o)) { CTypeID id = cdataV(o)->typeid; diff --git a/src/lj_cconv.c b/src/lj_cconv.c index 94a9895f..884edef1 100644 --- a/src/lj_cconv.c +++ b/src/lj_cconv.c @@ -375,10 +375,20 @@ int lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid, if (ctype_isnum(sinfo)) { if (!ctype_isbool(sinfo)) { if (ctype_isinteger(sinfo) && s->size > 4) goto copyval; - lj_cconv_ct_ct(cts, ctype_get(cts, CTID_DOUBLE), s, - (uint8_t *)&o->n, sp, 0); - /* Numbers are NOT canonicalized here! Beware of uninitialized data. */ - lua_assert(tvisnum(o)); + if (LJ_DUALNUM && ctype_isinteger(sinfo)) { + int32_t i; + lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT32), s, + (uint8_t *)&i, sp, 0); + if ((sinfo & CTF_UNSIGNED) && i < 0) + setnumV(o, (lua_Number)(uint32_t)i); + else + setintV(o, i); + } else { + lj_cconv_ct_ct(cts, ctype_get(cts, CTID_DOUBLE), s, + (uint8_t *)&o->n, sp, 0); + /* Numbers are NOT canonicalized here! Beware of uninitialized data. */ + lua_assert(tvisnum(o)); + } } else { uint32_t b = ((*sp) & 1); setboolV(o, b); @@ -426,10 +436,15 @@ int lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp) lj_err_caller(cts->L, LJ_ERR_FFI_NYIPACKBIT); if (!(info & CTF_BOOL)) { CTSize shift = 32 - bsz; - if (!(info & CTF_UNSIGNED)) - setnumV(o, (lua_Number)((int32_t)(val << (shift-pos)) >> shift)); - else - setnumV(o, (lua_Number)((val << (shift-pos)) >> shift)); + if (!(info & CTF_UNSIGNED)) { + setintV(o, (int32_t)(val << (shift-pos)) >> shift); + } else { + val = (val << (shift-pos)) >> shift; + if (!LJ_DUALNUM || (int32_t)val < 0) + setnumV(o, (lua_Number)(uint32_t)val); + else + setintV(o, (int32_t)val); + } } else { lua_assert(bsz == 1); setboolV(o, (val >> pos) & 1); @@ -519,7 +534,11 @@ void lj_cconv_ct_tv(CTState *cts, CType *d, CType *s; void *tmpptr; uint8_t tmpbool, *sp = (uint8_t *)&tmpptr; - if (LJ_LIKELY(tvisnum(o))) { + if (LJ_LIKELY(tvisint(o))) { + sp = (uint8_t *)&o->i; + sid = CTID_INT32; + flags |= CCF_FROMTV; + } else if (LJ_LIKELY(tvisnum(o))) { sp = (uint8_t *)&o->n; sid = CTID_DOUBLE; flags |= CCF_FROMTV; diff --git a/src/lj_cdata.c b/src/lj_cdata.c index af78d05e..ae66b4b5 100644 --- a/src/lj_cdata.c +++ b/src/lj_cdata.c @@ -88,7 +88,10 @@ collect_attrib: } lua_assert(!ctype_isref(ct->info)); /* Interning rejects refs to refs. */ - if (tvisnum(key)) { /* Numeric key. */ + if (tvisint(key)) { + idx = (ptrdiff_t)intV(key); + goto integer_key; + } else if (tvisnum(key)) { /* Numeric key. */ idx = LJ_64 ? (ptrdiff_t)numV(key) : (ptrdiff_t)lj_num2int(numV(key)); integer_key: if (ctype_ispointer(ct->info)) { @@ -171,10 +174,10 @@ static void cdata_getconst(CTState *cts, TValue *o, CType *ct) CType *ctt = ctype_child(cts, ct); lua_assert(ctype_isinteger(ctt->info) && ctt->size <= 4); /* Constants are already zero-extended/sign-extended to 32 bits. */ - if (!(ctt->info & CTF_UNSIGNED)) - setintV(o, (int32_t)ct->size); - else + if ((ctt->info & CTF_UNSIGNED) && (int32_t)ct->size < 0) setnumV(o, (lua_Number)(uint32_t)ct->size); + else + setintV(o, (int32_t)ct->size); } /* Get C data value and convert to TValue. */ diff --git a/src/lj_clib.c b/src/lj_clib.c index 98d74cde..d7721860 100644 --- a/src/lj_clib.c +++ b/src/lj_clib.c @@ -266,10 +266,10 @@ TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name) if (ctype_isconstval(ct->info)) { CType *ctt = ctype_child(cts, ct); lua_assert(ctype_isinteger(ctt->info) && ctt->size <= 4); - if ((ctt->info & CTF_UNSIGNED) && ctt->size == 4) + if ((ctt->info & CTF_UNSIGNED) && (int32_t)ct->size < 0) setnumV(tv, (lua_Number)(uint32_t)ct->size); else - setnumV(tv, (lua_Number)(int32_t)ct->size); + setintV(tv, (int32_t)ct->size); } else { const char *sym = clib_extsym(cts, ct, name); void *p = clib_getsym(cl, sym);