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") |
