Skip to content

Commit

Permalink
lj_crecord.c: JIT pointer difference for all element sizes
Browse files Browse the repository at this point in the history
Support JIT for taking the difference between two pointers whose
element sizes are not a power of 2. This was previously an NYI but not
generates code using a division to convert a pointer to an element
number.

The case where the element size is a power of 2 is handled the same
way as before i.e. using a bit-shift instead of a division.
  • Loading branch information
lukego committed Aug 13, 2017
1 parent 5708b06 commit cf655d9
Showing 1 changed file with 11 additions and 6 deletions.
17 changes: 11 additions & 6 deletions src/lj_crecord.c
Original file line number Diff line number Diff line change
Expand Up @@ -1244,12 +1244,17 @@ static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm)
if (mm == MM_sub) { /* Pointer difference. */
TRef tr;
CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info));
if (sz == 0 || (sz & (sz-1)) != 0)
return 0; /* NYI: integer division. */
tr = emitir(IRT(IR_SUB, IRT_INTP), sp[0], sp[1]);
tr = emitir(IRT(IR_BSAR, IRT_INTP), tr, lj_ir_kint(J, lj_fls(sz)));
tr = emitconv(tr, IRT_NUM, IRT_INTP, 0);
return tr;
if (sz == 0) {
return 0;
}
tr = emitir(IRT(IR_SUB, IRT_INTP), sp[0], sp[1]);
if ((sz & (sz-1)) == 0) { /* special case: divide using bit-shift */
tr = emitir(IRT(IR_BSAR, IRT_INTP), tr, lj_ir_kint(J, lj_fls(sz)));
} else { /* general case: divide using division */
tr = emitir(IRT(IR_DIV, IRT_INTP), tr, lj_ir_kint(J, sz));
}
tr = emitconv(tr, IRT_NUM, IRT_INTP, 0);
return tr;
} else { /* Pointer comparison (unsigned). */
/* Assume true comparison. Fixup and emit pending guard later. */
IROp op = mm == MM_eq ? IR_EQ : mm == MM_lt ? IR_ULT : IR_ULE;
Expand Down

0 comments on commit cf655d9

Please sign in to comment.