Refactoring of conversion ops, part 2: cleanup cdata conversions.

This commit is contained in:
Mike Pall 2010-12-30 00:42:00 +01:00
parent 8bcc5ed021
commit 158de60b8c
3 changed files with 85 additions and 75 deletions

View File

@ -335,7 +335,8 @@ void lj_cconv_ct_ct(CTState *cts, CType *d, CType *s,
case CCX(P, F): case CCX(P, F):
if (!(flags & CCF_CAST) || !(flags & CCF_FROMTV)) goto err_conv; if (!(flags & CCF_CAST) || !(flags & CCF_FROMTV)) goto err_conv;
dinfo = CTINFO(CT_NUM, CTF_UNSIGNED); /* The signed conversion is cheaper. x64 really has 47 bit pointers. */
dinfo = CTINFO(CT_NUM, (LJ_64 && dsize == 8) ? 0 : CTF_UNSIGNED);
goto conv_I_F; goto conv_I_F;
case CCX(P, P): case CCX(P, P):

View File

@ -90,8 +90,10 @@ static IRType crec_ct2irt(CType *ct)
{ {
if (LJ_LIKELY(ctype_isnum(ct->info))) { if (LJ_LIKELY(ctype_isnum(ct->info))) {
if ((ct->info & CTF_FP)) { if ((ct->info & CTF_FP)) {
if (ct->size == sizeof(double)) /* NYI: float IRType. */ if (ct->size == sizeof(double))
return IRT_NUM; return IRT_NUM;
else if (ct->size == sizeof(float))
return IRT_FLOAT;
} else { } else {
uint32_t b = lj_fls(ct->size); uint32_t b = lj_fls(ct->size);
if (b <= 3) if (b <= 3)
@ -99,16 +101,21 @@ static IRType crec_ct2irt(CType *ct)
} }
} else if (ctype_isptr(ct->info)) { } else if (ctype_isptr(ct->info)) {
return (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32; return (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32;
} else if (ctype_iscomplex(ct->info)) {
if (ct->size == 2*sizeof(double))
return IRT_NUM;
else if (ct->size == 2*sizeof(float))
return IRT_FLOAT;
} }
return IRT_CDATA; return IRT_CDATA;
} }
static void crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp) static void crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp)
{ {
CTState *cts = ctype_ctsG(J2G(J));
CTSize dsize = d->size, ssize = s->size; CTSize dsize = d->size, ssize = s->size;
CTInfo dinfo = d->info, sinfo = s->info; CTInfo dinfo = d->info, sinfo = s->info;
IRType dt = crec_ct2irt(d); IRType dt = crec_ct2irt(d);
IRType st = crec_ct2irt(s);
if (ctype_type(dinfo) > CT_MAYCONVERT || ctype_type(sinfo) > CT_MAYCONVERT) if (ctype_type(dinfo) > CT_MAYCONVERT || ctype_type(sinfo) > CT_MAYCONVERT)
goto err_conv; goto err_conv;
@ -134,90 +141,77 @@ static void crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp)
case CCX(I, B): case CCX(I, B):
case CCX(I, I): case CCX(I, I):
conv_I_I: conv_I_I:
lua_assert(ssize >= 4); if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
if (dsize > 8 || ssize > 8) goto err_nyi; #if LJ_64
if (dsize > ssize) /* Zero-extend or sign-extend 32 to 64 bit integer. */ /* Sign-extend 32 to 64 bit integer. */
sp = emitir(IRT(IR_TOI64, dt), sp, if (dsize == 8 && ssize < 8 && !(sinfo & CTF_UNSIGNED))
(sinfo&CTF_UNSIGNED) ? IRTOINT_ZEXT64 : IRTOINT_SEXT64); sp = emitir(IRT(IR_CONV, dt), sp, IRT_INT|IRCONV_SEXT);
/* All other conversions are no-ops on x64. */
#else
if (dsize == 8 && ssize < 8) /* Extend to 64 bit integer. */
sp = emitir(IRT(IR_CONV, dt), sp,
(st < IRT_INT ? IRT_INT : st) |
((sinfo & CTF_UNSIGNED) ? 0 : IRCONV_SEXT));
else if (dsize < 8 && ssize == 8) /* Truncate from 64 bit integer. */
sp = emitir(IRT(IR_CONV, dt < IRT_INT ? IRT_INT : dt), sp, st);
#endif
xstore: xstore:
emitir(IRT(IR_XSTORE, dt), dp, sp); emitir(IRT(IR_XSTORE, dt), dp, sp);
break; break;
case CCX(I, F):
conv_I_F:
if (dsize > 8 || ssize != sizeof(double)) goto err_nyi;
if (dsize == 8) {
if (dt == IRT_U64) goto err_nyi;
sp = emitir(IRT(IR_TOI64, dt), sp, IRTOINT_TRUNCI64);
} else {
sp = emitir(IRTI(IR_TOINT), sp, IRTOINT_ANY); /* NYI: should truncate. */
}
goto xstore;
case CCX(I, C): case CCX(I, C):
if (ssize != 2*sizeof(double)) goto err_nyi; sp = emitir(IRT(IR_XLOAD, st), sp, 0); /* Load re. */
sp = emitir(IRT(IR_XLOAD, IRT_NUM), sp, 0); /* Load re. */ /* fallthrough */
s = ctype_child(cts, s); case CCX(I, F):
sinfo = s->info; if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
ssize = s->size; sp = emitir(IRT(IR_CONV, dsize < 4 ? IRT_INT : dt), sp, st|IRCONV_TRUNC);
goto conv_I_F; /* Just convert re. */ goto xstore;
case CCX(I, P): case CCX(I, P):
case CCX(I, A): case CCX(I, A):
sinfo = CTINFO(CT_NUM, CTF_UNSIGNED); sinfo = CTINFO(CT_NUM, CTF_UNSIGNED);
ssize = CTSIZE_PTR; ssize = CTSIZE_PTR;
/* st = IRT_UINTP;
** Note: Overriding the size is also required for pointers, since
** crec_ct_tv passes IRT_P32/IRT_P64 independently of the C type size.
** This avoids unnecessary zero-extensions on x64.
*/
goto conv_I_I; goto conv_I_I;
/* Destination is a floating-point number. */ /* Destination is a floating-point number. */
case CCX(F, B): case CCX(F, B):
case CCX(F, I): case CCX(F, I):
conv_F_I: conv_F_I:
if (dsize != sizeof(double) || ssize > 4) goto err_nyi; if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
if (ssize == 4 && (sinfo & CTF_UNSIGNED)) goto err_nyi; sp = emitir(IRT(IR_CONV, dt), sp, st < IRT_INT ? IRT_INT : st);
sp = emitir(IRTI(IR_TONUM), sp, 0);
goto xstore;
case CCX(F, F):
conv_F_F:
if (dsize != sizeof(double) || ssize != sizeof(double)) goto err_nyi;
goto xstore; goto xstore;
case CCX(F, C): case CCX(F, C):
if (ssize != 2*sizeof(double)) goto err_nyi; sp = emitir(IRT(IR_XLOAD, st), sp, 0); /* Load re. */
sp = emitir(IRT(IR_XLOAD, IRT_NUM), sp, 0); /* Load re. */ /* fallthrough */
s = ctype_child(cts, s); case CCX(F, F):
sinfo = s->info; conv_F_F:
ssize = s->size; if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
goto conv_F_F; /* Ignore im, and convert from re. */ if (dt != st) sp = emitir(IRT(IR_CONV, dt), sp, st);
goto xstore;
/* Destination is a complex number. */ /* Destination is a complex number. */
case CCX(C, I): case CCX(C, I):
case CCX(C, F): case CCX(C, F):
d = ctype_child(cts, d);
dinfo = d->info;
dsize = d->size;
dt = crec_ct2irt(d);
if (dt == IRT_CDATA) goto err_nyi;
{ /* Clear im. */ { /* Clear im. */
TRef dpim = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, dsize)); TRef ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, (dsize >> 1)));
emitir(IRT(IR_XSTORE, IRT_NUM), dpim, lj_ir_knum(J, 0)); emitir(IRT(IR_XSTORE, dt), ptr, lj_ir_knum(J, 0));
} }
/* Convert to re. */ /* Convert to re. */
if ((sinfo & CTF_FP)) goto conv_F_F; else goto conv_F_I; if ((sinfo & CTF_FP)) goto conv_F_F; else goto conv_F_I;
case CCX(C, C): case CCX(C, C):
d = ctype_child(cts, d); if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi;
dinfo = d->info;
dsize = d->size;
dt = crec_ct2irt(d);
if (dt == IRT_CDATA) goto err_nyi;
{ {
TRef spim = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, dsize)); TRef re, im, ptr;
TRef re = emitir(IRT(IR_XLOAD, IRT_NUM), sp, 0); re = emitir(IRT(IR_XLOAD, st), sp, 0);
TRef im = emitir(IRT(IR_XLOAD, IRT_NUM), spim, 0); ptr = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, (ssize >> 1)));
TRef dpim = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, dsize)); im = emitir(IRT(IR_XLOAD, st), ptr, 0);
emitir(IRT(IR_XSTORE, IRT_NUM), dp, re); if (dt != st) {
emitir(IRT(IR_XSTORE, IRT_NUM), dpim, im); re = emitir(IRT(IR_CONV, dt), re, st);
im = emitir(IRT(IR_CONV, dt), im, st);
}
emitir(IRT(IR_XSTORE, dt), dp, re);
ptr = emitir(IRT(IR_ADD, IRT_PTR), dp, lj_ir_kintp(J, (dsize >> 1)));
emitir(IRT(IR_XSTORE, dt), ptr, im);
} }
break; break;
@ -230,19 +224,23 @@ static void crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp)
/* Destination is a pointer. */ /* Destination is a pointer. */
case CCX(P, P): case CCX(P, P):
/* Note: ok on x64, since all 32 bit ops clear the upper part of the reg. */
goto xstore;
case CCX(P, A): case CCX(P, A):
case CCX(P, S): case CCX(P, S):
ssize = CTSIZE_PTR; /* There are only 32 bit pointers/addresses on 32 bit machines.
sinfo = CTINFO(CT_NUM, CTF_UNSIGNED); ** Also ok on x64, since all 32 bit ops clear the upper part of the reg.
/* fallthrough */ */
goto xstore;
case CCX(P, I): case CCX(P, I):
dinfo = CTINFO(CT_NUM, CTF_UNSIGNED); if (st == IRT_CDATA) goto err_nyi;
goto conv_I_I; if (!LJ_64 && ssize == 8) /* Truncate from 64 bit integer. */
sp = emitir(IRT(IR_CONV, IRT_U32), sp, st);
goto xstore;
case CCX(P, F): case CCX(P, F):
dinfo = CTINFO(CT_NUM, CTF_UNSIGNED); if (st == IRT_CDATA) goto err_nyi;
goto conv_I_F; /* The signed conversion is cheaper. x64 really has 47 bit pointers. */
sp = emitir(IRT(IR_CONV, (LJ_64 && dsize == 8) ? IRT_I64 : IRT_U32),
sp, st|IRCONV_TRUNC);
goto xstore;
/* Destination is an array. */ /* Destination is an array. */
case CCX(A, A): case CCX(A, A):
@ -269,24 +267,32 @@ static TRef crec_tv_ct(jit_State *J, CType *s, CTypeID sid, TRef sp)
lua_assert(!ctype_isenum(sinfo)); lua_assert(!ctype_isenum(sinfo));
if (ctype_isnum(sinfo)) { if (ctype_isnum(sinfo)) {
IRType t = crec_ct2irt(s); IRType t = crec_ct2irt(s);
TRef tr;
if ((sinfo & CTF_BOOL)) if ((sinfo & CTF_BOOL))
goto err_nyi; /* NYI: specialize to the result. */ goto err_nyi; /* NYI: specialize to the result. */
if (t == IRT_CDATA) if (t == IRT_CDATA)
goto err_nyi; /* NYI: copyval of >64 bit integers. */ goto err_nyi; /* NYI: copyval of >64 bit integers. */
if (t >= IRT_U32) tr = emitir(IRT(IR_XLOAD, t), sp, 0);
goto err_nyi; /* NYI: on-trace handling of U32/I64/U64. */ if (t == IRT_FLOAT || t == IRT_U32) { /* Keep uint32_t/float as numbers. */
return emitir(IRT(IR_XLOAD, t), sp, 0); tr = emitir(IRT(IR_CONV, IRT_NUM), tr, t);
} else if (t == IRT_I64 || t == IRT_U64) { /* Box 64 bit integer. */
TRef dp = emitir(IRTG(IR_CNEW, IRT_CDATA), lj_ir_kint(J, sid), TREF_NIL);
TRef ptr = emitir(IRT(IR_ADD, IRT_PTR), dp,
lj_ir_kintp(J, sizeof(GCcdata)));
emitir(IRT(IR_XSTORE, t), ptr, tr);
return dp;
}
return tr;
} else if (ctype_isptr(sinfo)) { } else if (ctype_isptr(sinfo)) {
IRType t = (LJ_64 && s->size == 8) ? IRT_P64 : IRT_P32; IRType t = (LJ_64 && s->size == 8) ? IRT_P64 : IRT_P32;
sp = emitir(IRT(IR_XLOAD, t), sp, 0); sp = emitir(IRT(IR_XLOAD, t), sp, 0);
} else if (ctype_isrefarray(sinfo) || ctype_isstruct(sinfo)) { } else if (ctype_isrefarray(sinfo) || ctype_isstruct(sinfo)) {
cts->L = J->L; cts->L = J->L;
sid = lj_ctype_intern(cts, CTINFO_REF(sid), CTSIZE_PTR); /* Create ref. */ sid = lj_ctype_intern(cts, CTINFO_REF(sid), CTSIZE_PTR); /* Create ref. */
} else if (ctype_iscomplex(sinfo)) { } else if (ctype_iscomplex(sinfo)) { /* Unbox/box complex. */
IRType t = s->size == 2*sizeof(double) ? IRT_NUM : IRT_CDATA; IRType t = s->size == 2*sizeof(double) ? IRT_NUM : IRT_FLOAT;
ptrdiff_t esz = (ptrdiff_t)(s->size >> 1); ptrdiff_t esz = (ptrdiff_t)(s->size >> 1);
TRef ptr, tr1, tr2, dp; TRef ptr, tr1, tr2, dp;
if (t == IRT_CDATA) goto err_nyi; /* NYI: float IRType. */
dp = emitir(IRTG(IR_CNEW, IRT_CDATA), lj_ir_kint(J, sid), TREF_NIL); dp = emitir(IRTG(IR_CNEW, IRT_CDATA), lj_ir_kint(J, sid), TREF_NIL);
tr1 = emitir(IRT(IR_XLOAD, t), sp, 0); tr1 = emitir(IRT(IR_XLOAD, t), sp, 0);
ptr = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, esz)); ptr = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, esz));
@ -301,6 +307,7 @@ static TRef crec_tv_ct(jit_State *J, CType *s, CTypeID sid, TRef sp)
err_nyi: err_nyi:
lj_trace_err(J, LJ_TRERR_NYICONV); lj_trace_err(J, LJ_TRERR_NYICONV);
} }
/* Box pointer or ref. */
return emitir(IRTG(IR_CNEWP, IRT_CDATA), lj_ir_kint(J, sid), sp); return emitir(IRTG(IR_CNEWP, IRT_CDATA), lj_ir_kint(J, sid), sp);
} }

