Skip to content

Commit

Permalink
String buffers, part 3a: Add IR_TMPREF for passing TValues to helpers.
Browse files Browse the repository at this point in the history
Sponsored by fmad.io.
  • Loading branch information
Mike Pall committed Jul 19, 2021
1 parent 71db0cf commit 6df650f
Show file tree
Hide file tree
Showing 12 changed files with 249 additions and 125 deletions.
1 change: 1 addition & 0 deletions src/jit/dump.lua
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ local litname = {
["FLOAD "] = vmdef.irfield,
["FREF "] = vmdef.irfield,
["FPMATH"] = vmdef.irfpm,
["TMPREF"] = { [0] = "", "IN", "OUT", "INOUT", "", "", "OUT2", "INOUT2" },
["BUFHDR"] = { [0] = "RESET", "APPEND" },
["TOSTR "] = { [0] = "INT", "NUM", "CHAR" },
}
Expand Down
19 changes: 15 additions & 4 deletions src/lj_asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,7 @@ static void asm_gcstep(ASMState *as, IRIns *ir)

/* -- Buffer operations --------------------------------------------------- */

static void asm_tvptr(ASMState *as, Reg dest, IRRef ref);
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode);

static void asm_bufhdr(ASMState *as, IRIns *ir)
{
Expand Down Expand Up @@ -1218,7 +1218,7 @@ static void asm_bufput(ASMState *as, IRIns *ir)
if (args[1] == ASMREF_TMP1) {
Reg tmp = ra_releasetmp(as, ASMREF_TMP1);
if (kchar == -129)
asm_tvptr(as, tmp, irs->op1);
asm_tvptr(as, tmp, irs->op1, IRTMPREF_IN1);
else
ra_allockreg(as, kchar, tmp);
}
Expand Down Expand Up @@ -1256,7 +1256,7 @@ static void asm_tostr(ASMState *as, IRIns *ir)
asm_setupresult(as, ir, ci); /* GCstr * */
asm_gencall(as, ci, args);
if (ir->op2 == IRTOSTR_NUM)
asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1);
asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1, IRTMPREF_IN1);
}

#if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86
Expand Down Expand Up @@ -1303,7 +1303,13 @@ static void asm_newref(ASMState *as, IRIns *ir)
args[2] = ASMREF_TMP1; /* cTValue *key */
asm_setupresult(as, ir, ci); /* TValue * */
asm_gencall(as, ci, args);
asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2);
asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2, IRTMPREF_IN1);
}

static void asm_tmpref(ASMState *as, IRIns *ir)
{
Reg r = ra_dest(as, ir, RSET_GPR);
asm_tvptr(as, r, ir->op1, ir->op2);
}

static void asm_lref(ASMState *as, IRIns *ir)
Expand Down Expand Up @@ -1785,6 +1791,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
case IR_NEWREF: asm_newref(as, ir); break;
case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break;
case IR_FREF: asm_fref(as, ir); break;
case IR_TMPREF: asm_tmpref(as, ir); break;
case IR_STRREF: asm_strref(as, ir); break;
case IR_LREF: asm_lref(as, ir); break;

Expand Down Expand Up @@ -2192,6 +2199,10 @@ static void asm_setup_regsp(ASMState *as)
ir->prev = (uint16_t)REGSP_HINT((rload & 15));
rload = lj_ror(rload, 4);
continue;
case IR_TMPREF:
if ((ir->op2 & IRTMPREF_OUT2) && as->evenspill < 4)
as->evenspill = 4; /* TMPREF OUT2 needs two TValues on the stack. */
break;
#endif
case IR_CALLXS: {
CCallInfo ci;
Expand Down
69 changes: 46 additions & 23 deletions src/lj_asm_arm.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow,
*ofsp = (ofs & 255); /* Mask out less bits to allow LDRD. */
return ra_allock(as, (ofs & ~255), allow);
}
} else if (ir->o == IR_TMPREF) {
*ofsp = 0;
return RID_SP;
}
}
*ofsp = 0;
Expand Down Expand Up @@ -666,35 +669,55 @@ static void asm_strto(ASMState *as, IRIns *ir)
/* -- Memory references --------------------------------------------------- */

