mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-08 07:34:07 +00:00
JIT-compile bitfield stores
This commit implements compilation of bitfield stores. The generated IR is not good – in fact, it’s downright terrible – but it is certainly a big improvement over these operations being banished to the interpreter.
This commit is contained in:
parent
bc01981736
commit
bbec2d4760
@ -401,8 +401,20 @@ static int crec_isnonzero(CType *s, void *p)
|
||||
}
|
||||
}
|
||||
|
||||
static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp,
|
||||
void *svisnz)
|
||||
/* Load a C type from a bitfield ------------------------------------------ */
|
||||
static TRef crec_bitfield_load(jit_State *J, CTypeID sid, TRef tr) {
|
||||
uint32_t pos = ctype_bitpos(sid);
|
||||
uint32_t bsz = ctype_bitbsz(sid);
|
||||
CTSize shift = 32 - bsz;
|
||||
lua_assert(ctype_isbitfield(sid));
|
||||
lua_assert(bsz > 0 && "Zero sized bitfield is invalid");
|
||||
tr = emitir(IRT(IR_BSHL, IRT_INT), tr, lj_ir_kint(J, shift - pos));
|
||||
return emitir(IRT(IR_BSHR, IRT_INT), tr, lj_ir_kint(J, shift));
|
||||
/* if crosses container boundary: interpreter will throw */
|
||||
}
|
||||
|
||||
static TRef crec_ct_ct(jit_State *J, CType *d, CTypeID bitfield_val,
|
||||
CType *s, TRef dp, TRef sp, void *svisnz)
|
||||
{
|
||||
IRType dt = crec_ct2irt(ctype_ctsG(J2G(J)), d);
|
||||
IRType st = crec_ct2irt(ctype_ctsG(J2G(J)), s);
|
||||
@ -449,6 +461,23 @@ static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp,
|
||||
else if (st == IRT_INT)
|
||||
sp = lj_opt_narrow_toint(J, sp);
|
||||
xstore:
|
||||
if (bitfield_val) {
|
||||
CTSize bsz, pos;
|
||||
TRef target;
|
||||
CTSize shift;
|
||||
TRef k, loaded;
|
||||
lua_assert(ctype_isbitfield(bitfield_val));
|
||||
bsz = ctype_bitbsz(bitfield_val);
|
||||
pos = ctype_bitpos(bitfield_val);
|
||||
k = lj_ir_kint(J, 8*pos);
|
||||
target = emitir(IRT(IR_XLOAD, IRT_INT), dp, k);
|
||||
shift = ~(((uint32_t)-1 >> (32 - bsz)) << pos);
|
||||
lua_assert(bsz && "Zero sized bitfield is invalid!");
|
||||
loaded = emitir(IRT(IR_BAND, IRT_INT), target, lj_ir_kint(J, shift));
|
||||
sp = emitir(IRT(IR_BSHL, IRT_INT), sp, lj_ir_kint(J, pos));
|
||||
sp = emitir(IRT(IR_BAND, IRT_INT), sp, lj_ir_kint(J, ~shift));
|
||||
sp = emitir(IRT(IR_BOR, IRT_INT), sp, loaded);
|
||||
}
|
||||
if (dt == IRT_I64 || dt == IRT_U64) lj_needsplit(J);
|
||||
if (dp == 0) return sp;
|
||||
emitir(IRT(IR_XSTORE, dt), dp, sp);
|
||||
@ -558,22 +587,6 @@ static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Load a C type from a bitfield ------------------------------------------ */
|
||||
static TRef crec_bitfield_load(jit_State *J, CTypeID sid, TRef tr) {
|
||||
uint32_t pos = ctype_bitpos(sid);
|
||||
uint32_t bsz = ctype_bitbsz(sid);
|
||||
lua_assert(ctype_isbitfield(sid));
|
||||
lua_assert(bsz > 0 && "Zero sized bitfield is invalid");
|
||||
if (!(sid & CTF_BOOL)) {
|
||||
CTSize shift = 32 - bsz;
|
||||
tr = emitir(IRT(IR_BSHL, IRT_INT), tr, lj_ir_kint(J, shift - pos));
|
||||
return emitir(IRT(IR_BSHR, IRT_INT), tr, lj_ir_kint(J, shift));
|
||||
/* if crosses container boundary: interpreter will throw */
|
||||
} else {
|
||||
lj_trace_err(J, LJ_TRERR_NYICONV);
|
||||
}
|
||||
}
|
||||
|
||||
/* -- Convert C type to TValue (load) ------------------------------------- */
|
||||
|
||||
static TRef crec_tv_ct(jit_State *J, CType *s, CTypeID sid, TRef sp)
|
||||
@ -633,8 +646,8 @@ boolfield:
|
||||
}
|
||||
|
||||
/* -- Convert TValue to C type (store) ------------------------------------ */
|
||||
|
||||
static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval)
|
||||
static TRef crec_ct_tv_(jit_State *J, CType *d, CTypeID bitfield_val, TRef dp,
|
||||
TRef sp, cTValue *sval)
|
||||
{
|
||||
CTState *cts = ctype_ctsG(J2G(J));
|
||||
CTypeID sid = CTID_P_VOID;
|
||||
@ -725,7 +738,11 @@ static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval)
|
||||
s = ctype_get(cts, sid);
|
||||
doconv:
|
||||
if (ctype_isenum(d->info)) d = ctype_child(cts, d);
|
||||
return crec_ct_ct(J, d, s, dp, sp, svisnz);
|
||||
return crec_ct_ct(J, d, bitfield_val, s, dp, sp, svisnz);
|
||||
}
|
||||
|
||||
static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval) {
|
||||
return crec_ct_tv_(J, d, 0, dp, sp, sval);
|
||||
}
|
||||
|
||||
/* -- C data metamethods -------------------------------------------------- */
|
||||
@ -876,8 +893,6 @@ again:
|
||||
J->base[0] = lj_ir_kint(J, (int32_t)fct->size);
|
||||
return; /* Interpreter will throw for newindex. */
|
||||
} else if (ctype_isbitfield(fct->info)) {
|
||||
if (rd->data != 0)
|
||||
lj_trace_err(J, LJ_TRERR_NYICONV);
|
||||
isbitfield = 1;
|
||||
bitfield_val = fct->info;
|
||||
sid = ctype_underlying_type(bitfield_val);
|
||||
@ -930,7 +945,7 @@ again:
|
||||
} else { /* __newindex metamethod. */
|
||||
rd->nres = 0;
|
||||
J->needsnap = 1;
|
||||
crec_ct_tv(J, ct, ptr, J->base[2], &rd->argv[2]);
|
||||
crec_ct_tv_(J, ct, bitfield_val, ptr, J->base[2], &rd->argv[2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user