Improve assertions.
This commit is contained in:
122
src/lj_asm.c
122
src/lj_asm.c
@@ -96,6 +96,12 @@ typedef struct ASMState {
|
||||
uint16_t parentmap[LJ_MAX_JSLOTS]; /* Parent instruction to RegSP map. */
|
||||
} ASMState;
|
||||
|
||||
#ifdef LUA_USE_ASSERT
|
||||
#define lj_assertA(c, ...) lj_assertG_(J2G(as->J), (c), __VA_ARGS__)
|
||||
#else
|
||||
#define lj_assertA(c, ...) ((void)as)
|
||||
#endif
|
||||
|
||||
#define IR(ref) (&as->ir[(ref)])
|
||||
|
||||
#define ASMREF_TMP1 REF_TRUE /* Temp. register. */
|
||||
@@ -127,9 +133,8 @@ static LJ_AINLINE void checkmclim(ASMState *as)
|
||||
#ifdef LUA_USE_ASSERT
|
||||
if (as->mcp + MCLIM_REDZONE < as->mcp_prev) {
|
||||
IRIns *ir = IR(as->curins+1);
|
||||
fprintf(stderr, "RED ZONE OVERFLOW: %p IR %04d %02d %04d %04d\n", as->mcp,
|
||||
as->curins+1-REF_BIAS, ir->o, ir->op1-REF_BIAS, ir->op2-REF_BIAS);
|
||||
lua_assert(0);
|
||||
lj_assertA(0, "red zone overflow: %p IR %04d %02d %04d %04d\n", as->mcp,
|
||||
as->curins+1-REF_BIAS, ir->o, ir->op1-REF_BIAS, ir->op2-REF_BIAS);
|
||||
}
|
||||
#endif
|
||||
if (LJ_UNLIKELY(as->mcp < as->mclim)) asm_mclimit(as);
|
||||
@@ -243,7 +248,7 @@ static void ra_dprintf(ASMState *as, const char *fmt, ...)
|
||||
*p++ = *q >= 'A' && *q <= 'Z' ? *q + 0x20 : *q;
|
||||
} else {
|
||||
*p++ = '?';
|
||||
lua_assert(0);
|
||||
lj_assertA(0, "bad register %d for debug format \"%s\"", r, fmt);
|
||||
}
|
||||
} else if (e[1] == 'f' || e[1] == 'i') {
|
||||
IRRef ref;
|
||||
@@ -261,7 +266,7 @@ static void ra_dprintf(ASMState *as, const char *fmt, ...)
|
||||
} else if (e[1] == 'x') {
|
||||
p += sprintf(p, "%08x", va_arg(argp, int32_t));
|
||||
} else {
|
||||
lua_assert(0);
|
||||
lj_assertA(0, "bad debug format code");
|
||||
}
|
||||
fmt = e+2;
|
||||
}
|
||||
@@ -320,7 +325,7 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
||||
Reg r;
|
||||
if (ra_iskref(ref)) {
|
||||
r = ra_krefreg(ref);
|
||||
lua_assert(!rset_test(as->freeset, r));
|
||||
lj_assertA(!rset_test(as->freeset, r), "rematk of free reg %d", r);
|
||||
ra_free(as, r);
|
||||
ra_modified(as, r);
|
||||
#if LJ_64
|
||||
@@ -332,7 +337,9 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
||||
}
|
||||
ir = IR(ref);
|
||||
r = ir->r;
|
||||
lua_assert(ra_hasreg(r) && !ra_hasspill(ir->s));
|
||||
lj_assertA(ra_hasreg(r), "rematk of K%03d has no reg", REF_BIAS - ref);
|
||||
lj_assertA(!ra_hasspill(ir->s),
|
||||
"rematk of K%03d has spill slot [%x]", REF_BIAS - ref, ir->s);
|
||||
ra_free(as, r);
|
||||
ra_modified(as, r);
|
||||
ir->r = RID_INIT; /* Do not keep any hint. */
|
||||
@@ -346,7 +353,8 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
||||
ra_sethint(ir->r, RID_BASE); /* Restore BASE register hint. */
|
||||
emit_getgl(as, r, jit_base);
|
||||
} else if (emit_canremat(ASMREF_L) && ir->o == IR_KPRI) {
|
||||
lua_assert(irt_isnil(ir->t)); /* REF_NIL stores ASMREF_L register. */
|
||||
/* REF_NIL stores ASMREF_L register. */
|
||||
lj_assertA(irt_isnil(ir->t), "rematk of bad ASMREF_L");
|
||||
emit_getgl(as, r, cur_L);
|
||||
#if LJ_64
|
||||
} else if (ir->o == IR_KINT64) {
|
||||
@@ -359,8 +367,9 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
lua_assert(ir->o == IR_KINT || ir->o == IR_KGC ||
|
||||
ir->o == IR_KPTR || ir->o == IR_KKPTR || ir->o == IR_KNULL);
|
||||
lj_assertA(ir->o == IR_KINT || ir->o == IR_KGC ||
|
||||
ir->o == IR_KPTR || ir->o == IR_KKPTR || ir->o == IR_KNULL,
|
||||
"rematk of bad IR op %d", ir->o);
|
||||
emit_loadi(as, r, ir->i);
|
||||
}
|
||||
return r;
|
||||
@@ -370,7 +379,8 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
||||
static int32_t ra_spill(ASMState *as, IRIns *ir)
|
||||
{
|
||||
int32_t slot = ir->s;
|
||||
lua_assert(ir >= as->ir + REF_TRUE);
|
||||
lj_assertA(ir >= as->ir + REF_TRUE,
|
||||
"spill of K%03d", REF_BIAS - (int)(ir - as->ir));
|
||||
if (!ra_hasspill(slot)) {
|
||||
if (irt_is64(ir->t)) {
|
||||
slot = as->evenspill;
|
||||
@@ -395,7 +405,9 @@ static Reg ra_releasetmp(ASMState *as, IRRef ref)
|
||||
{
|
||||
IRIns *ir = IR(ref);
|
||||
Reg r = ir->r;
|
||||
lua_assert(ra_hasreg(r) && !ra_hasspill(ir->s));
|
||||
lj_assertA(ra_hasreg(r), "release of TMP%d has no reg", ref-ASMREF_TMP1+1);
|
||||
lj_assertA(!ra_hasspill(ir->s),
|
||||
"release of TMP%d has spill slot [%x]", ref-ASMREF_TMP1+1, ir->s);
|
||||
ra_free(as, r);
|
||||
ra_modified(as, r);
|
||||
ir->r = RID_INIT;
|
||||
@@ -411,7 +423,7 @@ static Reg ra_restore(ASMState *as, IRRef ref)
|
||||
IRIns *ir = IR(ref);
|
||||
int32_t ofs = ra_spill(as, ir); /* Force a spill slot. */
|
||||
Reg r = ir->r;
|
||||
lua_assert(ra_hasreg(r));
|
||||
lj_assertA(ra_hasreg(r), "restore of IR %04d has no reg", ref - REF_BIAS);
|
||||
ra_sethint(ir->r, r); /* Keep hint. */
|
||||
ra_free(as, r);
|
||||
if (!rset_test(as->weakset, r)) { /* Only restore non-weak references. */
|
||||
@@ -440,14 +452,15 @@ static Reg ra_evict(ASMState *as, RegSet allow)
|
||||
{
|
||||
IRRef ref;
|
||||
RegCost cost = ~(RegCost)0;
|
||||
lua_assert(allow != RSET_EMPTY);
|
||||
lj_assertA(allow != RSET_EMPTY, "evict from empty set");
|
||||
if (RID_NUM_FPR == 0 || allow < RID2RSET(RID_MAX_GPR)) {
|
||||
GPRDEF(MINCOST)
|
||||
} else {
|
||||
FPRDEF(MINCOST)
|
||||
}
|
||||
ref = regcost_ref(cost);
|
||||
lua_assert(ra_iskref(ref) || (ref >= as->T->nk && ref < as->T->nins));
|
||||
lj_assertA(ra_iskref(ref) || (ref >= as->T->nk && ref < as->T->nins),
|
||||
"evict of out-of-range IR %04d", ref - REF_BIAS);
|
||||
/* Preferably pick any weak ref instead of a non-weak, non-const ref. */
|
||||
if (!irref_isk(ref) && (as->weakset & allow)) {
|
||||
IRIns *ir = IR(ref);
|
||||
@@ -605,7 +618,8 @@ static Reg ra_allocref(ASMState *as, IRRef ref, RegSet allow)
|
||||
IRIns *ir = IR(ref);
|
||||
RegSet pick = as->freeset & allow;
|
||||
Reg r;
|
||||
lua_assert(ra_noreg(ir->r));
|
||||
lj_assertA(ra_noreg(ir->r),
|
||||
"IR %04d already has reg %d", ref - REF_BIAS, ir->r);
|
||||
if (pick) {
|
||||
/* First check register hint from propagation or PHI. */
|
||||
if (ra_hashint(ir->r)) {
|
||||
@@ -669,8 +683,10 @@ static void ra_rename(ASMState *as, Reg down, Reg up)
|
||||
IRIns *ir = IR(ref);
|
||||
ir->r = (uint8_t)up;
|
||||
as->cost[down] = 0;
|
||||
lua_assert((down < RID_MAX_GPR) == (up < RID_MAX_GPR));
|
||||
lua_assert(!rset_test(as->freeset, down) && rset_test(as->freeset, up));
|
||||
lj_assertA((down < RID_MAX_GPR) == (up < RID_MAX_GPR),
|
||||
"rename between GPR/FPR %d and %d", down, up);
|
||||
lj_assertA(!rset_test(as->freeset, down), "rename from free reg %d", down);
|
||||
lj_assertA(rset_test(as->freeset, up), "rename to non-free reg %d", up);
|
||||
ra_free(as, down); /* 'down' is free ... */
|
||||
ra_modified(as, down);
|
||||
rset_clear(as->freeset, up); /* ... and 'up' is now allocated. */
|
||||
@@ -711,7 +727,7 @@ static void ra_destreg(ASMState *as, IRIns *ir, Reg r)
|
||||
{
|
||||
Reg dest = ra_dest(as, ir, RID2RSET(r));
|
||||
if (dest != r) {
|
||||
lua_assert(rset_test(as->freeset, r));
|
||||
lj_assertA(rset_test(as->freeset, r), "dest reg %d is not free", r);
|
||||
ra_modified(as, r);
|
||||
emit_movrr(as, ir, dest, r);
|
||||
}
|
||||
@@ -744,8 +760,9 @@ static void ra_left(ASMState *as, Reg dest, IRRef lref)
|
||||
#endif
|
||||
#endif
|
||||
} else if (ir->o != IR_KPRI) {
|
||||
lua_assert(ir->o == IR_KINT || ir->o == IR_KGC ||
|
||||
ir->o == IR_KPTR || ir->o == IR_KKPTR || ir->o == IR_KNULL);
|
||||
lj_assertA(ir->o == IR_KINT || ir->o == IR_KGC ||
|
||||
ir->o == IR_KPTR || ir->o == IR_KKPTR || ir->o == IR_KNULL,
|
||||
"K%03d has bad IR op %d", REF_BIAS - lref, ir->o);
|
||||
emit_loadi(as, dest, ir->i);
|
||||
return;
|
||||
}
|
||||
@@ -887,11 +904,14 @@ static void asm_snap_alloc1(ASMState *as, IRRef ref)
|
||||
#endif
|
||||
{ /* Allocate stored values for TNEW, TDUP and CNEW. */
|
||||
IRIns *irs;
|
||||
lua_assert(ir->o == IR_TNEW || ir->o == IR_TDUP || ir->o == IR_CNEW);
|
||||
lj_assertA(ir->o == IR_TNEW || ir->o == IR_TDUP || ir->o == IR_CNEW,
|
||||
"sink of IR %04d has bad op %d", ref - REF_BIAS, ir->o);
|
||||
for (irs = IR(as->snapref-1); irs > ir; irs--)
|
||||
if (irs->r == RID_SINK && asm_sunk_store(as, ir, irs)) {
|
||||
lua_assert(irs->o == IR_ASTORE || irs->o == IR_HSTORE ||
|
||||
irs->o == IR_FSTORE || irs->o == IR_XSTORE);
|
||||
lj_assertA(irs->o == IR_ASTORE || irs->o == IR_HSTORE ||
|
||||
irs->o == IR_FSTORE || irs->o == IR_XSTORE,
|
||||
"sunk store IR %04d has bad op %d",
|
||||
(int)(irs - as->ir) - REF_BIAS, irs->o);
|
||||
asm_snap_alloc1(as, irs->op2);
|
||||
if (LJ_32 && (irs+1)->o == IR_HIOP)
|
||||
asm_snap_alloc1(as, (irs+1)->op2);
|
||||
@@ -938,7 +958,9 @@ static void asm_snap_alloc(ASMState *as)
|
||||
if (!irref_isk(ref)) {
|
||||
asm_snap_alloc1(as, ref);
|
||||
if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) {
|
||||
lua_assert(irt_type(IR(ref+1)->t) == IRT_SOFTFP);
|
||||
lj_assertA(irt_type(IR(ref+1)->t) == IRT_SOFTFP,
|
||||
"snap %d[%d] points to bad SOFTFP IR %04d",
|
||||
as->snapno, n, ref - REF_BIAS);
|
||||
asm_snap_alloc1(as, ref+1);
|
||||
}
|
||||
}
|
||||
@@ -1002,19 +1024,20 @@ static int32_t asm_stack_adjust(ASMState *as)
|
||||
}
|
||||
|
||||
/* Must match with hash*() in lj_tab.c. */
|
||||
static uint32_t ir_khash(IRIns *ir)
|
||||
static uint32_t ir_khash(ASMState *as, IRIns *ir)
|
||||
{
|
||||
uint32_t lo, hi;
|
||||
UNUSED(as);
|
||||
if (irt_isstr(ir->t)) {
|
||||
return ir_kstr(ir)->hash;
|
||||
} else if (irt_isnum(ir->t)) {
|
||||
lo = ir_knum(ir)->u32.lo;
|
||||
hi = ir_knum(ir)->u32.hi << 1;
|
||||
} else if (irt_ispri(ir->t)) {
|
||||
lua_assert(!irt_isnil(ir->t));
|
||||
lj_assertA(!irt_isnil(ir->t), "hash of nil key");
|
||||
return irt_type(ir->t)-IRT_FALSE;
|
||||
} else {
|
||||
lua_assert(irt_isgcv(ir->t));
|
||||
lj_assertA(irt_isgcv(ir->t), "hash of bad IR type %d", irt_type(ir->t));
|
||||
lo = u32ptr(ir_kgc(ir));
|
||||
#if LJ_GC64
|
||||
hi = (uint32_t)(u64ptr(ir_kgc(ir)) >> 32) | (irt_toitype(ir->t) << 15);
|
||||
@@ -1122,7 +1145,8 @@ static void asm_bufput(ASMState *as, IRIns *ir)
|
||||
args[0] = ir->op1; /* SBuf * */
|
||||
args[1] = ir->op2; /* GCstr * */
|
||||
irs = IR(ir->op2);
|
||||
lua_assert(irt_isstr(irs->t));
|
||||
lj_assertA(irt_isstr(irs->t),
|
||||
"BUFPUT of non-string IR %04d", ir->op2 - REF_BIAS);
|
||||
if (irs->o == IR_KGC) {
|
||||
GCstr *s = ir_kstr(irs);
|
||||
if (s->len == 1) { /* Optimize put of single-char string constant. */
|
||||
@@ -1136,7 +1160,8 @@ static void asm_bufput(ASMState *as, IRIns *ir)
|
||||
args[1] = ASMREF_TMP1; /* TValue * */
|
||||
ci = &lj_ir_callinfo[IRCALL_lj_strfmt_putnum];
|
||||
} else {
|
||||
lua_assert(irt_isinteger(IR(irs->op1)->t));
|
||||
lj_assertA(irt_isinteger(IR(irs->op1)->t),
|
||||
"TOSTR of non-numeric IR %04d", irs->op1);
|
||||
args[1] = irs->op1; /* int */
|
||||
if (irs->op2 == IRTOSTR_INT)
|
||||
ci = &lj_ir_callinfo[IRCALL_lj_strfmt_putint];
|
||||
@@ -1201,7 +1226,8 @@ static void asm_conv64(ASMState *as, IRIns *ir)
|
||||
IRType dt = (((ir-1)->op2 & IRCONV_DSTMASK) >> IRCONV_DSH);
|
||||
IRCallID id;
|
||||
IRRef args[2];
|
||||
lua_assert((ir-1)->o == IR_CONV && ir->o == IR_HIOP);
|
||||
lj_assertA((ir-1)->o == IR_CONV && ir->o == IR_HIOP,
|
||||
"not a CONV/HIOP pair at IR %04d", (int)(ir - as->ir) - REF_BIAS);
|
||||
args[LJ_BE] = (ir-1)->op1;
|
||||
args[LJ_LE] = ir->op1;
|
||||
if (st == IRT_NUM || st == IRT_FLOAT) {
|
||||
@@ -1256,15 +1282,16 @@ static void asm_collectargs(ASMState *as, IRIns *ir,
|
||||
const CCallInfo *ci, IRRef *args)
|
||||
{
|
||||
uint32_t n = CCI_XNARGS(ci);
|
||||
lua_assert(n <= CCI_NARGS_MAX*2); /* Account for split args. */
|
||||
/* Account for split args. */
|
||||
lj_assertA(n <= CCI_NARGS_MAX*2, "too many args %d to collect", n);
|
||||
if ((ci->flags & CCI_L)) { *args++ = ASMREF_L; n--; }
|
||||
while (n-- > 1) {
|
||||
ir = IR(ir->op1);
|
||||
lua_assert(ir->o == IR_CARG);
|
||||
lj_assertA(ir->o == IR_CARG, "malformed CALL arg tree");
|
||||
args[n] = ir->op2 == REF_NIL ? 0 : ir->op2;
|
||||
}
|
||||
args[0] = ir->op1 == REF_NIL ? 0 : ir->op1;
|
||||
lua_assert(IR(ir->op1)->o != IR_CARG);
|
||||
lj_assertA(IR(ir->op1)->o != IR_CARG, "malformed CALL arg tree");
|
||||
}
|
||||
|
||||
/* Reconstruct CCallInfo flags for CALLX*. */
|
||||
@@ -1648,7 +1675,10 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
||||
switch ((IROp)ir->o) {
|
||||
/* Miscellaneous ops. */
|
||||
case IR_LOOP: asm_loop(as); break;
|
||||
case IR_NOP: case IR_XBAR: lua_assert(!ra_used(ir)); break;
|
||||
case IR_NOP: case IR_XBAR:
|
||||
lj_assertA(!ra_used(ir),
|
||||
"IR %04d not unused", (int)(ir - as->ir) - REF_BIAS);
|
||||
break;
|
||||
case IR_USE:
|
||||
ra_alloc1(as, ir->op1, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); break;
|
||||
case IR_PHI: asm_phi(as, ir); break;
|
||||
@@ -1687,7 +1717,9 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
||||
#if LJ_SOFTFP32
|
||||
case IR_DIV: case IR_POW: case IR_ABS:
|
||||
case IR_LDEXP: case IR_FPMATH: case IR_TOBIT:
|
||||
lua_assert(0); /* Unused for LJ_SOFTFP32. */
|
||||
/* Unused for LJ_SOFTFP32. */
|
||||
lj_assertA(0, "IR %04d with unused op %d",
|
||||
(int)(ir - as->ir) - REF_BIAS, ir->o);
|
||||
break;
|
||||
#else
|
||||
case IR_DIV: asm_div(as, ir); break;
|
||||
@@ -1736,7 +1768,8 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
||||
#if LJ_HASFFI
|
||||
asm_cnew(as, ir);
|
||||
#else
|
||||
lua_assert(0);
|
||||
lj_assertA(0, "IR %04d with unused op %d",
|
||||
(int)(ir - as->ir) - REF_BIAS, ir->o);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -1814,8 +1847,10 @@ static void asm_head_side(ASMState *as)
|
||||
for (i = as->stopins; i > REF_BASE; i--) {
|
||||
IRIns *ir = IR(i);
|
||||
RegSP rs;
|
||||
lua_assert((ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_PARENT)) ||
|
||||
(LJ_SOFTFP && ir->o == IR_HIOP) || ir->o == IR_PVAL);
|
||||
lj_assertA((ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_PARENT)) ||
|
||||
(LJ_SOFTFP && ir->o == IR_HIOP) || ir->o == IR_PVAL,
|
||||
"IR %04d has bad parent op %d",
|
||||
(int)(ir - as->ir) - REF_BIAS, ir->o);
|
||||
rs = as->parentmap[i - REF_FIRST];
|
||||
if (ra_hasreg(ir->r)) {
|
||||
rset_clear(allow, ir->r);
|
||||
@@ -2074,7 +2109,7 @@ static void asm_setup_regsp(ASMState *as)
|
||||
ir = IR(REF_FIRST);
|
||||
if (as->parent) {
|
||||
uint16_t *p;
|
||||
lastir = lj_snap_regspmap(as->parent, as->J->exitno, ir);
|
||||
lastir = lj_snap_regspmap(as->J, as->parent, as->J->exitno, ir);
|
||||
if (lastir - ir > LJ_MAX_JSLOTS)
|
||||
lj_trace_err(as->J, LJ_TRERR_NYICOAL);
|
||||
as->stopins = (IRRef)((lastir-1) - as->ir);
|
||||
@@ -2378,7 +2413,10 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
||||
/* Assemble a trace in linear backwards order. */
|
||||
for (as->curins--; as->curins > as->stopins; as->curins--) {
|
||||
IRIns *ir = IR(as->curins);
|
||||
lua_assert(!(LJ_32 && irt_isint64(ir->t))); /* Handled by SPLIT. */
|
||||
/* 64 bit types handled by SPLIT for 32 bit archs. */
|
||||
lj_assertA(!(LJ_32 && irt_isint64(ir->t)),
|
||||
"IR %04d has unsplit 64 bit type",
|
||||
(int)(ir - as->ir) - REF_BIAS);
|
||||
if (!ra_used(ir) && !ir_sideeff(ir) && (as->flags & JIT_F_OPT_DCE))
|
||||
continue; /* Dead-code elimination can be soooo easy. */
|
||||
if (irt_isguard(ir->t))
|
||||
@@ -2408,7 +2446,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
||||
asm_phi_fixup(as);
|
||||
|
||||
if (J->curfinal->nins >= T->nins) { /* IR didn't grow? */
|
||||
lua_assert(J->curfinal->nk == T->nk);
|
||||
lj_assertA(J->curfinal->nk == T->nk, "unexpected IR constant growth");
|
||||
memcpy(J->curfinal->ir + as->orignins, T->ir + as->orignins,
|
||||
(T->nins - as->orignins) * sizeof(IRIns)); /* Copy RENAMEs. */
|
||||
T->nins = J->curfinal->nins;
|
||||
|
||||
Reference in New Issue
Block a user