diff options
author | Mike Pall <mike> | 2011-02-05 21:50:15 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2011-02-05 21:50:15 +0100 |
commit | 26fadcd25bb9e84e15be0a81a56806d5419c3183 (patch) | |
tree | 91bb326735cb745093d63845027f4bff238b3dc3 /src | |
parent | bf05209e1446aa13416b3dfffe021c85057b9a5d (diff) | |
download | luajit-26fadcd25bb9e84e15be0a81a56806d5419c3183.tar.gz luajit-26fadcd25bb9e84e15be0a81a56806d5419c3183.tar.bz2 luajit-26fadcd25bb9e84e15be0a81a56806d5419c3183.zip |
FFI: Record simple C function calls.
Only handles cdecl and fixarg C functions.
Doesn't handle pass-by-value aggregates.
Doesn't handle 64 bit args/returns on 32 bit CPUs.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_asm.c | 117 | ||||
-rw-r--r-- | src/lj_crecord.c | 71 | ||||
-rw-r--r-- | src/lj_ir.h | 4 | ||||
-rw-r--r-- | src/lj_opt_fold.c | 1 | ||||
-rw-r--r-- | src/lj_opt_mem.c | 7 | ||||
-rw-r--r-- | src/lj_traceerr.h | 1 |
6 files changed, 169 insertions, 32 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index 77b55f0c..acad3b25 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -1459,7 +1459,6 @@ static Reg asm_fuseload(ASMState *as, IRRef ref, RegSet allow) | |||
1459 | /* Generate a call to a C function. */ | 1459 | /* Generate a call to a C function. */ |
1460 | static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | 1460 | static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) |
1461 | { | 1461 | { |
1462 | RegSet allow = RSET_ALL; | ||
1463 | uint32_t n, nargs = CCI_NARGS(ci); | 1462 | uint32_t n, nargs = CCI_NARGS(ci); |
1464 | int32_t ofs = STACKARG_OFS; | 1463 | int32_t ofs = STACKARG_OFS; |
1465 | uint32_t gprs = REGARG_GPRS; | 1464 | uint32_t gprs = REGARG_GPRS; |
@@ -1467,24 +1466,25 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
1467 | Reg fpr = REGARG_FIRSTFPR; | 1466 | Reg fpr = REGARG_FIRSTFPR; |
1468 | #endif | 1467 | #endif |
1469 | lua_assert(!(nargs > 2 && (ci->flags&CCI_FASTCALL))); /* Avoid stack adj. */ | 1468 | lua_assert(!(nargs > 2 && (ci->flags&CCI_FASTCALL))); /* Avoid stack adj. */ |
1470 | emit_call(as, ci->func); | 1469 | if ((void *)ci->func) |
1470 | emit_call(as, ci->func); | ||
1471 | for (n = 0; n < nargs; n++) { /* Setup args. */ | 1471 | for (n = 0; n < nargs; n++) { /* Setup args. */ |
1472 | IRRef ref = args[n]; | 1472 | IRRef ref = args[n]; |
1473 | IRIns *ir = IR(ref); | 1473 | IRIns *ir = IR(ref); |
1474 | Reg r; | 1474 | Reg r; |
1475 | #if LJ_64 && LJ_ABI_WIN | 1475 | #if LJ_64 && LJ_ABI_WIN |
1476 | /* Windows/x64 argument registers are strictly positional. */ | 1476 | /* Windows/x64 argument registers are strictly positional. */ |
1477 | r = irt_isnum(ir->t) ? (fpr <= REGARG_LASTFPR ? fpr : 0) : (gprs & 31); | 1477 | r = irt_isfp(ir->t) ? (fpr <= REGARG_LASTFPR ? fpr : 0) : (gprs & 31); |
1478 | fpr++; gprs >>= 5; | 1478 | fpr++; gprs >>= 5; |
1479 | #elif LJ_64 | 1479 | #elif LJ_64 |
1480 | /* POSIX/x64 argument registers are used in order of appearance. */ | 1480 | /* POSIX/x64 argument registers are used in order of appearance. */ |
1481 | if (irt_isnum(ir->t)) { | 1481 | if (irt_isfp(ir->t)) { |
1482 | r = fpr <= REGARG_LASTFPR ? fpr : 0; fpr++; | 1482 | r = fpr <= REGARG_LASTFPR ? fpr : 0; fpr++; |
1483 | } else { | 1483 | } else { |
1484 | r = gprs & 31; gprs >>= 5; | 1484 | r = gprs & 31; gprs >>= 5; |
1485 | } | 1485 | } |
1486 | #else | 1486 | #else |
1487 | if (irt_isnum(ir->t) || !(ci->flags & CCI_FASTCALL)) { | 1487 | if (irt_isfp(ir->t) || !(ci->flags & CCI_FASTCALL)) { |
1488 | r = 0; | 1488 | r = 0; |
1489 | } else { | 1489 | } else { |
1490 | r = gprs & 31; gprs >>= 5; | 1490 | r = gprs & 31; gprs >>= 5; |
@@ -1514,22 +1514,16 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
1514 | emit_movmroi(as, RID_ESP, ofs, (int32_t)ir_knum(ir)->u32.lo); | 1514 | emit_movmroi(as, RID_ESP, ofs, (int32_t)ir_knum(ir)->u32.lo); |
1515 | emit_movmroi(as, RID_ESP, ofs+4, (int32_t)ir_knum(ir)->u32.hi); | 1515 | emit_movmroi(as, RID_ESP, ofs+4, (int32_t)ir_knum(ir)->u32.hi); |
1516 | } else { | 1516 | } else { |
1517 | if ((allow & RSET_FPR) == RSET_EMPTY) | 1517 | r = ra_alloc1(as, ref, RSET_FPR); |
1518 | lj_trace_err(as->J, LJ_TRERR_NYICOAL); | ||
1519 | r = ra_alloc1(as, ref, allow & RSET_FPR); | ||
1520 | allow &= ~RID2RSET(r); | ||
1521 | emit_rmro(as, irt_isnum(ir->t) ? XO_MOVSDto : XO_MOVSSto, | 1518 | emit_rmro(as, irt_isnum(ir->t) ? XO_MOVSDto : XO_MOVSSto, |
1522 | r, RID_ESP, ofs); | 1519 | r, RID_ESP, ofs); |
1523 | } | 1520 | } |
1524 | ofs += 8; | 1521 | ofs += (LJ_32 && irt_isfloat(ir->t)) ? 4 : 8; |
1525 | } else { /* Non-FP argument is on stack. */ | 1522 | } else { /* Non-FP argument is on stack. */ |
1526 | if (LJ_32 && ref < ASMREF_TMP1) { | 1523 | if (LJ_32 && ref < ASMREF_TMP1) { |
1527 | emit_movmroi(as, RID_ESP, ofs, ir->i); | 1524 | emit_movmroi(as, RID_ESP, ofs, ir->i); |
1528 | } else { | 1525 | } else { |
1529 | if ((allow & RSET_GPR) == RSET_EMPTY) | 1526 | r = ra_alloc1(as, ref, RSET_GPR); |
1530 | lj_trace_err(as->J, LJ_TRERR_NYICOAL); | ||
1531 | r = ra_alloc1(as, ref, allow & RSET_GPR); | ||
1532 | allow &= ~RID2RSET(r); | ||
1533 | emit_movtomro(as, REX_64IR(ir, r), RID_ESP, ofs); | 1527 | emit_movtomro(as, REX_64IR(ir, r), RID_ESP, ofs); |
1534 | } | 1528 | } |
1535 | ofs += sizeof(intptr_t); | 1529 | ofs += sizeof(intptr_t); |
@@ -1575,7 +1569,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) | |||
1575 | emit_movtomro(as, RID_RET, RID_ESP, ofs); | 1569 | emit_movtomro(as, RID_RET, RID_ESP, ofs); |
1576 | emit_movtomro(as, RID_RETHI, RID_ESP, ofs+4); | 1570 | emit_movtomro(as, RID_RETHI, RID_ESP, ofs+4); |
1577 | } else { | 1571 | } else { |
1578 | emit_rmro(as, XO_FSTPq, XOg_FSTPq, RID_ESP, ofs); | 1572 | emit_rmro(as, irt_isnum(ir->t) ? XO_FSTPq : XO_FSTPd, |
1573 | irt_isnum(ir->t) ? XOg_FSTPq : XOg_FSTPd, RID_ESP, ofs); | ||
1579 | } | 1574 | } |
1580 | #endif | 1575 | #endif |
1581 | } else { | 1576 | } else { |
@@ -1585,7 +1580,7 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) | |||
1585 | } | 1580 | } |
1586 | } | 1581 | } |
1587 | 1582 | ||
1588 | /* Collect arguments from CALL* and ARG instructions. */ | 1583 | /* Collect arguments from CALL* and CARG instructions. */ |
1589 | static void asm_collectargs(ASMState *as, IRIns *ir, | 1584 | static void asm_collectargs(ASMState *as, IRIns *ir, |
1590 | const CCallInfo *ci, IRRef *args) | 1585 | const CCallInfo *ci, IRRef *args) |
1591 | { | 1586 | { |
@@ -1610,6 +1605,40 @@ static void asm_call(ASMState *as, IRIns *ir) | |||
1610 | asm_gencall(as, ci, args); | 1605 | asm_gencall(as, ci, args); |
1611 | } | 1606 | } |
1612 | 1607 | ||
1608 | /* Reconstruct CCallInfo flags for CALLX*. */ | ||
1609 | static uint32_t asm_callx_flags(ASMState *as, IRIns *ir) | ||
1610 | { | ||
1611 | uint32_t nargs = 0; | ||
1612 | if (ir->op1 != REF_NIL) { /* Count number of arguments first. */ | ||
1613 | IRIns *ira = IR(ir->op1); | ||
1614 | nargs++; | ||
1615 | while (ira->o == IR_CARG) { nargs++; ira = IR(ira->op1); } | ||
1616 | } | ||
1617 | /* NYI: fastcall etc. */ | ||
1618 | return (nargs | (ir->t.irt << CCI_OTSHIFT)); | ||
1619 | } | ||
1620 | |||
1621 | static void asm_callx(ASMState *as, IRIns *ir) | ||
1622 | { | ||
1623 | IRRef args[CCI_NARGS_MAX]; | ||
1624 | CCallInfo ci; | ||
1625 | IRIns *irf; | ||
1626 | ci.flags = asm_callx_flags(as, ir); | ||
1627 | asm_collectargs(as, ir, &ci, args); | ||
1628 | asm_setupresult(as, ir, &ci); | ||
1629 | irf = IR(ir->op2); | ||
1630 | if (LJ_32 && irref_isk(ir->op2)) { /* Call to constant address on x86. */ | ||
1631 | ci.func = (ASMFunction)(void *)(uintptr_t)(uint32_t)irf->i; | ||
1632 | } else { | ||
1633 | /* Prefer a non-argument register or RID_RET for indirect calls. */ | ||
1634 | RegSet allow = (RSET_GPR & ~RSET_SCRATCH)|RID2RSET(RID_RET); | ||
1635 | Reg r = ra_alloc1(as, ir->op2, allow); | ||
1636 | emit_rr(as, XO_GROUP5, XOg_CALL, r); | ||
1637 | ci.func = (ASMFunction)(void *)0; | ||
1638 | } | ||
1639 | asm_gencall(as, &ci, args); | ||
1640 | } | ||
1641 | |||
1613 | /* -- Returns ------------------------------------------------------------- */ | 1642 | /* -- Returns ------------------------------------------------------------- */ |
1614 | 1643 | ||
1615 | /* Return to lower frame. Guard that it goes to the right spot. */ | 1644 | /* Return to lower frame. Guard that it goes to the right spot. */ |
@@ -4086,6 +4115,7 @@ static void asm_ir(ASMState *as, IRIns *ir) | |||
4086 | 4115 | ||
4087 | /* Calls. */ | 4116 | /* Calls. */ |
4088 | case IR_CALLN: case IR_CALLL: case IR_CALLS: asm_call(as, ir); break; | 4117 | case IR_CALLN: case IR_CALLL: case IR_CALLS: asm_call(as, ir); break; |
4118 | case IR_CALLXS: asm_callx(as, ir); break; | ||
4089 | case IR_CARG: break; | 4119 | case IR_CARG: break; |
4090 | 4120 | ||
4091 | default: | 4121 | default: |
@@ -4113,6 +4143,43 @@ static void asm_trace(ASMState *as) | |||
4113 | 4143 | ||
4114 | /* -- Trace setup --------------------------------------------------------- */ | 4144 | /* -- Trace setup --------------------------------------------------------- */ |
4115 | 4145 | ||
4146 | /* Ensure there are enough stack slots for call arguments. */ | ||
4147 | static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci) | ||
4148 | { | ||
4149 | IRRef args[CCI_NARGS_MAX]; | ||
4150 | uint32_t nargs = (int)CCI_NARGS(ci); | ||
4151 | int nslots = 0; | ||
4152 | asm_collectargs(as, ir, ci, args); | ||
4153 | #if LJ_64 | ||
4154 | if (LJ_ABI_WIN) { | ||
4155 | nslots = (int)(nargs*2); /* Only matters for more than four args. */ | ||
4156 | } else { | ||
4157 | uint32_t i; | ||
4158 | int ngpr = 6, nfpr = 8; | ||
4159 | for (i = 0; i < nargs; i++) | ||
4160 | if (irt_isfp(IR(args[i])->t)) { | ||
4161 | if (nfpr > 0) nfpr--; else nslots += 2; | ||
4162 | } else { | ||
4163 | if (ngpr > 0) ngpr--; else nslots += 2; | ||
4164 | } | ||
4165 | } | ||
4166 | if (nslots > as->evenspill) /* Leave room for args in stack slots. */ | ||
4167 | as->evenspill = nslots; | ||
4168 | return irt_isfp(ir->t) ? REGSP_HINT(RID_FPRET) : REGSP_HINT(RID_RET); | ||
4169 | #else | ||
4170 | if ((ci->flags & CCI_FASTCALL)) { | ||
4171 | lua_assert(nargs <= 2); | ||
4172 | } else { | ||
4173 | uint32_t i; | ||
4174 | for (i = 0; i < nargs; i++) | ||
4175 | nslots += irt_isnum(IR(args[i])->t) ? 2 : 1; | ||
4176 | if (nslots > as->evenspill) /* Leave room for args. */ | ||
4177 | as->evenspill = nslots; | ||
4178 | } | ||
4179 | return irt_isfp(ir->t) ? REGSP_INIT : REGSP_HINT(RID_RET); | ||
4180 | #endif | ||
4181 | } | ||
4182 | |||
4116 | /* Clear reg/sp for all instructions and add register hints. */ | 4183 | /* Clear reg/sp for all instructions and add register hints. */ |
4117 | static void asm_setup_regsp(ASMState *as, GCtrace *T) | 4184 | static void asm_setup_regsp(ASMState *as, GCtrace *T) |
4118 | { | 4185 | { |
@@ -4161,17 +4228,17 @@ static void asm_setup_regsp(ASMState *as, GCtrace *T) | |||
4161 | } | 4228 | } |
4162 | } | 4229 | } |
4163 | break; | 4230 | break; |
4231 | case IR_CALLXS: { | ||
4232 | CCallInfo ci; | ||
4233 | ci.flags = asm_callx_flags(as, ir); | ||
4234 | ir->prev = asm_setup_call_slots(as, ir, &ci); | ||
4235 | if (inloop) | ||
4236 | as->modset |= RSET_SCRATCH; | ||
4237 | continue; | ||
4238 | } | ||
4164 | case IR_CALLN: case IR_CALLL: case IR_CALLS: { | 4239 | case IR_CALLN: case IR_CALLL: case IR_CALLS: { |
4165 | const CCallInfo *ci = &lj_ir_callinfo[ir->op2]; | 4240 | const CCallInfo *ci = &lj_ir_callinfo[ir->op2]; |
4166 | #if LJ_64 | 4241 | ir->prev = asm_setup_call_slots(as, ir, ci); |
4167 | lua_assert(CCI_NARGS(ci) <= (LJ_ABI_WIN ? 4 : 6)); | ||
4168 | ir->prev = REGSP_HINT(irt_isnum(ir->t) ? RID_FPRET : RID_RET); | ||
4169 | #else | ||
4170 | lua_assert(!(ci->flags & CCI_FASTCALL) || CCI_NARGS(ci) <= 2); | ||
4171 | if (CCI_NARGS(ci) > (uint32_t)as->evenspill) /* Leave room for args. */ | ||
4172 | as->evenspill = (int32_t)CCI_NARGS(ci); | ||
4173 | ir->prev = REGSP_HINT(RID_RET); | ||
4174 | #endif | ||
4175 | if (inloop) | 4242 | if (inloop) |
4176 | as->modset |= (ci->flags & CCI_NOFPRCLOBBER) ? | 4243 | as->modset |= (ci->flags & CCI_NOFPRCLOBBER) ? |
4177 | (RSET_SCRATCH & ~RSET_FPR) : RSET_SCRATCH; | 4244 | (RSET_SCRATCH & ~RSET_FPR) : RSET_SCRATCH; |
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index b4bfd0c2..2ecd2867 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c | |||
@@ -670,14 +670,79 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
670 | } | 670 | } |
671 | } | 671 | } |
672 | 672 | ||
673 | /* Record argument conversions. */ | ||
674 | static TRef crec_call_args(jit_State *J, RecordFFData *rd, | ||
675 | CTState *cts, CType *ct) | ||
676 | { | ||
677 | TRef args[CCI_NARGS_MAX]; | ||
678 | MSize i, n; | ||
679 | TRef tr; | ||
680 | args[0] = TREF_NIL; | ||
681 | for (n = 0; J->base[n+1]; n++) { | ||
682 | CType *d; | ||
683 | do { | ||
684 | if (!ct->sib) | ||
685 | lj_trace_err(J, LJ_TRERR_NYICALL); | ||
686 | ct = ctype_get(cts, ct->sib); | ||
687 | } while (ctype_isattrib(ct->info)); | ||
688 | if (!ctype_isfield(ct->info)) | ||
689 | lj_trace_err(J, LJ_TRERR_NYICALL); | ||
690 | d = ctype_rawchild(cts, ct); | ||
691 | if (ctype_isenum(d->info)) d = ctype_child(cts, d); | ||
692 | if (!(ctype_isnum(d->info) || ctype_isptr(d->info))) | ||
693 | lj_trace_err(J, LJ_TRERR_NYICALL); | ||
694 | args[n] = crec_ct_tv(J, d, 0, J->base[n+1], &rd->argv[n+1]); | ||
695 | } | ||
696 | tr = args[0]; | ||
697 | for (i = 1; i < n; i++) | ||
698 | tr = emitir(IRT(IR_CARG, IRT_NIL), tr, args[i]); | ||
699 | return tr; | ||
700 | } | ||
701 | |||
702 | /* Record function call. */ | ||
703 | static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) | ||
704 | { | ||
705 | CTState *cts = ctype_ctsG(J2G(J)); | ||
706 | CType *ct = ctype_raw(cts, cd->typeid); | ||
707 | IRType tp = IRT_PTR; | ||
708 | if (ctype_isptr(ct->info)) { | ||
709 | tp = (LJ_64 && ct->size == 8) ? IRT_P64 : IRT_P32; | ||
710 | ct = ctype_rawchild(cts, ct); | ||
711 | } | ||
712 | if (ctype_isfunc(ct->info)) { | ||
713 | TRef func = emitir(IRT(IR_FLOAD, tp), J->base[0], IRFL_CDATA_PTR); | ||
714 | CType *ctr = ctype_rawchild(cts, ct); | ||
715 | IRType t = crec_ct2irt(ctr); | ||
716 | TRef tr; | ||
717 | if (ctype_isenum(ctr->info)) ctr = ctype_child(cts, ctr); | ||
718 | if (!(ctype_isnum(ctr->info) || ctype_isptr(ctr->info)) || | ||
719 | ctype_isbool(ctr->info) || (ct->info & CTF_VARARG) || | ||
720 | #if LJ_TARGET_X86 | ||
721 | ctype_cconv(ct->info) != CTCC_CDECL || | ||
722 | #endif | ||
723 | t == IRT_CDATA || (LJ_32 && (t == IRT_I64 || t == IRT_U64))) | ||
724 | lj_trace_err(J, LJ_TRERR_NYICALL); | ||
725 | tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func); | ||
726 | if (t == IRT_FLOAT || t == IRT_U32) { | ||
727 | tr = emitconv(tr, IRT_NUM, t, 0); | ||
728 | } else if (t == IRT_PTR || (LJ_64 && t == IRT_P32) || | ||
729 | (LJ_64 && (t == IRT_I64 || t == IRT_U64))) { | ||
730 | TRef trid = lj_ir_kint(J, ctype_cid(ct->info)); | ||
731 | tr = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, tr); | ||
732 | } | ||
733 | J->base[0] = tr; | ||
734 | return 1; | ||
735 | } | ||
736 | return 0; | ||
737 | } | ||
738 | |||
673 | void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd) | 739 | void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd) |
674 | { | 740 | { |
675 | GCcdata *cd = argv2cdata(J, J->base[0], &rd->argv[0]); | 741 | GCcdata *cd = argv2cdata(J, J->base[0], &rd->argv[0]); |
676 | if (cd->typeid == CTID_CTYPEID) { | 742 | if (cd->typeid == CTID_CTYPEID) |
677 | crec_alloc(J, rd, crec_constructor(J, cd, J->base[0])); | 743 | crec_alloc(J, rd, crec_constructor(J, cd, J->base[0])); |
678 | } else { | 744 | else if (!crec_call(J, rd, cd)) |
679 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 745 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
680 | } | ||
681 | } | 746 | } |
682 | 747 | ||
683 | static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm) | 748 | static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm) |
diff --git a/src/lj_ir.h b/src/lj_ir.h index bedb4c2b..532d7a9e 100644 --- a/src/lj_ir.h +++ b/src/lj_ir.h | |||
@@ -129,6 +129,7 @@ | |||
129 | _(CALLN, N , ref, lit) \ | 129 | _(CALLN, N , ref, lit) \ |
130 | _(CALLL, L , ref, lit) \ | 130 | _(CALLL, L , ref, lit) \ |
131 | _(CALLS, S , ref, lit) \ | 131 | _(CALLS, S , ref, lit) \ |
132 | _(CALLXS, S , ref, ref) \ | ||
132 | _(CARG, N , ref, ref) \ | 133 | _(CARG, N , ref, ref) \ |
133 | \ | 134 | \ |
134 | /* End of list. */ | 135 | /* End of list. */ |
@@ -236,7 +237,7 @@ typedef struct CCallInfo { | |||
236 | } CCallInfo; | 237 | } CCallInfo; |
237 | 238 | ||
238 | #define CCI_NARGS(ci) ((ci)->flags & 0xff) /* Extract # of args. */ | 239 | #define CCI_NARGS(ci) ((ci)->flags & 0xff) /* Extract # of args. */ |
239 | #define CCI_NARGS_MAX 16 /* Max. # of args. */ | 240 | #define CCI_NARGS_MAX 32 /* Max. # of args. */ |
240 | 241 | ||
241 | #define CCI_OTSHIFT 16 | 242 | #define CCI_OTSHIFT 16 |
242 | #define CCI_OPTYPE(ci) ((ci)->flags >> CCI_OTSHIFT) /* Get op/type. */ | 243 | #define CCI_OPTYPE(ci) ((ci)->flags >> CCI_OTSHIFT) /* Get op/type. */ |
@@ -590,7 +591,6 @@ typedef union IRIns { | |||
590 | check_exp((ir)->o == IR_KNUM || (ir)->o == IR_KINT64, mref((ir)->ptr,cTValue)) | 591 | check_exp((ir)->o == IR_KNUM || (ir)->o == IR_KINT64, mref((ir)->ptr,cTValue)) |
591 | #define ir_kptr(ir) \ | 592 | #define ir_kptr(ir) \ |
592 | check_exp((ir)->o == IR_KPTR || (ir)->o == IR_KKPTR, mref((ir)->ptr, void)) | 593 | check_exp((ir)->o == IR_KPTR || (ir)->o == IR_KKPTR, mref((ir)->ptr, void)) |
593 | |||
594 | LJ_STATIC_ASSERT((int)IRT_GUARD == (int)IRM_W); | 594 | LJ_STATIC_ASSERT((int)IRT_GUARD == (int)IRM_W); |
595 | 595 | ||
596 | /* A store or any other op with a non-weak guard has a side-effect. */ | 596 | /* A store or any other op with a non-weak guard has a side-effect. */ |
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index ef397aea..1172f4fc 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c | |||
@@ -1891,6 +1891,7 @@ LJFOLDX(lj_opt_dse_xstore) | |||
1891 | LJFOLD(NEWREF any any) /* Treated like a store. */ | 1891 | LJFOLD(NEWREF any any) /* Treated like a store. */ |
1892 | LJFOLD(CALLS any any) | 1892 | LJFOLD(CALLS any any) |
1893 | LJFOLD(CALLL any any) /* Safeguard fallback. */ | 1893 | LJFOLD(CALLL any any) /* Safeguard fallback. */ |
1894 | LJFOLD(CALLXS any any) | ||
1894 | LJFOLD(RETF any any) /* Modifies BASE. */ | 1895 | LJFOLD(RETF any any) /* Modifies BASE. */ |
1895 | LJFOLD(TNEW any any) | 1896 | LJFOLD(TNEW any any) |
1896 | LJFOLD(TDUP any) | 1897 | LJFOLD(TDUP any) |
diff --git a/src/lj_opt_mem.c b/src/lj_opt_mem.c index cad85bb7..211c329a 100644 --- a/src/lj_opt_mem.c +++ b/src/lj_opt_mem.c | |||
@@ -675,7 +675,8 @@ TRef LJ_FASTCALL lj_opt_fwd_xload(jit_State *J) | |||
675 | /* Search for conflicting stores. */ | 675 | /* Search for conflicting stores. */ |
676 | ref = J->chain[IR_XSTORE]; | 676 | ref = J->chain[IR_XSTORE]; |
677 | retry: | 677 | retry: |
678 | while (ref > xref) { | 678 | if (J->chain[IR_CALLXS] > lim) lim = J->chain[IR_CALLXS]; |
679 | while (ref > lim) { | ||
679 | IRIns *store = IR(ref); | 680 | IRIns *store = IR(ref); |
680 | switch (aa_xref(J, xr, fins, store)) { | 681 | switch (aa_xref(J, xr, fins, store)) { |
681 | case ALIAS_NO: break; /* Continue searching. */ | 682 | case ALIAS_NO: break; /* Continue searching. */ |
@@ -732,10 +733,12 @@ TRef LJ_FASTCALL lj_opt_dse_xstore(jit_State *J) | |||
732 | { | 733 | { |
733 | IRRef xref = fins->op1; | 734 | IRRef xref = fins->op1; |
734 | IRIns *xr = IR(xref); | 735 | IRIns *xr = IR(xref); |
736 | IRRef lim = xref; /* Search limit. */ | ||
735 | IRRef val = fins->op2; /* Stored value reference. */ | 737 | IRRef val = fins->op2; /* Stored value reference. */ |
736 | IRRef1 *refp = &J->chain[IR_XSTORE]; | 738 | IRRef1 *refp = &J->chain[IR_XSTORE]; |
737 | IRRef ref = *refp; | 739 | IRRef ref = *refp; |
738 | while (ref > xref) { /* Search for redundant or conflicting stores. */ | 740 | if (J->chain[IR_CALLXS] > lim) lim = J->chain[IR_CALLXS]; |
741 | while (ref > lim) { /* Search for redundant or conflicting stores. */ | ||
739 | IRIns *store = IR(ref); | 742 | IRIns *store = IR(ref); |
740 | switch (aa_xref(J, xr, fins, store)) { | 743 | switch (aa_xref(J, xr, fins, store)) { |
741 | case ALIAS_NO: | 744 | case ALIAS_NO: |
diff --git a/src/lj_traceerr.h b/src/lj_traceerr.h index f0c45963..756330ec 100644 --- a/src/lj_traceerr.h +++ b/src/lj_traceerr.h | |||
@@ -37,6 +37,7 @@ TREDEF(NYITMIX, "NYI: mixed sparse/dense table") | |||
37 | /* Recording C data operations. */ | 37 | /* Recording C data operations. */ |
38 | TREDEF(NOCACHE, "symbol not in cache") | 38 | TREDEF(NOCACHE, "symbol not in cache") |
39 | TREDEF(NYICONV, "NYI: unsupported C type conversion") | 39 | TREDEF(NYICONV, "NYI: unsupported C type conversion") |
40 | TREDEF(NYICALL, "NYI: unsupported C function type") | ||
40 | 41 | ||
41 | /* Optimizations. */ | 42 | /* Optimizations. */ |
42 | TREDEF(GFAIL, "guard would always fail") | 43 | TREDEF(GFAIL, "guard would always fail") |