aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jit/dump.lua1
-rw-r--r--src/lj_asm.c19
-rw-r--r--src/lj_asm_arm.h69
-rw-r--r--src/lj_asm_arm64.h28
-rw-r--r--src/lj_asm_mips.h82
-rw-r--r--src/lj_asm_ppc.h71
-rw-r--r--src/lj_asm_x86.h79
-rw-r--r--src/lj_ir.h6
-rw-r--r--src/lj_opt_fold.c1
-rw-r--r--src/lj_opt_split.c2
-rw-r--r--src/lj_record.c15
-rw-r--r--src/lj_record.h1
12 files changed, 249 insertions, 125 deletions
diff --git a/src/jit/dump.lua b/src/jit/dump.lua
index 34ced76d..4806f4c4 100644
--- a/src/jit/dump.lua
+++ b/src/jit/dump.lua
@@ -287,6 +287,7 @@ local litname = {
287 ["FLOAD "] = vmdef.irfield, 287 ["FLOAD "] = vmdef.irfield,
288 ["FREF "] = vmdef.irfield, 288 ["FREF "] = vmdef.irfield,
289 ["FPMATH"] = vmdef.irfpm, 289 ["FPMATH"] = vmdef.irfpm,
290 ["TMPREF"] = { [0] = "", "IN", "OUT", "INOUT", "", "", "OUT2", "INOUT2" },
290 ["BUFHDR"] = { [0] = "RESET", "APPEND" }, 291 ["BUFHDR"] = { [0] = "RESET", "APPEND" },
291 ["TOSTR "] = { [0] = "INT", "NUM", "CHAR" }, 292 ["TOSTR "] = { [0] = "INT", "NUM", "CHAR" },
292} 293}
diff --git a/src/lj_asm.c b/src/lj_asm.c
index b613e6d3..ebcff43c 100644
--- a/src/lj_asm.c
+++ b/src/lj_asm.c
@@ -1144,7 +1144,7 @@ static void asm_gcstep(ASMState *as, IRIns *ir)
1144 1144
1145/* -- Buffer operations --------------------------------------------------- */ 1145/* -- Buffer operations --------------------------------------------------- */
1146 1146
1147static void asm_tvptr(ASMState *as, Reg dest, IRRef ref); 1147static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode);
1148 1148
1149static void asm_bufhdr(ASMState *as, IRIns *ir) 1149static void asm_bufhdr(ASMState *as, IRIns *ir)
1150{ 1150{
@@ -1218,7 +1218,7 @@ static void asm_bufput(ASMState *as, IRIns *ir)
1218 if (args[1] == ASMREF_TMP1) { 1218 if (args[1] == ASMREF_TMP1) {
1219 Reg tmp = ra_releasetmp(as, ASMREF_TMP1); 1219 Reg tmp = ra_releasetmp(as, ASMREF_TMP1);
1220 if (kchar == -129) 1220 if (kchar == -129)
1221 asm_tvptr(as, tmp, irs->op1); 1221 asm_tvptr(as, tmp, irs->op1, IRTMPREF_IN1);
1222 else 1222 else
1223 ra_allockreg(as, kchar, tmp); 1223 ra_allockreg(as, kchar, tmp);
1224 } 1224 }
@@ -1256,7 +1256,7 @@ static void asm_tostr(ASMState *as, IRIns *ir)
1256 asm_setupresult(as, ir, ci); /* GCstr * */ 1256 asm_setupresult(as, ir, ci); /* GCstr * */
1257 asm_gencall(as, ci, args); 1257 asm_gencall(as, ci, args);
1258 if (ir->op2 == IRTOSTR_NUM) 1258 if (ir->op2 == IRTOSTR_NUM)
1259 asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1); 1259 asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1, IRTMPREF_IN1);
1260} 1260}
1261 1261
1262#if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86 1262#if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86
@@ -1303,7 +1303,13 @@ static void asm_newref(ASMState *as, IRIns *ir)
1303 args[2] = ASMREF_TMP1; /* cTValue *key */ 1303 args[2] = ASMREF_TMP1; /* cTValue *key */
1304 asm_setupresult(as, ir, ci); /* TValue * */ 1304 asm_setupresult(as, ir, ci); /* TValue * */
1305 asm_gencall(as, ci, args); 1305 asm_gencall(as, ci, args);
1306 asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2); 1306 asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2, IRTMPREF_IN1);
1307}
1308
1309static void asm_tmpref(ASMState *as, IRIns *ir)
1310{
1311 Reg r = ra_dest(as, ir, RSET_GPR);
1312 asm_tvptr(as, r, ir->op1, ir->op2);
1307} 1313}
1308 1314
1309static void asm_lref(ASMState *as, IRIns *ir) 1315static void asm_lref(ASMState *as, IRIns *ir)
@@ -1785,6 +1791,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
1785 case IR_NEWREF: asm_newref(as, ir); break; 1791 case IR_NEWREF: asm_newref(as, ir); break;
1786 case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break; 1792 case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break;
1787 case IR_FREF: asm_fref(as, ir); break; 1793 case IR_FREF: asm_fref(as, ir); break;
1794 case IR_TMPREF: asm_tmpref(as, ir); break;
1788 case IR_STRREF: asm_strref(as, ir); break; 1795 case IR_STRREF: asm_strref(as, ir); break;
1789 case IR_LREF: asm_lref(as, ir); break; 1796 case IR_LREF: asm_lref(as, ir); break;
1790 1797
@@ -2192,6 +2199,10 @@ static void asm_setup_regsp(ASMState *as)
2192 ir->prev = (uint16_t)REGSP_HINT((rload & 15)); 2199 ir->prev = (uint16_t)REGSP_HINT((rload & 15));
2193 rload = lj_ror(rload, 4); 2200 rload = lj_ror(rload, 4);
2194 continue; 2201 continue;
2202 case IR_TMPREF:
2203 if ((ir->op2 & IRTMPREF_OUT2) && as->evenspill < 4)
2204 as->evenspill = 4; /* TMPREF OUT2 needs two TValues on the stack. */
2205 break;
2195#endif 2206#endif
2196 case IR_CALLXS: { 2207 case IR_CALLXS: {
2197 CCallInfo ci; 2208 CCallInfo ci;
diff --git a/src/lj_asm_arm.h b/src/lj_asm_arm.h
index c93c99c9..208c3203 100644
--- a/src/lj_asm_arm.h
+++ b/src/lj_asm_arm.h
@@ -185,6 +185,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow,
185 *ofsp = (ofs & 255); /* Mask out less bits to allow LDRD. */ 185 *ofsp = (ofs & 255); /* Mask out less bits to allow LDRD. */
186 return ra_allock(as, (ofs & ~255), allow); 186 return ra_allock(as, (ofs & ~255), allow);
187 } 187 }
188 } else if (ir->o == IR_TMPREF) {
189 *ofsp = 0;
190 return RID_SP;
188 } 191 }
189 } 192 }
190 *ofsp = 0; 193 *ofsp = 0;
@@ -666,35 +669,55 @@ static void asm_strto(ASMState *as, IRIns *ir)
666/* -- Memory references --------------------------------------------------- */ 669/* -- Memory references --------------------------------------------------- */
667 670
668/* Get pointer to TValue. */ 671/* Get pointer to TValue. */
669static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) 672static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
670{ 673{
671 IRIns *ir = IR(ref); 674 if ((mode & IRTMPREF_IN1)) {
672 if (irt_isnum(ir->t)) { 675 IRIns *ir = IR(ref);
673 if (irref_isk(ref)) { 676 if (irt_isnum(ir->t)) {
674 /* Use the number constant itself as a TValue. */ 677 if ((mode & IRTMPREF_OUT1)) {
675 ra_allockreg(as, i32ptr(ir_knum(ir)), dest); 678#if LJ_SOFTFP
676 } else { 679 lj_assertA(irref_isk(ref), "unsplit FP op");
680 emit_dm(as, ARMI_MOV, dest, RID_SP);
681 emit_lso(as, ARMI_STR,
682 ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR),
683 RID_SP, 0);
684 emit_lso(as, ARMI_STR,
685 ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR),
686 RID_SP, 4);
687#else
688 Reg src = ra_alloc1(as, ref, RSET_FPR);
689 emit_dm(as, ARMI_MOV, dest, RID_SP);
690 emit_vlso(as, ARMI_VSTR_D, src, RID_SP, 0);
691#endif
692 } else if (irref_isk(ref)) {
693 /* Use the number constant itself as a TValue. */
694 ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
695 } else {
677#if LJ_SOFTFP 696#if LJ_SOFTFP
678 lj_assertA(0, "unsplit FP op"); 697 lj_assertA(0, "unsplit FP op");
679#else 698#else
680 /* Otherwise force a spill and use the spill slot. */ 699 /* Otherwise force a spill and use the spill slot. */
681 emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR); 700 emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR);
682#endif 701#endif
702 }
703 } else {
704 /* Otherwise use [sp] and [sp+4] to hold the TValue.
705 ** This assumes the following call has max. 4 args.
706 */
707 Reg type;
708 emit_dm(as, ARMI_MOV, dest, RID_SP);
709 if (!irt_ispri(ir->t)) {
710 Reg src = ra_alloc1(as, ref, RSET_GPR);
711 emit_lso(as, ARMI_STR, src, RID_SP, 0);
712 }
713 if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t))
714 type = ra_alloc1(as, ref+1, RSET_GPR);
715 else
716 type = ra_allock(as, irt_toitype(ir->t), RSET_GPR);
717 emit_lso(as, ARMI_STR, type, RID_SP, 4);
683 } 718 }
684 } else { 719 } else {
685 /* Otherwise use [sp] and [sp+4] to hold the TValue. */
686 RegSet allow = rset_exclude(RSET_GPR, dest);
687 Reg type;
688 emit_dm(as, ARMI_MOV, dest, RID_SP); 720 emit_dm(as, ARMI_MOV, dest, RID_SP);
689 if (!irt_ispri(ir->t)) {
690 Reg src = ra_alloc1(as, ref, allow);
691 emit_lso(as, ARMI_STR, src, RID_SP, 0);
692 }
693 if (LJ_SOFTFP && (ir+1)->o == IR_HIOP)
694 type = ra_alloc1(as, ref+1, allow);
695 else
696 type = ra_allock(as, irt_toitype(ir->t), allow);
697 emit_lso(as, ARMI_STR, type, RID_SP, 4);
698 } 721 }
699} 722}
700 723
@@ -1909,7 +1932,7 @@ static void asm_hiop(ASMState *as, IRIns *ir)
1909 ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ 1932 ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
1910 break; 1933 break;
1911#if LJ_SOFTFP 1934#if LJ_SOFTFP
1912 case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: 1935 case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF:
1913#endif 1936#endif
1914 case IR_CNEWI: 1937 case IR_CNEWI:
1915 /* Nothing to do here. Handled by lo op itself. */ 1938 /* Nothing to do here. Handled by lo op itself. */
diff --git a/src/lj_asm_arm64.h b/src/lj_asm_arm64.h
index c9ba7b7b..5bd4e0d5 100644
--- a/src/lj_asm_arm64.h
+++ b/src/lj_asm_arm64.h
@@ -198,6 +198,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow,
198 return RID_GL; 198 return RID_GL;
199 } 199 }
200 } 200 }
201 } else if (ir->o == IR_TMPREF) {
202 *ofsp = (int32_t)glofs(as, &J2G(as->J)->tmptv);
203 return RID_GL;
201 } 204 }
202 } 205 }
203 *ofsp = 0; 206 *ofsp = 0;
@@ -675,22 +678,23 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref)
675} 678}
676 679
677/* Get pointer to TValue. */ 680/* Get pointer to TValue. */
678static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) 681static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
679{ 682{
680 IRIns *ir = IR(ref); 683 if ((mode & IRTMPREF_IN1)) {
681 if (irt_isnum(ir->t)) { 684 IRIns *ir = IR(ref);
682 if (irref_isk(ref)) { 685 if (irt_isnum(ir->t)) {
683 /* Use the number constant itself as a TValue. */ 686 if (irref_isk(ref) && !(mode & IRTMPREF_OUT1)) {
684 ra_allockreg(as, i64ptr(ir_knum(ir)), dest); 687 /* Use the number constant itself as a TValue. */
688 ra_allockreg(as, i64ptr(ir_knum(ir)), dest);
689 return;
690 }
691 emit_lso(as, A64I_STRd, (ra_alloc1(as, ref, RSET_FPR) & 31), dest, 0);
685 } else { 692 } else {
686 /* Otherwise force a spill and use the spill slot. */ 693 asm_tvstore64(as, dest, 0, ref);
687 emit_opk(as, A64I_ADDx, dest, RID_SP, ra_spill(as, ir), RSET_GPR);
688 } 694 }
689 } else {
690 /* Otherwise use g->tmptv to hold the TValue. */
691 asm_tvstore64(as, dest, 0, ref);
692 emit_dn(as, A64I_ADDx^emit_isk12(glofs(as, &J2G(as->J)->tmptv)), dest, RID_GL);
693 } 695 }
696 /* g->tmptv holds the TValue(s). */
697 emit_dn(as, A64I_ADDx^emit_isk12(glofs(as, &J2G(as->J)->tmptv)), dest, RID_GL);
694} 698}
695 699
696static void asm_aref(ASMState *as, IRIns *ir) 700static void asm_aref(ASMState *as, IRIns *ir)
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h
index f775d08b..058df8be 100644
--- a/src/lj_asm_mips.h
+++ b/src/lj_asm_mips.h
@@ -193,6 +193,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow)
193 return ra_allock(as, ofs-(int16_t)ofs, allow); 193 return ra_allock(as, ofs-(int16_t)ofs, allow);
194 } 194 }
195 } 195 }
196 } else if (ir->o == IR_TMPREF) {
197 *ofsp = (int32_t)(offsetof(global_State, tmptv)-32768);
198 return RID_JGL;
196 } 199 }
197 } 200 }
198 *ofsp = 0; 201 *ofsp = 0;
@@ -839,34 +842,63 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref)
839#endif 842#endif
840 843
841/* Get pointer to TValue. */ 844/* Get pointer to TValue. */
842static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) 845static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
843{ 846{
844 IRIns *ir = IR(ref); 847 int32_t tmpofs = (int32_t)(offsetof(global_State, tmptv)-32768);
845 if (irt_isnum(ir->t)) { 848 if ((mode & IRTMPREF_IN1)) {
846 if (irref_isk(ref)) /* Use the number constant itself as a TValue. */ 849 IRIns *ir = IR(ref);
847 ra_allockreg(as, igcptr(ir_knum(ir)), dest); 850 if (irt_isnum(ir->t)) {
848 else /* Otherwise force a spill and use the spill slot. */ 851 if ((mode & IRTMPREF_OUT1)) {
849 emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir)); 852#if LJ_SOFTFP
850 } else { 853 emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
851 /* Otherwise use g->tmptv to hold the TValue. */ 854#if LJ_64
855 emit_setgl(as, ra_alloc1(as, ref, RSET_GPR), tmptv.u64);
856#else
857 lj_assertA(irref_isk(ref), "unsplit FP op");
858 emit_setgl(as,
859 ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR),
860 tmptv.u32.lo);
861 emit_setgl(as,
862 ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR),
863 tmptv.u32.hi);
864#endif
865#else
866 Reg src = ra_alloc1(as, ref, RSET_FPR);
867 emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
868 emit_tsi(as, MIPSI_SDC1, (src & 31), RID_JGL, tmpofs);
869#endif
870 } else if (irref_isk(ref)) {
871 /* Use the number constant itself as a TValue. */
872 ra_allockreg(as, igcptr(ir_knum(ir)), dest);
873 } else {
874#if LJ_SOFTFP
875 lj_assertA(0, "unsplit FP op");
876#else
877 /* Otherwise force a spill and use the spill slot. */
878 emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir));
879#endif
880 }
881 } else {
882 /* Otherwise use g->tmptv to hold the TValue. */
852#if LJ_32 883#if LJ_32
853 RegSet allow = rset_exclude(RSET_GPR, dest); 884 Reg type;
854 Reg type; 885 emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, tmpofs);
855 emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, (int32_t)(offsetof(global_State, tmptv)-32768)); 886 if (!irt_ispri(ir->t)) {
856 if (!irt_ispri(ir->t)) { 887 Reg src = ra_alloc1(as, ref, RSET_GPR);
857 Reg src = ra_alloc1(as, ref, allow); 888 emit_setgl(as, src, tmptv.gcr);
858 emit_setgl(as, src, tmptv.gcr); 889 }
859 } 890 if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t))
860 if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) 891 type = ra_alloc1(as, ref+1, RSET_GPR);
861 type = ra_alloc1(as, ref+1, allow); 892 else
862 else 893 type = ra_allock(as, (int32_t)irt_toitype(ir->t), RSET_GPR);
863 type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); 894 emit_setgl(as, type, tmptv.it);
864 emit_setgl(as, type, tmptv.it);
865#else 895#else
866 asm_tvstore64(as, dest, 0, ref); 896 asm_tvstore64(as, dest, 0, ref);
867 emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, 897 emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, tmpofs);
868 (int32_t)(offsetof(global_State, tmptv)-32768));
869#endif 898#endif
899 }
900 } else {
901 emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
870 } 902 }
871} 903}
872 904
@@ -2415,7 +2447,7 @@ static void asm_hiop(ASMState *as, IRIns *ir)
2415 ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ 2447 ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
2416 break; 2448 break;
2417#if LJ_SOFTFP 2449#if LJ_SOFTFP
2418 case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: 2450 case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF:
2419#endif 2451#endif
2420 case IR_CNEWI: 2452 case IR_CNEWI:
2421 /* Nothing to do here. Handled by lo op itself. */ 2453 /* Nothing to do here. Handled by lo op itself. */
diff --git a/src/lj_asm_ppc.h b/src/lj_asm_ppc.h
index 88869d9d..caef8fd7 100644
--- a/src/lj_asm_ppc.h
+++ b/src/lj_asm_ppc.h
@@ -156,6 +156,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow)
156 return ra_allock(as, ofs-(int16_t)ofs, allow); 156 return ra_allock(as, ofs-(int16_t)ofs, allow);
157 } 157 }
158 } 158 }
159 } else if (ir->o == IR_TMPREF) {
160 *ofsp = (int32_t)(offsetof(global_State, tmptv)-32768);
161 return RID_JGL;
159 } 162 }
160 } 163 }
161 *ofsp = 0; 164 *ofsp = 0;
@@ -567,28 +570,54 @@ static void asm_strto(ASMState *as, IRIns *ir)
567/* -- Memory references --------------------------------------------------- */ 570/* -- Memory references --------------------------------------------------- */
568 571
569/* Get pointer to TValue. */ 572/* Get pointer to TValue. */
570static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) 573static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
571{ 574{
572 IRIns *ir = IR(ref); 575 int32_t tmpofs = (int32_t)(offsetof(global_State, tmptv)-32768);
573 if (irt_isnum(ir->t)) { 576 if ((mode & IRTMPREF_IN1)) {
574 if (irref_isk(ref)) /* Use the number constant itself as a TValue. */ 577 IRIns *ir = IR(ref);
575 ra_allockreg(as, i32ptr(ir_knum(ir)), dest); 578 if (irt_isnum(ir->t)) {
576 else /* Otherwise force a spill and use the spill slot. */ 579 if ((mode & IRTMPREF_OUT1)) {
577 emit_tai(as, PPCI_ADDI, dest, RID_SP, ra_spill(as, ir)); 580#if LJ_SOFTFP
578 } else { 581 lj_assertA(irref_isk(ref), "unsplit FP op");
579 /* Otherwise use g->tmptv to hold the TValue. */ 582 emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs);
580 RegSet allow = rset_exclude(RSET_GPR, dest); 583 emit_setgl(as,
581 Reg type; 584 ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR),
582 emit_tai(as, PPCI_ADDI, dest, RID_JGL, (int32_t)offsetof(global_State, tmptv)-32768); 585 tmptv.u32.lo);
583 if (!irt_ispri(ir->t)) { 586 emit_setgl(as,
584 Reg src = ra_alloc1(as, ref, allow); 587 ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR),
585 emit_setgl(as, src, tmptv.gcr); 588 tmptv.u32.hi);
589#else
590 Reg src = ra_alloc1(as, ref, RSET_FPR);
591 emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs);
592 emit_fai(as, PPCI_STFD, src, RID_JGL, tmpofs);
593#endif
594 } else if (irref_isk(ref)) {
595 /* Use the number constant itself as a TValue. */
596 ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
597 } else {
598#if LJ_SOFTFP
599 lj_assertA(0, "unsplit FP op");
600#else
601 /* Otherwise force a spill and use the spill slot. */
602 emit_tai(as, PPCI_ADDI, dest, RID_SP, ra_spill(as, ir));
603#endif
604 }
605 } else {
606 /* Otherwise use g->tmptv to hold the TValue. */
607 Reg type;
608 emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs);
609 if (!irt_ispri(ir->t)) {
610 Reg src = ra_alloc1(as, ref, RSET_GPR);
611 emit_setgl(as, src, tmptv.gcr);
612 }
613 if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t))
614 type = ra_alloc1(as, ref+1, RSET_GPR);
615 else
616 type = ra_allock(as, irt_toitype(ir->t), RSET_GPR);
617 emit_setgl(as, type, tmptv.it);
586 } 618 }
587 if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) 619 } else {
588 type = ra_alloc1(as, ref+1, allow); 620 emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs);
589 else
590 type = ra_allock(as, irt_toitype(ir->t), allow);
591 emit_setgl(as, type, tmptv.it);
592 } 621 }
593} 622}
594 623
@@ -1958,7 +1987,7 @@ static void asm_hiop(ASMState *as, IRIns *ir)
1958 ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ 1987 ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
1959 break; 1988 break;
1960#if LJ_SOFTFP 1989#if LJ_SOFTFP
1961 case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: 1990 case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF:
1962#endif 1991#endif
1963 case IR_CNEWI: 1992 case IR_CNEWI:
1964 /* Nothing to do here. Handled by lo op itself. */ 1993 /* Nothing to do here. Handled by lo op itself. */
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h
index 715e1535..b8abf9d6 100644
--- a/src/lj_asm_x86.h
+++ b/src/lj_asm_x86.h
@@ -216,6 +216,16 @@ static void asm_fuseahuref(ASMState *as, IRRef ref, RegSet allow)
216#endif 216#endif
217 } 217 }
218 break; 218 break;
219 case IR_TMPREF:
220#if LJ_GC64
221 as->mrm.ofs = (int32_t)dispofs(as, &J2G(as->J)->tmptv);
222 as->mrm.base = RID_DISPATCH;
223 as->mrm.idx = RID_NONE;
224#else
225 as->mrm.ofs = igcptr(&J2G(as->J)->tmptv);
226 as->mrm.base = as->mrm.idx = RID_NONE;
227#endif
228 return;
219 default: 229 default:
220 lj_assertA(ir->o == IR_HREF || ir->o == IR_NEWREF || ir->o == IR_UREFO || 230 lj_assertA(ir->o == IR_HREF || ir->o == IR_NEWREF || ir->o == IR_UREFO ||
221 ir->o == IR_KKPTR, 231 ir->o == IR_KKPTR,
@@ -1050,47 +1060,48 @@ static void asm_strto(ASMState *as, IRIns *ir)
1050/* -- Memory references --------------------------------------------------- */ 1060/* -- Memory references --------------------------------------------------- */
1051 1061
1052/* Get pointer to TValue. */ 1062/* Get pointer to TValue. */
1053static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) 1063static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
1054{ 1064{
1055 IRIns *ir = IR(ref); 1065 if ((mode & IRTMPREF_IN1)) {
1056 if (irt_isnum(ir->t)) { 1066 IRIns *ir = IR(ref);
1057 /* For numbers use the constant itself or a spill slot as a TValue. */ 1067 if (irt_isnum(ir->t)) {
1058 if (irref_isk(ref)) 1068 if (irref_isk(ref) && !(mode & IRTMPREF_OUT1)) {
1059 emit_loada(as, dest, ir_knum(ir)); 1069 /* Use the number constant itself as a TValue. */
1060 else 1070 emit_loada(as, dest, ir_knum(ir));
1061 emit_rmro(as, XO_LEA, dest|REX_64, RID_ESP, ra_spill(as, ir)); 1071 return;
1062 } else { 1072 }
1063 /* Otherwise use g->tmptv to hold the TValue. */ 1073 emit_rmro(as, XO_MOVSDto, ra_alloc1(as, ref, RSET_FPR), dest, 0);
1064#if LJ_GC64
1065 if (irref_isk(ref)) {
1066 TValue k;
1067 lj_ir_kvalue(as->J->L, &k, ir);
1068 emit_movmroi(as, dest, 4, k.u32.hi);
1069 emit_movmroi(as, dest, 0, k.u32.lo);
1070 } else { 1074 } else {
1071 /* TODO: 64 bit store + 32 bit load-modify-store is suboptimal. */ 1075#if LJ_GC64
1072 Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest)); 1076 if (irref_isk(ref)) {
1073 if (irt_is64(ir->t)) { 1077 TValue k;
1074 emit_u32(as, irt_toitype(ir->t) << 15); 1078 lj_ir_kvalue(as->J->L, &k, ir);
1075 emit_rmro(as, XO_ARITHi, XOg_OR, dest, 4); 1079 emit_movmroi(as, dest, 4, k.u32.hi);
1080 emit_movmroi(as, dest, 0, k.u32.lo);
1076 } else { 1081 } else {
1077 /* Currently, no caller passes integers that might end up here. */ 1082 /* TODO: 64 bit store + 32 bit load-modify-store is suboptimal. */
1078 emit_movmroi(as, dest, 4, (irt_toitype(ir->t) << 15)); 1083 Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest));
1084 if (irt_is64(ir->t)) {
1085 emit_u32(as, irt_toitype(ir->t) << 15);
1086 emit_rmro(as, XO_ARITHi, XOg_OR, dest, 4);
1087 } else {
1088 emit_movmroi(as, dest, 4, (irt_toitype(ir->t) << 15));
1089 }
1090 emit_movtomro(as, REX_64IR(ir, src), dest, 0);
1079 } 1091 }
1080 emit_movtomro(as, REX_64IR(ir, src), dest, 0);
1081 }
1082#else 1092#else
1083 if (!irref_isk(ref)) { 1093 if (!irref_isk(ref)) {
1084 Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest)); 1094 Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest));
1085 emit_movtomro(as, REX_64IR(ir, src), dest, 0); 1095 emit_movtomro(as, REX_64IR(ir, src), dest, 0);
1086 } else if (!irt_ispri(ir->t)) { 1096 } else if (!irt_ispri(ir->t)) {
1087 emit_movmroi(as, dest, 0, ir->i); 1097 emit_movmroi(as, dest, 0, ir->i);
1088 } 1098 }
1089 if (!(LJ_64 && irt_islightud(ir->t))) 1099 if (!(LJ_64 && irt_islightud(ir->t)))
1090 emit_movmroi(as, dest, 4, irt_toitype(ir->t)); 1100 emit_movmroi(as, dest, 4, irt_toitype(ir->t));
1091#endif 1101#endif
1092 emit_loada(as, dest, &J2G(as->J)->tmptv); 1102 }
1093 } 1103 }
1104 emit_loada(as, dest, &J2G(as->J)->tmptv); /* g->tmptv holds the TValue(s). */
1094} 1105}
1095 1106
1096static void asm_aref(ASMState *as, IRIns *ir) 1107static void asm_aref(ASMState *as, IRIns *ir)
diff --git a/src/lj_ir.h b/src/lj_ir.h
index ea8616ec..22a3b79c 100644
--- a/src/lj_ir.h
+++ b/src/lj_ir.h
@@ -95,6 +95,7 @@
95 _(UREFO, LW, ref, lit) \ 95 _(UREFO, LW, ref, lit) \
96 _(UREFC, LW, ref, lit) \ 96 _(UREFC, LW, ref, lit) \
97 _(FREF, R , ref, lit) \ 97 _(FREF, R , ref, lit) \
98 _(TMPREF, S , ref, lit) \
98 _(STRREF, N , ref, ref) \ 99 _(STRREF, N , ref, ref) \
99 _(LREF, L , ___, ___) \ 100 _(LREF, L , ___, ___) \
100 \ 101 \
@@ -218,6 +219,11 @@ IRFLDEF(FLENUM)
218 IRFL__MAX 219 IRFL__MAX
219} IRFieldID; 220} IRFieldID;
220 221
222/* TMPREF mode bits, stored in op2. */
223#define IRTMPREF_IN1 0x01 /* First input value. */
224#define IRTMPREF_OUT1 0x02 /* First output value. */
225#define IRTMPREF_OUT2 0x04 /* Second output value. */
226
221/* SLOAD mode bits, stored in op2. */ 227/* SLOAD mode bits, stored in op2. */
222#define IRSLOAD_PARENT 0x01 /* Coalesce with parent trace. */ 228#define IRSLOAD_PARENT 0x01 /* Coalesce with parent trace. */
223#define IRSLOAD_FRAME 0x02 /* Load 32 bits of ftsz. */ 229#define IRSLOAD_FRAME 0x02 /* Load 32 bits of ftsz. */
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c
index 3cf448d6..9a41a5a4 100644
--- a/src/lj_opt_fold.c
+++ b/src/lj_opt_fold.c
@@ -2421,6 +2421,7 @@ LJFOLD(XSTORE any any)
2421LJFOLDX(lj_opt_dse_xstore) 2421LJFOLDX(lj_opt_dse_xstore)
2422 2422
2423LJFOLD(NEWREF any any) /* Treated like a store. */ 2423LJFOLD(NEWREF any any) /* Treated like a store. */
2424LJFOLD(TMPREF any any)
2424LJFOLD(CALLA any any) 2425LJFOLD(CALLA any any)
2425LJFOLD(CALLL any any) /* Safeguard fallback. */ 2426LJFOLD(CALLL any any) /* Safeguard fallback. */
2426LJFOLD(CALLS any any) 2427LJFOLD(CALLS any any)
diff --git a/src/lj_opt_split.c b/src/lj_opt_split.c
index 3a02abd4..25c1c234 100644
--- a/src/lj_opt_split.c
+++ b/src/lj_opt_split.c
@@ -645,7 +645,7 @@ static void split_ir(jit_State *J)
645 tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), hisubst[op1], oir[op1].prev); 645 tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), hisubst[op1], oir[op1].prev);
646#endif 646#endif
647 ir->prev = split_emit(J, IRTI(IR_CALLN), tmp, IRCALL_lj_vm_tobit); 647 ir->prev = split_emit(J, IRTI(IR_CALLN), tmp, IRCALL_lj_vm_tobit);
648 } else if (ir->o == IR_TOSTR) { 648 } else if (ir->o == IR_TOSTR || ir->o == IR_TMPREF) {
649 if (hisubst[ir->op1]) { 649 if (hisubst[ir->op1]) {
650 if (irref_isk(ir->op1)) 650 if (irref_isk(ir->op1))
651 nir->op1 = ir->op1; 651 nir->op1 = ir->op1;
diff --git a/src/lj_record.c b/src/lj_record.c
index 86f17abc..c0aea106 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -259,6 +259,14 @@ TRef lj_record_constify(jit_State *J, cTValue *o)
259 return 0; /* Can't represent lightuserdata (pointless). */ 259 return 0; /* Can't represent lightuserdata (pointless). */
260} 260}
261 261
262/* Emit a VLOAD with the correct type. */
263TRef lj_record_vload(jit_State *J, TRef ref, IRType t)
264{
265 TRef tr = emitir(IRTG(IR_VLOAD, t), ref, 0);
266 if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */
267 return tr;
268}
269
262/* -- Record loop ops ----------------------------------------------------- */ 270/* -- Record loop ops ----------------------------------------------------- */
263 271
264/* Loop event. */ 272/* Loop event. */
@@ -1832,9 +1840,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
1832 IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]); 1840 IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]);
1833 TRef aref = emitir(IRT(IR_AREF, IRT_PGC), 1841 TRef aref = emitir(IRT(IR_AREF, IRT_PGC),
1834 vbase, lj_ir_kint(J, (int32_t)i)); 1842 vbase, lj_ir_kint(J, (int32_t)i));
1835 TRef tr = emitir(IRTG(IR_VLOAD, t), aref, 0); 1843 J->base[dst+i] = lj_record_vload(J, aref, t);
1836 if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */
1837 J->base[dst+i] = tr;
1838 } 1844 }
1839 } else { 1845 } else {
1840 emitir(IRTGI(IR_LE), fr, lj_ir_kint(J, frofs)); 1846 emitir(IRTGI(IR_LE), fr, lj_ir_kint(J, frofs));
@@ -1881,8 +1887,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
1881 lj_ir_kint(J, frofs-(8<<LJ_FR2))); 1887 lj_ir_kint(J, frofs-(8<<LJ_FR2)));
1882 t = itype2irt(&J->L->base[idx-2-LJ_FR2-nvararg]); 1888 t = itype2irt(&J->L->base[idx-2-LJ_FR2-nvararg]);
1883 aref = emitir(IRT(IR_AREF, IRT_PGC), vbase, tridx); 1889 aref = emitir(IRT(IR_AREF, IRT_PGC), vbase, tridx);
1884 tr = emitir(IRTG(IR_VLOAD, t), aref, 0); 1890 tr = lj_record_vload(J, aref, t);
1885 if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */
1886 } 1891 }
1887 J->base[dst-2-LJ_FR2] = tr; 1892 J->base[dst-2-LJ_FR2] = tr;
1888 J->maxslot = dst-1-LJ_FR2; 1893 J->maxslot = dst-1-LJ_FR2;
diff --git a/src/lj_record.h b/src/lj_record.h
index de74277e..03d84a71 100644
--- a/src/lj_record.h
+++ b/src/lj_record.h
@@ -30,6 +30,7 @@ LJ_FUNC int lj_record_objcmp(jit_State *J, TRef a, TRef b,
30 cTValue *av, cTValue *bv); 30 cTValue *av, cTValue *bv);
31LJ_FUNC void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk); 31LJ_FUNC void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk);
32LJ_FUNC TRef lj_record_constify(jit_State *J, cTValue *o); 32LJ_FUNC TRef lj_record_constify(jit_State *J, cTValue *o);
33LJ_FUNC TRef lj_record_vload(jit_State *J, TRef ref, IRType t);
33 34
34LJ_FUNC void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs); 35LJ_FUNC void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs);
35LJ_FUNC void lj_record_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs); 36LJ_FUNC void lj_record_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs);