DUALNUM: Handle integer type in FFI.

This commit is contained in:
Mike Pall 2011-02-27 01:31:22 +01:00
parent d437086c5a
commit c031d4b6a0
5 changed files with 42 additions and 17 deletions

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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. */

View File

@ -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);