View File

@ -222,6 +222,7 @@ IRFLDEF(FLENUM)
/* CONV mode, stored in op2. Lowest 8 bits is the IRType of the source. */ /* CONV mode, stored in op2. Lowest 8 bits is the IRType of the source. */
#define IRCONV_TRUNC 0x100 /* Truncate number to integer. */ #define IRCONV_TRUNC 0x100 /* Truncate number to integer. */
#define IRCONV_SEXT 0x200 /* Sign-extend integer to integer. */ #define IRCONV_SEXT 0x200 /* Sign-extend integer to integer. */
#define IRCONV_MODEMASK 0x3ff
#define IRCONV_CSH 10 #define IRCONV_CSH 10
/* Number to integer conversion mode. Ordered by strength of the checks. */ /* Number to integer conversion mode. Ordered by strength of the checks. */
#define IRCONV_TOBIT (0<<IRCONV_CSH) /* None. Cache only: TOBIT conv. */ #define IRCONV_TOBIT (0<<IRCONV_CSH) /* None. Cache only: TOBIT conv. */
@ -348,6 +349,7 @@ IRTDEF(IRTENUM)
/* Native pointer type and the corresponding integer type. */ /* Native pointer type and the corresponding integer type. */
IRT_PTR = LJ_64 ? IRT_P64 : IRT_P32, IRT_PTR = LJ_64 ? IRT_P64 : IRT_P32,
IRT_INTP = LJ_64 ? IRT_I64 : IRT_INT, IRT_INTP = LJ_64 ? IRT_I64 : IRT_INT,
IRT_UINTP = LJ_64 ? IRT_U64 : IRT_U32,
/* Additional flags. */ /* Additional flags. */
IRT_MARK = 0x20, /* Marker for misc. purposes. */ IRT_MARK = 0x20, /* Marker for misc. purposes. */