summaryrefslogtreecommitdiff
path: root/src/lj_crecord.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_crecord.c')
-rw-r--r--src/lj_crecord.c57
1 files changed, 38 insertions, 19 deletions
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index e2b3e8af..c6577975 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -663,7 +663,20 @@ static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm)
663 sp[i] = emitconv(sp[i], dt, IRT_INT, 663 sp[i] = emitconv(sp[i], dt, IRT_INT,
664 ((st - IRT_I8) & 1) ? 0 : IRCONV_SEXT); 664 ((st - IRT_I8) & 1) ? 0 : IRCONV_SEXT);
665 } 665 }
666 if (mm == MM_pow) { 666 if (mm < MM_add) {
667 /* Assume true comparison. Fixup and emit pending guard later. */
668 IROp op;
669 if (mm == MM_eq) {
670 op = IR_EQ;
671 } else {
672 op = mm == MM_lt ? IR_LT : IR_LE;
673 if (dt == IRT_U64)
674 op += (IR_ULT-IR_LT);
675 }
676 lj_ir_set(J, IRTG(op, dt), sp[0], sp[1]);
677 J->postproc = LJ_POST_FIXGUARD;
678 return TREF_TRUE;
679 } else if (mm == MM_pow) {
667 tr = lj_ir_call(J, IRCALL_lj_cdata_powi64, sp[0], sp[1], 680 tr = lj_ir_call(J, IRCALL_lj_cdata_powi64, sp[0], sp[1],
668 lj_ir_kint(J, (int)dt-(int)IRT_I64)); 681 lj_ir_kint(J, (int)dt-(int)IRT_I64));
669 } else { 682 } else {
@@ -683,35 +696,41 @@ static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm)
683{ 696{
684 CTState *cts = ctype_ctsG(J2G(J)); 697 CTState *cts = ctype_ctsG(J2G(J));
685 CType *ctp = s[0]; 698 CType *ctp = s[0];
686 CTSize sz; 699 if (ctype_isptr(ctp->info) || ctype_isrefarray(ctp->info)) {
687 if (!(mm == MM_add || mm == MM_sub)) 700 if ((mm == MM_sub || mm == MM_eq || mm == MM_lt || mm == MM_le) &&
688 return 0; 701 (ctype_isptr(s[1]->info) || ctype_isrefarray(s[1]->info))) {
689 if (ctype_ispointer(ctp->info)) { 702 if (mm == MM_sub) { /* Pointer difference. */
690 sz = lj_ctype_size(cts, ctype_cid(ctp->info)); 703 TRef tr;
691 if (mm == MM_sub && ctype_ispointer(s[1]->info)) { 704 CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info));
692 /* Pointer difference. */ 705 if (sz == 0 || (sz & (sz-1)) != 0)
693 TRef tr; 706 return 0; /* NYI: integer division. */
694 if (sz == 0 || (sz & (sz-1)) != 0) 707 tr = emitir(IRT(IR_SUB, IRT_PTR), sp[0], sp[1]);
695 return 0; /* NYI: integer division. */ 708 tr = emitir(IRT(IR_BSAR, IRT_INTP), tr, lj_ir_kint(J, lj_fls(sz)));
696 tr = emitir(IRT(IR_SUB, IRT_PTR), sp[0], sp[1]);
697 tr = emitir(IRT(IR_BSAR, IRT_INTP), tr, lj_ir_kint(J, lj_fls(sz)));
698#if LJ_64 709#if LJ_64
699 tr = emitconv(tr, IRT_NUM, IRT_INTP, 0); 710 tr = emitconv(tr, IRT_NUM, IRT_INTP, 0);
700#endif 711#endif
701 return tr; 712 return tr;
713 } else { /* Pointer comparison (unsigned). */
714 /* Assume true comparison. Fixup and emit pending guard later. */
715 IROp op = mm == MM_eq ? IR_EQ : mm == MM_lt ? IR_ULT : IR_ULE;
716 lj_ir_set(J, IRTG(op, IRT_PTR), sp[0], sp[1]);
717 J->postproc = LJ_POST_FIXGUARD;
718 return TREF_TRUE;
719 }
702 } 720 }
703 if (!ctype_isnum(s[1]->info)) return 0; 721 if (!((mm == MM_add || mm == MM_sub) && ctype_isnum(s[1]->info)))
704 } else if (mm == MM_add && 722 return 0;
705 ctype_isnum(ctp->info) && ctype_ispointer(s[1]->info)) { 723 } else if (mm == MM_add && ctype_isnum(ctp->info) &&
724 (ctype_isptr(s[1]->info) || ctype_isrefarray(s[1]->info))) {
706 TRef tr = sp[0]; sp[0] = sp[1]; sp[1] = tr; /* Swap pointer and index. */ 725 TRef tr = sp[0]; sp[0] = sp[1]; sp[1] = tr; /* Swap pointer and index. */
707 ctp = s[1]; 726 ctp = s[1];
708 sz = lj_ctype_size(cts, ctype_cid(ctp->info));
709 } else { 727 } else {
710 return 0; 728 return 0;
711 } 729 }
712 { 730 {
713 TRef tr = sp[1]; 731 TRef tr = sp[1];
714 IRType t = tref_type(tr); 732 IRType t = tref_type(tr);
733 CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info));
715 CTypeID id; 734 CTypeID id;
716#if LJ_64 735#if LJ_64
717 if (t == IRT_NUM || t == IRT_FLOAT) 736 if (t == IRT_NUM || t == IRT_FLOAT)