/* Get pointer to TValue. */
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
{
IRIns *ir = IR(ref);
if (irt_isnum(ir->t)) {
if (irref_isk(ref)) {
/* Use the number constant itself as a TValue. */
ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
} else {
if ((mode & IRTMPREF_IN1)) {
IRIns *ir = IR(ref);
if (irt_isnum(ir->t)) {
if ((mode & IRTMPREF_OUT1)) {
#if LJ_SOFTFP
lj_assertA(irref_isk(ref), "unsplit FP op");
emit_dm(as, ARMI_MOV, dest, RID_SP);
emit_lso(as, ARMI_STR,
ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR),
RID_SP, 0);
emit_lso(as, ARMI_STR,
ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR),
RID_SP, 4);
#else
Reg src = ra_alloc1(as, ref, RSET_FPR);
emit_dm(as, ARMI_MOV, dest, RID_SP);
emit_vlso(as, ARMI_VSTR_D, src, RID_SP, 0);
#endif
} else if (irref_isk(ref)) {
/* Use the number constant itself as a TValue. */
ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
} else {
#if LJ_SOFTFP
lj_assertA(0, "unsplit FP op");
lj_assertA(0, "unsplit FP op");
#else
/* Otherwise force a spill and use the spill slot. */
emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR);
/* Otherwise force a spill and use the spill slot. */
emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR);
#endif
}
} else {
/* Otherwise use [sp] and [sp+4] to hold the TValue.
** This assumes the following call has max. 4 args.
*/
Reg type;
emit_dm(as, ARMI_MOV, dest, RID_SP);
if (!irt_ispri(ir->t)) {
Reg src = ra_alloc1(as, ref, RSET_GPR);
emit_lso(as, ARMI_STR, src, RID_SP, 0);
}
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t))
type = ra_alloc1(as, ref+1, RSET_GPR);
else
type = ra_allock(as, irt_toitype(ir->t), RSET_GPR);
emit_lso(as, ARMI_STR, type, RID_SP, 4);
}
} else {
/* Otherwise use [sp] and [sp+4] to hold the TValue. */
RegSet allow = rset_exclude(RSET_GPR, dest);
Reg type;
emit_dm(as, ARMI_MOV, dest, RID_SP);
if (!irt_ispri(ir->t)) {
Reg src = ra_alloc1(as, ref, allow);
emit_lso(as, ARMI_STR, src, RID_SP, 0);
}
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP)
type = ra_alloc1(as, ref+1, allow);
else
type = ra_allock(as, irt_toitype(ir->t), allow);
emit_lso(as, ARMI_STR, type, RID_SP, 4);
}
}

Expand Down Expand Up @@ -1909,7 +1932,7 @@ static void asm_hiop(ASMState *as, IRIns *ir)
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
break;
#if LJ_SOFTFP
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR:
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF:
#endif
case IR_CNEWI:
/* Nothing to do here. Handled by lo op itself. */
Expand Down
28 changes: 16 additions & 12 deletions src/lj_asm_arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow,
return RID_GL;
}
}
} else if (ir->o == IR_TMPREF) {
*ofsp = (int32_t)glofs(as, &J2G(as->J)->tmptv);
return RID_GL;
}
}
*ofsp = 0;
Expand Down Expand Up @@ -675,22 +678,23 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref)
}

/* Get pointer to TValue. */
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
{
IRIns *ir = IR(ref);
if (irt_isnum(ir->t)) {
if (irref_isk(ref)) {
/* Use the number constant itself as a TValue. */
ra_allockreg(as, i64ptr(ir_knum(ir)), dest);
if ((mode & IRTMPREF_IN1)) {
IRIns *ir = IR(ref);
if (irt_isnum(ir->t)) {
if (irref_isk(ref) && !(mode & IRTMPREF_OUT1)) {
/* Use the number constant itself as a TValue. */
ra_allockreg(as, i64ptr(ir_knum(ir)), dest);
return;
}
emit_lso(as, A64I_STRd, (ra_alloc1(as, ref, RSET_FPR) & 31), dest, 0);
} else {
/* Otherwise force a spill and use the spill slot. */
emit_opk(as, A64I_ADDx, dest, RID_SP, ra_spill(as, ir), RSET_GPR);
asm_tvstore64(as, dest, 0, ref);
}
} else {
/* Otherwise use g->tmptv to hold the TValue. */
asm_tvstore64(as, dest, 0, ref);
emit_dn(as, A64I_ADDx^emit_isk12(glofs(as, &J2G(as->J)->tmptv)), dest, RID_GL);
}
/* g->tmptv holds the TValue(s). */
emit_dn(as, A64I_ADDx^emit_isk12(glofs(as, &J2G(as->J)->tmptv)), dest, RID_GL);
}

static void asm_aref(ASMState *as, IRIns *ir)
Expand Down
82 changes: 57 additions & 25 deletions src/lj_asm_mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow)
return ra_allock(as, ofs-(int16_t)ofs, allow);
}
}
} else if (ir->o == IR_TMPREF) {
*ofsp = (int32_t)(offsetof(global_State, tmptv)-32768);
return RID_JGL;
}
}
*ofsp = 0;
Expand Down Expand Up @@ -839,34 +842,63 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref)
#endif

/* Get pointer to TValue. */
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
{
IRIns *ir = IR(ref);
if (irt_isnum(ir->t)) {
if (irref_isk(ref)) /* Use the number constant itself as a TValue. */
ra_allockreg(as, igcptr(ir_knum(ir)), dest);
else /* Otherwise force a spill and use the spill slot. */
emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir));
} else {
/* Otherwise use g->tmptv to hold the TValue. */
int32_t tmpofs = (int32_t)(offsetof(global_State, tmptv)-32768);
if ((mode & IRTMPREF_IN1)) {
IRIns *ir = IR(ref);
if (irt_isnum(ir->t)) {
if ((mode & IRTMPREF_OUT1)) {
#if LJ_SOFTFP
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
#if LJ_64
emit_setgl(as, ra_alloc1(as, ref, RSET_GPR), tmptv.u64);
#else
lj_assertA(irref_isk(ref), "unsplit FP op");
emit_setgl(as,
ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR),
tmptv.u32.lo);
emit_setgl(as,
ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR),
tmptv.u32.hi);
#endif
#else
Reg src = ra_alloc1(as, ref, RSET_FPR);
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
emit_tsi(as, MIPSI_SDC1, (src & 31), RID_JGL, tmpofs);
#endif
} else if (irref_isk(ref)) {
/* Use the number constant itself as a TValue. */
ra_allockreg(as, igcptr(ir_knum(ir)), dest);
} else {
#if LJ_SOFTFP
lj_assertA(0, "unsplit FP op");
#else
/* Otherwise force a spill and use the spill slot. */
emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir));
#endif
}
} else {
/* Otherwise use g->tmptv to hold the TValue. */
#if LJ_32
RegSet allow = rset_exclude(RSET_GPR, dest);
Reg type;
emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, (int32_t)(offsetof(global_State, tmptv)-32768));
if (!irt_ispri(ir->t)) {
Reg src = ra_alloc1(as, ref, allow);
emit_setgl(as, src, tmptv.gcr);
}
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP)
type = ra_alloc1(as, ref+1, allow);
else
type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
emit_setgl(as, type, tmptv.it);
Reg type;
emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, tmpofs);
if (!irt_ispri(ir->t)) {
Reg src = ra_alloc1(as, ref, RSET_GPR);
emit_setgl(as, src, tmptv.gcr);
}
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t))
type = ra_alloc1(as, ref+1, RSET_GPR);
else
type = ra_allock(as, (int32_t)irt_toitype(ir->t), RSET_GPR);
emit_setgl(as, type, tmptv.it);
#else
asm_tvstore64(as, dest, 0, ref);
emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL,
(int32_t)(offsetof(global_State, tmptv)-32768));
asm_tvstore64(as, dest, 0, ref);
emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, tmpofs);
#endif
}
} else {
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
}
}

Expand Down Expand Up @@ -2415,7 +2447,7 @@ static void asm_hiop(ASMState *as, IRIns *ir)
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
break;
#if LJ_SOFTFP
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR:
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF:
#endif
case IR_CNEWI:
/* Nothing to do here. Handled by lo op itself. */
Expand Down
Loading

0 comments on commit 6df650f

Please sign in to comment.