diff options
Diffstat (limited to 'src/lj_crecord.c')
-rw-r--r-- | src/lj_crecord.c | 391 |
1 files changed, 327 insertions, 64 deletions
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 3f3552a6..bc21d859 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c | |||
@@ -11,13 +11,13 @@ | |||
11 | #if LJ_HASJIT && LJ_HASFFI | 11 | #if LJ_HASJIT && LJ_HASFFI |
12 | 12 | ||
13 | #include "lj_err.h" | 13 | #include "lj_err.h" |
14 | #include "lj_str.h" | ||
15 | #include "lj_tab.h" | 14 | #include "lj_tab.h" |
16 | #include "lj_frame.h" | 15 | #include "lj_frame.h" |
17 | #include "lj_ctype.h" | 16 | #include "lj_ctype.h" |
18 | #include "lj_cdata.h" | 17 | #include "lj_cdata.h" |
19 | #include "lj_cparse.h" | 18 | #include "lj_cparse.h" |
20 | #include "lj_cconv.h" | 19 | #include "lj_cconv.h" |
20 | #include "lj_carith.h" | ||
21 | #include "lj_clib.h" | 21 | #include "lj_clib.h" |
22 | #include "lj_ccall.h" | 22 | #include "lj_ccall.h" |
23 | #include "lj_ff.h" | 23 | #include "lj_ff.h" |
@@ -31,6 +31,7 @@ | |||
31 | #include "lj_snap.h" | 31 | #include "lj_snap.h" |
32 | #include "lj_crecord.h" | 32 | #include "lj_crecord.h" |
33 | #include "lj_dispatch.h" | 33 | #include "lj_dispatch.h" |
34 | #include "lj_strfmt.h" | ||
34 | 35 | ||
35 | /* Some local macros to save typing. Undef'd at the end. */ | 36 | /* Some local macros to save typing. Undef'd at the end. */ |
36 | #define IR(ref) (&J->cur.ir[(ref)]) | 37 | #define IR(ref) (&J->cur.ir[(ref)]) |
@@ -60,7 +61,8 @@ static GCcdata *argv2cdata(jit_State *J, TRef tr, cTValue *o) | |||
60 | static CTypeID crec_constructor(jit_State *J, GCcdata *cd, TRef tr) | 61 | static CTypeID crec_constructor(jit_State *J, GCcdata *cd, TRef tr) |
61 | { | 62 | { |
62 | CTypeID id; | 63 | CTypeID id; |
63 | lua_assert(tref_iscdata(tr) && cd->ctypeid == CTID_CTYPEID); | 64 | lj_assertJ(tref_iscdata(tr) && cd->ctypeid == CTID_CTYPEID, |
65 | "expected CTypeID cdata"); | ||
64 | id = *(CTypeID *)cdataptr(cd); | 66 | id = *(CTypeID *)cdataptr(cd); |
65 | tr = emitir(IRT(IR_FLOAD, IRT_INT), tr, IRFL_CDATA_INT); | 67 | tr = emitir(IRT(IR_FLOAD, IRT_INT), tr, IRFL_CDATA_INT); |
66 | emitir(IRTG(IR_EQ, IRT_INT), tr, lj_ir_kint(J, (int32_t)id)); | 68 | emitir(IRTG(IR_EQ, IRT_INT), tr, lj_ir_kint(J, (int32_t)id)); |
@@ -211,7 +213,7 @@ static void crec_copy_emit(jit_State *J, CRecMemList *ml, MSize mlp, | |||
211 | ml[i].trval = emitir(IRT(IR_XLOAD, ml[i].tp), trsptr, 0); | 213 | ml[i].trval = emitir(IRT(IR_XLOAD, ml[i].tp), trsptr, 0); |
212 | ml[i].trofs = trofs; | 214 | ml[i].trofs = trofs; |
213 | i++; | 215 | i++; |
214 | rwin += (LJ_SOFTFP && ml[i].tp == IRT_NUM) ? 2 : 1; | 216 | rwin += (LJ_SOFTFP32 && ml[i].tp == IRT_NUM) ? 2 : 1; |
215 | if (rwin >= CREC_COPY_REGWIN || i >= mlp) { /* Flush buffered stores. */ | 217 | if (rwin >= CREC_COPY_REGWIN || i >= mlp) { /* Flush buffered stores. */ |
216 | rwin = 0; | 218 | rwin = 0; |
217 | for ( ; j < i; j++) { | 219 | for ( ; j < i; j++) { |
@@ -236,13 +238,14 @@ static void crec_copy(jit_State *J, TRef trdst, TRef trsrc, TRef trlen, | |||
236 | if (len > CREC_COPY_MAXLEN) goto fallback; | 238 | if (len > CREC_COPY_MAXLEN) goto fallback; |
237 | if (ct) { | 239 | if (ct) { |
238 | CTState *cts = ctype_ctsG(J2G(J)); | 240 | CTState *cts = ctype_ctsG(J2G(J)); |
239 | lua_assert(ctype_isarray(ct->info) || ctype_isstruct(ct->info)); | 241 | lj_assertJ(ctype_isarray(ct->info) || ctype_isstruct(ct->info), |
242 | "copy of non-aggregate"); | ||
240 | if (ctype_isarray(ct->info)) { | 243 | if (ctype_isarray(ct->info)) { |
241 | CType *cct = ctype_rawchild(cts, ct); | 244 | CType *cct = ctype_rawchild(cts, ct); |
242 | tp = crec_ct2irt(cts, cct); | 245 | tp = crec_ct2irt(cts, cct); |
243 | if (tp == IRT_CDATA) goto rawcopy; | 246 | if (tp == IRT_CDATA) goto rawcopy; |
244 | step = lj_ir_type_size[tp]; | 247 | step = lj_ir_type_size[tp]; |
245 | lua_assert((len & (step-1)) == 0); | 248 | lj_assertJ((len & (step-1)) == 0, "copy of fractional size"); |
246 | } else if ((ct->info & CTF_UNION)) { | 249 | } else if ((ct->info & CTF_UNION)) { |
247 | step = (1u << ctype_align(ct->info)); | 250 | step = (1u << ctype_align(ct->info)); |
248 | goto rawcopy; | 251 | goto rawcopy; |
@@ -441,7 +444,7 @@ static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp, | |||
441 | /* fallthrough */ | 444 | /* fallthrough */ |
442 | case CCX(I, F): | 445 | case CCX(I, F): |
443 | if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi; | 446 | if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi; |
444 | sp = emitconv(sp, dsize < 4 ? IRT_INT : dt, st, IRCONV_TRUNC|IRCONV_ANY); | 447 | sp = emitconv(sp, dsize < 4 ? IRT_INT : dt, st, IRCONV_ANY); |
445 | goto xstore; | 448 | goto xstore; |
446 | case CCX(I, P): | 449 | case CCX(I, P): |
447 | case CCX(I, A): | 450 | case CCX(I, A): |
@@ -521,7 +524,7 @@ static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp, | |||
521 | if (st == IRT_CDATA) goto err_nyi; | 524 | if (st == IRT_CDATA) goto err_nyi; |
522 | /* The signed conversion is cheaper. x64 really has 47 bit pointers. */ | 525 | /* The signed conversion is cheaper. x64 really has 47 bit pointers. */ |
523 | sp = emitconv(sp, (LJ_64 && dsize == 8) ? IRT_I64 : IRT_U32, | 526 | sp = emitconv(sp, (LJ_64 && dsize == 8) ? IRT_I64 : IRT_U32, |
524 | st, IRCONV_TRUNC|IRCONV_ANY); | 527 | st, IRCONV_ANY); |
525 | goto xstore; | 528 | goto xstore; |
526 | 529 | ||
527 | /* Destination is an array. */ | 530 | /* Destination is an array. */ |
@@ -613,10 +616,12 @@ static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval) | |||
613 | sp = lj_ir_kptr(J, NULL); | 616 | sp = lj_ir_kptr(J, NULL); |
614 | } else if (tref_isudata(sp)) { | 617 | } else if (tref_isudata(sp)) { |
615 | GCudata *ud = udataV(sval); | 618 | GCudata *ud = udataV(sval); |
616 | if (ud->udtype == UDTYPE_IO_FILE) { | 619 | if (ud->udtype == UDTYPE_IO_FILE || ud->udtype == UDTYPE_BUFFER) { |
617 | TRef tr = emitir(IRT(IR_FLOAD, IRT_U8), sp, IRFL_UDATA_UDTYPE); | 620 | TRef tr = emitir(IRT(IR_FLOAD, IRT_U8), sp, IRFL_UDATA_UDTYPE); |
618 | emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, UDTYPE_IO_FILE)); | 621 | emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, ud->udtype)); |
619 | sp = emitir(IRT(IR_FLOAD, IRT_PTR), sp, IRFL_UDATA_FILE); | 622 | sp = emitir(IRT(IR_FLOAD, IRT_PTR), sp, |
623 | ud->udtype == UDTYPE_IO_FILE ? IRFL_UDATA_FILE : | ||
624 | IRFL_SBUF_R); | ||
620 | } else { | 625 | } else { |
621 | sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCudata))); | 626 | sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCudata))); |
622 | } | 627 | } |
@@ -628,7 +633,8 @@ static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval) | |||
628 | /* Specialize to the name of the enum constant. */ | 633 | /* Specialize to the name of the enum constant. */ |
629 | emitir(IRTG(IR_EQ, IRT_STR), sp, lj_ir_kstr(J, str)); | 634 | emitir(IRTG(IR_EQ, IRT_STR), sp, lj_ir_kstr(J, str)); |
630 | if (cct && ctype_isconstval(cct->info)) { | 635 | if (cct && ctype_isconstval(cct->info)) { |
631 | lua_assert(ctype_child(cts, cct)->size == 4); | 636 | lj_assertJ(ctype_child(cts, cct)->size == 4, |
637 | "only 32 bit const supported"); /* NYI */ | ||
632 | svisnz = (void *)(intptr_t)(ofs != 0); | 638 | svisnz = (void *)(intptr_t)(ofs != 0); |
633 | sp = lj_ir_kint(J, (int32_t)ofs); | 639 | sp = lj_ir_kint(J, (int32_t)ofs); |
634 | sid = ctype_cid(cct->info); | 640 | sid = ctype_cid(cct->info); |
@@ -640,12 +646,22 @@ static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval) | |||
640 | sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCstr))); | 646 | sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCstr))); |
641 | sid = CTID_A_CCHAR; | 647 | sid = CTID_A_CCHAR; |
642 | } | 648 | } |
643 | } else { /* NYI: tref_istab(sp), tref_islightud(sp). */ | 649 | } else if (tref_islightud(sp)) { |
650 | #if LJ_64 | ||
651 | lj_trace_err(J, LJ_TRERR_NYICONV); | ||
652 | #endif | ||
653 | } else { /* NYI: tref_istab(sp). */ | ||
644 | IRType t; | 654 | IRType t; |
645 | sid = argv2cdata(J, sp, sval)->ctypeid; | 655 | sid = argv2cdata(J, sp, sval)->ctypeid; |
646 | s = ctype_raw(cts, sid); | 656 | s = ctype_raw(cts, sid); |
647 | svisnz = cdataptr(cdataV(sval)); | 657 | svisnz = cdataptr(cdataV(sval)); |
648 | t = crec_ct2irt(cts, s); | 658 | if (ctype_isfunc(s->info)) { |
659 | sid = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|sid), CTSIZE_PTR); | ||
660 | s = ctype_get(cts, sid); | ||
661 | t = IRT_PTR; | ||
662 | } else { | ||
663 | t = crec_ct2irt(cts, s); | ||
664 | } | ||
649 | if (ctype_isptr(s->info)) { | 665 | if (ctype_isptr(s->info)) { |
650 | sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_PTR); | 666 | sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_PTR); |
651 | if (ctype_isref(s->info)) { | 667 | if (ctype_isref(s->info)) { |
@@ -700,6 +716,19 @@ static TRef crec_reassoc_ofs(jit_State *J, TRef tr, ptrdiff_t *ofsp, MSize sz) | |||
700 | return tr; | 716 | return tr; |
701 | } | 717 | } |
702 | 718 | ||
719 | /* Tailcall to function. */ | ||
720 | static void crec_tailcall(jit_State *J, RecordFFData *rd, cTValue *tv) | ||
721 | { | ||
722 | TRef kfunc = lj_ir_kfunc(J, funcV(tv)); | ||
723 | #if LJ_FR2 | ||
724 | J->base[-2] = kfunc; | ||
725 | J->base[-1] = TREF_FRAME; | ||
726 | #else | ||
727 | J->base[-1] = kfunc | TREF_FRAME; | ||
728 | #endif | ||
729 | rd->nres = -1; /* Pending tailcall. */ | ||
730 | } | ||
731 | |||
703 | /* Record ctype __index/__newindex metamethods. */ | 732 | /* Record ctype __index/__newindex metamethods. */ |
704 | static void crec_index_meta(jit_State *J, CTState *cts, CType *ct, | 733 | static void crec_index_meta(jit_State *J, CTState *cts, CType *ct, |
705 | RecordFFData *rd) | 734 | RecordFFData *rd) |
@@ -709,8 +738,7 @@ static void crec_index_meta(jit_State *J, CTState *cts, CType *ct, | |||
709 | if (!tv) | 738 | if (!tv) |
710 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 739 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
711 | if (tvisfunc(tv)) { | 740 | if (tvisfunc(tv)) { |
712 | J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME; | 741 | crec_tailcall(J, rd, tv); |
713 | rd->nres = -1; /* Pending tailcall. */ | ||
714 | } else if (rd->data == 0 && tvistab(tv) && tref_isstr(J->base[1])) { | 742 | } else if (rd->data == 0 && tvistab(tv) && tref_isstr(J->base[1])) { |
715 | /* Specialize to result of __index lookup. */ | 743 | /* Specialize to result of __index lookup. */ |
716 | cTValue *o = lj_tab_get(J->L, tabV(tv), &rd->argv[1]); | 744 | cTValue *o = lj_tab_get(J->L, tabV(tv), &rd->argv[1]); |
@@ -727,6 +755,48 @@ static void crec_index_meta(jit_State *J, CTState *cts, CType *ct, | |||
727 | } | 755 | } |
728 | } | 756 | } |
729 | 757 | ||
758 | /* Record bitfield load/store. */ | ||
759 | static void crec_index_bf(jit_State *J, RecordFFData *rd, TRef ptr, CTInfo info) | ||
760 | { | ||
761 | IRType t = IRT_I8 + 2*lj_fls(ctype_bitcsz(info)) + ((info&CTF_UNSIGNED)?1:0); | ||
762 | TRef tr = emitir(IRT(IR_XLOAD, t), ptr, 0); | ||
763 | CTSize pos = ctype_bitpos(info), bsz = ctype_bitbsz(info), shift = 32 - bsz; | ||
764 | lj_assertJ(t <= IRT_U32, "only 32 bit bitfields supported"); /* NYI */ | ||
765 | if (rd->data == 0) { /* __index metamethod. */ | ||
766 | if ((info & CTF_BOOL)) { | ||
767 | tr = emitir(IRTI(IR_BAND), tr, lj_ir_kint(J, (int32_t)((1u << pos)))); | ||
768 | /* Assume not equal to zero. Fixup and emit pending guard later. */ | ||
769 | lj_ir_set(J, IRTGI(IR_NE), tr, lj_ir_kint(J, 0)); | ||
770 | J->postproc = LJ_POST_FIXGUARD; | ||
771 | tr = TREF_TRUE; | ||
772 | } else if (!(info & CTF_UNSIGNED)) { | ||
773 | tr = emitir(IRTI(IR_BSHL), tr, lj_ir_kint(J, shift - pos)); | ||
774 | tr = emitir(IRTI(IR_BSAR), tr, lj_ir_kint(J, shift)); | ||
775 | } else { | ||
776 | lj_assertJ(bsz < 32, "unexpected full bitfield index"); | ||
777 | tr = emitir(IRTI(IR_BSHR), tr, lj_ir_kint(J, pos)); | ||
778 | tr = emitir(IRTI(IR_BAND), tr, lj_ir_kint(J, (int32_t)((1u << bsz)-1))); | ||
779 | /* We can omit the U32 to NUM conversion, since bsz < 32. */ | ||
780 | } | ||
781 | J->base[0] = tr; | ||
782 | } else { /* __newindex metamethod. */ | ||
783 | CTState *cts = ctype_ctsG(J2G(J)); | ||
784 | CType *ct = ctype_get(cts, | ||
785 | (info & CTF_BOOL) ? CTID_BOOL : | ||
786 | (info & CTF_UNSIGNED) ? CTID_UINT32 : CTID_INT32); | ||
787 | int32_t mask = (int32_t)(((1u << bsz)-1) << pos); | ||
788 | TRef sp = crec_ct_tv(J, ct, 0, J->base[2], &rd->argv[2]); | ||
789 | sp = emitir(IRTI(IR_BSHL), sp, lj_ir_kint(J, pos)); | ||
790 | /* Use of the target type avoids forwarding conversions. */ | ||
791 | sp = emitir(IRT(IR_BAND, t), sp, lj_ir_kint(J, mask)); | ||
792 | tr = emitir(IRT(IR_BAND, t), tr, lj_ir_kint(J, (int32_t)~mask)); | ||
793 | tr = emitir(IRT(IR_BOR, t), tr, sp); | ||
794 | emitir(IRT(IR_XSTORE, t), ptr, tr); | ||
795 | rd->nres = 0; | ||
796 | J->needsnap = 1; | ||
797 | } | ||
798 | } | ||
799 | |||
730 | void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd) | 800 | void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd) |
731 | { | 801 | { |
732 | TRef idx, ptr = J->base[0]; | 802 | TRef idx, ptr = J->base[0]; |
@@ -801,6 +871,7 @@ again: | |||
801 | CType *fct; | 871 | CType *fct; |
802 | fct = lj_ctype_getfield(cts, ct, name, &fofs); | 872 | fct = lj_ctype_getfield(cts, ct, name, &fofs); |
803 | if (fct) { | 873 | if (fct) { |
874 | ofs += (ptrdiff_t)fofs; | ||
804 | /* Always specialize to the field name. */ | 875 | /* Always specialize to the field name. */ |
805 | emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, name)); | 876 | emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, name)); |
806 | if (ctype_isconstval(fct->info)) { | 877 | if (ctype_isconstval(fct->info)) { |
@@ -812,12 +883,14 @@ again: | |||
812 | J->base[0] = lj_ir_kint(J, (int32_t)fct->size); | 883 | J->base[0] = lj_ir_kint(J, (int32_t)fct->size); |
813 | return; /* Interpreter will throw for newindex. */ | 884 | return; /* Interpreter will throw for newindex. */ |
814 | } else if (ctype_isbitfield(fct->info)) { | 885 | } else if (ctype_isbitfield(fct->info)) { |
815 | lj_trace_err(J, LJ_TRERR_NYICONV); | 886 | if (ofs) |
887 | ptr = emitir(IRT(IR_ADD, IRT_PTR), ptr, lj_ir_kintp(J, ofs)); | ||
888 | crec_index_bf(J, rd, ptr, fct->info); | ||
889 | return; | ||
816 | } else { | 890 | } else { |
817 | lua_assert(ctype_isfield(fct->info)); | 891 | lj_assertJ(ctype_isfield(fct->info), "field expected"); |
818 | sid = ctype_cid(fct->info); | 892 | sid = ctype_cid(fct->info); |
819 | } | 893 | } |
820 | ofs += (ptrdiff_t)fofs; | ||
821 | } | 894 | } |
822 | } else if (ctype_iscomplex(ct->info)) { | 895 | } else if (ctype_iscomplex(ct->info)) { |
823 | if (name->len == 2 && | 896 | if (name->len == 2 && |
@@ -867,21 +940,17 @@ again: | |||
867 | } | 940 | } |
868 | 941 | ||
869 | /* Record setting a finalizer. */ | 942 | /* Record setting a finalizer. */ |
870 | static void crec_finalizer(jit_State *J, TRef trcd, cTValue *fin) | 943 | static void crec_finalizer(jit_State *J, TRef trcd, TRef trfin, cTValue *fin) |
871 | { | 944 | { |
872 | TRef trlo = lj_ir_call(J, IRCALL_lj_cdata_setfin, trcd); | 945 | if (tvisgcv(fin)) { |
873 | TRef trhi = emitir(IRT(IR_ADD, IRT_P32), trlo, lj_ir_kint(J, 4)); | 946 | if (!trfin) trfin = lj_ir_kptr(J, gcval(fin)); |
874 | if (LJ_BE) { TRef tmp = trlo; trlo = trhi; trhi = tmp; } | 947 | } else if (tvisnil(fin)) { |
875 | if (tvisfunc(fin)) { | 948 | trfin = lj_ir_kptr(J, NULL); |
876 | emitir(IRT(IR_XSTORE, IRT_P32), trlo, lj_ir_kfunc(J, funcV(fin))); | ||
877 | emitir(IRTI(IR_XSTORE), trhi, lj_ir_kint(J, LJ_TFUNC)); | ||
878 | } else if (tviscdata(fin)) { | ||
879 | emitir(IRT(IR_XSTORE, IRT_P32), trlo, | ||
880 | lj_ir_kgc(J, obj2gco(cdataV(fin)), IRT_CDATA)); | ||
881 | emitir(IRTI(IR_XSTORE), trhi, lj_ir_kint(J, LJ_TCDATA)); | ||
882 | } else { | 949 | } else { |
883 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 950 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
884 | } | 951 | } |
952 | lj_ir_call(J, IRCALL_lj_cdata_setfin, trcd, | ||
953 | trfin, lj_ir_kint(J, (int32_t)itype(fin))); | ||
885 | J->needsnap = 1; | 954 | J->needsnap = 1; |
886 | } | 955 | } |
887 | 956 | ||
@@ -892,10 +961,8 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
892 | CTSize sz; | 961 | CTSize sz; |
893 | CTInfo info = lj_ctype_info(cts, id, &sz); | 962 | CTInfo info = lj_ctype_info(cts, id, &sz); |
894 | CType *d = ctype_raw(cts, id); | 963 | CType *d = ctype_raw(cts, id); |
895 | TRef trid; | 964 | TRef trcd, trid = lj_ir_kint(J, id); |
896 | if (!sz || sz > 128 || (info & CTF_VLA) || ctype_align(info) > CT_MEMALIGN) | 965 | cTValue *fin; |
897 | lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: large/special allocations. */ | ||
898 | trid = lj_ir_kint(J, id); | ||
899 | /* Use special instruction to box pointer or 32/64 bit integer. */ | 966 | /* Use special instruction to box pointer or 32/64 bit integer. */ |
900 | if (ctype_isptr(info) || (ctype_isinteger(info) && (sz == 4 || sz == 8))) { | 967 | if (ctype_isptr(info) || (ctype_isinteger(info) && (sz == 4 || sz == 8))) { |
901 | TRef sp = J->base[1] ? crec_ct_tv(J, d, 0, J->base[1], &rd->argv[1]) : | 968 | TRef sp = J->base[1] ? crec_ct_tv(J, d, 0, J->base[1], &rd->argv[1]) : |
@@ -903,11 +970,36 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
903 | sz == 4 ? lj_ir_kint(J, 0) : | 970 | sz == 4 ? lj_ir_kint(J, 0) : |
904 | (lj_needsplit(J), lj_ir_kint64(J, 0)); | 971 | (lj_needsplit(J), lj_ir_kint64(J, 0)); |
905 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp); | 972 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp); |
973 | return; | ||
906 | } else { | 974 | } else { |
907 | TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL); | 975 | TRef trsz = TREF_NIL; |
908 | cTValue *fin; | 976 | if ((info & CTF_VLA)) { /* Calculate VLA/VLS size at runtime. */ |
909 | J->base[0] = trcd; | 977 | CTSize sz0, sz1; |
910 | if (J->base[1] && !J->base[2] && | 978 | if (!J->base[1] || J->base[2]) |
979 | lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init VLA/VLS. */ | ||
980 | trsz = crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0, | ||
981 | J->base[1], &rd->argv[1]); | ||
982 | sz0 = lj_ctype_vlsize(cts, d, 0); | ||
983 | sz1 = lj_ctype_vlsize(cts, d, 1); | ||
984 | trsz = emitir(IRTGI(IR_MULOV), trsz, lj_ir_kint(J, (int32_t)(sz1-sz0))); | ||
985 | trsz = emitir(IRTGI(IR_ADDOV), trsz, lj_ir_kint(J, (int32_t)sz0)); | ||
986 | J->base[1] = 0; /* Simplify logic below. */ | ||
987 | } else if (ctype_align(info) > CT_MEMALIGN) { | ||
988 | trsz = lj_ir_kint(J, sz); | ||
989 | } | ||
990 | trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, trsz); | ||
991 | if (sz > 128 || (info & CTF_VLA)) { | ||
992 | TRef dp; | ||
993 | CTSize align; | ||
994 | special: /* Only handle bulk zero-fill for large/VLA/VLS types. */ | ||
995 | if (J->base[1]) | ||
996 | lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init large/VLA/VLS types. */ | ||
997 | dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, lj_ir_kintp(J, sizeof(GCcdata))); | ||
998 | if (trsz == TREF_NIL) trsz = lj_ir_kint(J, sz); | ||
999 | align = ctype_align(info); | ||
1000 | if (align < CT_MEMALIGN) align = CT_MEMALIGN; | ||
1001 | crec_fill(J, dp, trsz, lj_ir_kint(J, 0), (1u << align)); | ||
1002 | } else if (J->base[1] && !J->base[2] && | ||
911 | !lj_cconv_multi_init(cts, d, &rd->argv[1])) { | 1003 | !lj_cconv_multi_init(cts, d, &rd->argv[1])) { |
912 | goto single_init; | 1004 | goto single_init; |
913 | } else if (ctype_isarray(d->info)) { | 1005 | } else if (ctype_isarray(d->info)) { |
@@ -918,8 +1010,9 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
918 | TValue *sval = &tv; | 1010 | TValue *sval = &tv; |
919 | MSize i; | 1011 | MSize i; |
920 | tv.u64 = 0; | 1012 | tv.u64 = 0; |
921 | if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info))) | 1013 | if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info)) || |
922 | lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init array of aggregates. */ | 1014 | esize * CREC_FILL_MAXUNROLL < sz) |
1015 | goto special; | ||
923 | for (i = 1, ofs = 0; ofs < sz; ofs += esize) { | 1016 | for (i = 1, ofs = 0; ofs < sz; ofs += esize) { |
924 | TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, | 1017 | TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, |
925 | lj_ir_kintp(J, ofs + sizeof(GCcdata))); | 1018 | lj_ir_kintp(J, ofs + sizeof(GCcdata))); |
@@ -933,8 +1026,26 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
933 | crec_ct_tv(J, dc, dp, sp, sval); | 1026 | crec_ct_tv(J, dc, dp, sp, sval); |
934 | } | 1027 | } |
935 | } else if (ctype_isstruct(d->info)) { | 1028 | } else if (ctype_isstruct(d->info)) { |
936 | CTypeID fid = d->sib; | 1029 | CTypeID fid; |
937 | MSize i = 1; | 1030 | MSize i = 1; |
1031 | if (!J->base[1]) { /* Handle zero-fill of struct-of-NYI. */ | ||
1032 | fid = d->sib; | ||
1033 | while (fid) { | ||
1034 | CType *df = ctype_get(cts, fid); | ||
1035 | fid = df->sib; | ||
1036 | if (ctype_isfield(df->info)) { | ||
1037 | CType *dc; | ||
1038 | if (!gcref(df->name)) continue; /* Ignore unnamed fields. */ | ||
1039 | dc = ctype_rawchild(cts, df); /* Field type. */ | ||
1040 | if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info) || | ||
1041 | ctype_isenum(dc->info))) | ||
1042 | goto special; | ||
1043 | } else if (!ctype_isconstval(df->info)) { | ||
1044 | goto special; | ||
1045 | } | ||
1046 | } | ||
1047 | } | ||
1048 | fid = d->sib; | ||
938 | while (fid) { | 1049 | while (fid) { |
939 | CType *df = ctype_get(cts, fid); | 1050 | CType *df = ctype_get(cts, fid); |
940 | fid = df->sib; | 1051 | fid = df->sib; |
@@ -981,11 +1092,12 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
981 | crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv); | 1092 | crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv); |
982 | } | 1093 | } |
983 | } | 1094 | } |
984 | /* Handle __gc metamethod. */ | ||
985 | fin = lj_ctype_meta(cts, id, MM_gc); | ||
986 | if (fin) | ||
987 | crec_finalizer(J, trcd, fin); | ||
988 | } | 1095 | } |
1096 | J->base[0] = trcd; | ||
1097 | /* Handle __gc metamethod. */ | ||
1098 | fin = lj_ctype_meta(cts, id, MM_gc); | ||
1099 | if (fin) | ||
1100 | crec_finalizer(J, trcd, 0, fin); | ||
989 | } | 1101 | } |
990 | 1102 | ||
991 | /* Record argument conversions. */ | 1103 | /* Record argument conversions. */ |
@@ -1026,7 +1138,7 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd, | |||
1026 | if (fid) { /* Get argument type from field. */ | 1138 | if (fid) { /* Get argument type from field. */ |
1027 | CType *ctf = ctype_get(cts, fid); | 1139 | CType *ctf = ctype_get(cts, fid); |
1028 | fid = ctf->sib; | 1140 | fid = ctf->sib; |
1029 | lua_assert(ctype_isfield(ctf->info)); | 1141 | lj_assertJ(ctype_isfield(ctf->info), "field expected"); |
1030 | did = ctype_cid(ctf->info); | 1142 | did = ctype_cid(ctf->info); |
1031 | } else { | 1143 | } else { |
1032 | if (!(ct->info & CTF_VARARG)) | 1144 | if (!(ct->info & CTF_VARARG)) |
@@ -1045,7 +1157,7 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd, | |||
1045 | else | 1157 | else |
1046 | tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_I8 : IRT_I16,IRCONV_SEXT); | 1158 | tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_I8 : IRT_I16,IRCONV_SEXT); |
1047 | } | 1159 | } |
1048 | } else if (LJ_SOFTFP && ctype_isfp(d->info) && d->size > 4) { | 1160 | } else if (LJ_SOFTFP32 && ctype_isfp(d->info) && d->size > 4) { |
1049 | lj_needsplit(J); | 1161 | lj_needsplit(J); |
1050 | } | 1162 | } |
1051 | #if LJ_TARGET_X86 | 1163 | #if LJ_TARGET_X86 |
@@ -1091,20 +1203,20 @@ static void crec_snap_caller(jit_State *J) | |||
1091 | lua_State *L = J->L; | 1203 | lua_State *L = J->L; |
1092 | TValue *base = L->base, *top = L->top; | 1204 | TValue *base = L->base, *top = L->top; |
1093 | const BCIns *pc = J->pc; | 1205 | const BCIns *pc = J->pc; |
1094 | TRef ftr = J->base[-1]; | 1206 | TRef ftr = J->base[-1-LJ_FR2]; |
1095 | ptrdiff_t delta; | 1207 | ptrdiff_t delta; |
1096 | if (!frame_islua(base-1) || J->framedepth <= 0) | 1208 | if (!frame_islua(base-1) || J->framedepth <= 0) |
1097 | lj_trace_err(J, LJ_TRERR_NYICALL); | 1209 | lj_trace_err(J, LJ_TRERR_NYICALL); |
1098 | J->pc = frame_pc(base-1); delta = 1+bc_a(J->pc[-1]); | 1210 | J->pc = frame_pc(base-1); delta = 1+LJ_FR2+bc_a(J->pc[-1]); |
1099 | L->top = base; L->base = base - delta; | 1211 | L->top = base; L->base = base - delta; |
1100 | J->base[-1] = TREF_FALSE; | 1212 | J->base[-1-LJ_FR2] = TREF_FALSE; |
1101 | J->base -= delta; J->baseslot -= (BCReg)delta; | 1213 | J->base -= delta; J->baseslot -= (BCReg)delta; |
1102 | J->maxslot = (BCReg)delta; J->framedepth--; | 1214 | J->maxslot = (BCReg)delta-LJ_FR2; J->framedepth--; |
1103 | lj_snap_add(J); | 1215 | lj_snap_add(J); |
1104 | L->base = base; L->top = top; | 1216 | L->base = base; L->top = top; |
1105 | J->framedepth++; J->maxslot = 1; | 1217 | J->framedepth++; J->maxslot = 1; |
1106 | J->base += delta; J->baseslot += (BCReg)delta; | 1218 | J->base += delta; J->baseslot += (BCReg)delta; |
1107 | J->base[-1] = ftr; J->pc = pc; | 1219 | J->base[-1-LJ_FR2] = ftr; J->pc = pc; |
1108 | } | 1220 | } |
1109 | 1221 | ||
1110 | /* Record function call. */ | 1222 | /* Record function call. */ |
@@ -1124,8 +1236,7 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) | |||
1124 | TRef tr; | 1236 | TRef tr; |
1125 | TValue tv; | 1237 | TValue tv; |
1126 | /* Check for blacklisted C functions that might call a callback. */ | 1238 | /* Check for blacklisted C functions that might call a callback. */ |
1127 | setlightudV(&tv, | 1239 | tv.u64 = ((uintptr_t)cdata_getptr(cdataptr(cd), (LJ_64 && tp == IRT_P64) ? 8 : 4) >> 2) | U64x(800000000, 00000000); |
1128 | cdata_getptr(cdataptr(cd), (LJ_64 && tp == IRT_P64) ? 8 : 4)); | ||
1129 | if (tvistrue(lj_tab_get(J->L, cts->miscmap, &tv))) | 1240 | if (tvistrue(lj_tab_get(J->L, cts->miscmap, &tv))) |
1130 | lj_trace_err(J, LJ_TRERR_BLACKL); | 1241 | lj_trace_err(J, LJ_TRERR_BLACKL); |
1131 | if (ctype_isvoid(ctr->info)) { | 1242 | if (ctype_isvoid(ctr->info)) { |
@@ -1196,8 +1307,7 @@ void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd) | |||
1196 | tv = lj_ctype_meta(cts, ctype_isptr(ct->info) ? ctype_cid(ct->info) : id, mm); | 1307 | tv = lj_ctype_meta(cts, ctype_isptr(ct->info) ? ctype_cid(ct->info) : id, mm); |
1197 | if (tv) { | 1308 | if (tv) { |
1198 | if (tvisfunc(tv)) { | 1309 | if (tvisfunc(tv)) { |
1199 | J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME; | 1310 | crec_tailcall(J, rd, tv); |
1200 | rd->nres = -1; /* Pending tailcall. */ | ||
1201 | return; | 1311 | return; |
1202 | } | 1312 | } |
1203 | } else if (mm == MM_new) { | 1313 | } else if (mm == MM_new) { |
@@ -1238,7 +1348,7 @@ static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm) | |||
1238 | for (i = 0; i < 2; i++) { | 1348 | for (i = 0; i < 2; i++) { |
1239 | IRType st = tref_type(sp[i]); | 1349 | IRType st = tref_type(sp[i]); |
1240 | if (st == IRT_NUM || st == IRT_FLOAT) | 1350 | if (st == IRT_NUM || st == IRT_FLOAT) |
1241 | sp[i] = emitconv(sp[i], dt, st, IRCONV_TRUNC|IRCONV_ANY); | 1351 | sp[i] = emitconv(sp[i], dt, st, IRCONV_ANY); |
1242 | else if (!(st == IRT_I64 || st == IRT_U64)) | 1352 | else if (!(st == IRT_I64 || st == IRT_U64)) |
1243 | sp[i] = emitconv(sp[i], dt, IRT_INT, | 1353 | sp[i] = emitconv(sp[i], dt, IRT_INT, |
1244 | (s[i]->info & CTF_UNSIGNED) ? 0 : IRCONV_SEXT); | 1354 | (s[i]->info & CTF_UNSIGNED) ? 0 : IRCONV_SEXT); |
@@ -1307,15 +1417,14 @@ static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm) | |||
1307 | CTypeID id; | 1417 | CTypeID id; |
1308 | #if LJ_64 | 1418 | #if LJ_64 |
1309 | if (t == IRT_NUM || t == IRT_FLOAT) | 1419 | if (t == IRT_NUM || t == IRT_FLOAT) |
1310 | tr = emitconv(tr, IRT_INTP, t, IRCONV_TRUNC|IRCONV_ANY); | 1420 | tr = emitconv(tr, IRT_INTP, t, IRCONV_ANY); |
1311 | else if (!(t == IRT_I64 || t == IRT_U64)) | 1421 | else if (!(t == IRT_I64 || t == IRT_U64)) |
1312 | tr = emitconv(tr, IRT_INTP, IRT_INT, | 1422 | tr = emitconv(tr, IRT_INTP, IRT_INT, |
1313 | ((t - IRT_I8) & 1) ? 0 : IRCONV_SEXT); | 1423 | ((t - IRT_I8) & 1) ? 0 : IRCONV_SEXT); |
1314 | #else | 1424 | #else |
1315 | if (!tref_typerange(sp[1], IRT_I8, IRT_U32)) { | 1425 | if (!tref_typerange(sp[1], IRT_I8, IRT_U32)) { |
1316 | tr = emitconv(tr, IRT_INTP, t, | 1426 | tr = emitconv(tr, IRT_INTP, t, |
1317 | (t == IRT_NUM || t == IRT_FLOAT) ? | 1427 | (t == IRT_NUM || t == IRT_FLOAT) ? IRCONV_ANY : 0); |
1318 | IRCONV_TRUNC|IRCONV_ANY : 0); | ||
1319 | } | 1428 | } |
1320 | #endif | 1429 | #endif |
1321 | tr = emitir(IRT(IR_MUL, IRT_INTP), tr, lj_ir_kintp(J, sz)); | 1430 | tr = emitir(IRT(IR_MUL, IRT_INTP), tr, lj_ir_kintp(J, sz)); |
@@ -1347,8 +1456,7 @@ static TRef crec_arith_meta(jit_State *J, TRef *sp, CType **s, CTState *cts, | |||
1347 | } | 1456 | } |
1348 | if (tv) { | 1457 | if (tv) { |
1349 | if (tvisfunc(tv)) { | 1458 | if (tvisfunc(tv)) { |
1350 | J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME; | 1459 | crec_tailcall(J, rd, tv); |
1351 | rd->nres = -1; /* Pending tailcall. */ | ||
1352 | return 0; | 1460 | return 0; |
1353 | } /* NYI: non-function metamethods. */ | 1461 | } /* NYI: non-function metamethods. */ |
1354 | } else if ((MMS)rd->data == MM_eq) { /* Fallback cdata pointer comparison. */ | 1462 | } else if ((MMS)rd->data == MM_eq) { /* Fallback cdata pointer comparison. */ |
@@ -1460,8 +1568,7 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd) | |||
1460 | !irt_isguard(J->guardemit)) { | 1568 | !irt_isguard(J->guardemit)) { |
1461 | const BCIns *pc = frame_contpc(J->L->base-1) - 1; | 1569 | const BCIns *pc = frame_contpc(J->L->base-1) - 1; |
1462 | if (bc_op(*pc) <= BC_ISNEP) { | 1570 | if (bc_op(*pc) <= BC_ISNEP) { |
1463 | setframe_pc(&J2G(J)->tmptv, pc); | 1571 | J2G(J)->tmptv.u64 = (uint64_t)(uintptr_t)pc; |
1464 | J2G(J)->tmptv.u32.lo = ((tref_istrue(tr) ^ bc_op(*pc)) & 1); | ||
1465 | J->postproc = LJ_POST_FIXCOMP; | 1572 | J->postproc = LJ_POST_FIXCOMP; |
1466 | } | 1573 | } |
1467 | } | 1574 | } |
@@ -1650,7 +1757,139 @@ void LJ_FASTCALL recff_ffi_xof(jit_State *J, RecordFFData *rd) | |||
1650 | void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd) | 1757 | void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd) |
1651 | { | 1758 | { |
1652 | argv2cdata(J, J->base[0], &rd->argv[0]); | 1759 | argv2cdata(J, J->base[0], &rd->argv[0]); |
1653 | crec_finalizer(J, J->base[0], &rd->argv[1]); | 1760 | if (!J->base[1]) |
1761 | lj_trace_err(J, LJ_TRERR_BADTYPE); | ||
1762 | crec_finalizer(J, J->base[0], J->base[1], &rd->argv[1]); | ||
1763 | } | ||
1764 | |||
1765 | /* -- 64 bit bit.* library functions -------------------------------------- */ | ||
1766 | |||
1767 | /* Determine bit operation type from argument type. */ | ||
1768 | static CTypeID crec_bit64_type(CTState *cts, cTValue *tv) | ||
1769 | { | ||
1770 | if (tviscdata(tv)) { | ||
1771 | CType *ct = lj_ctype_rawref(cts, cdataV(tv)->ctypeid); | ||
1772 | if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); | ||
1773 | if ((ct->info & (CTMASK_NUM|CTF_BOOL|CTF_FP|CTF_UNSIGNED)) == | ||
1774 | CTINFO(CT_NUM, CTF_UNSIGNED) && ct->size == 8) | ||
1775 | return CTID_UINT64; /* Use uint64_t, since it has the highest rank. */ | ||
1776 | return CTID_INT64; /* Otherwise use int64_t. */ | ||
1777 | } | ||
1778 | return 0; /* Use regular 32 bit ops. */ | ||
1779 | } | ||
1780 | |||
1781 | void LJ_FASTCALL recff_bit64_tobit(jit_State *J, RecordFFData *rd) | ||
1782 | { | ||
1783 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1784 | TRef tr = crec_ct_tv(J, ctype_get(cts, CTID_INT64), 0, | ||
1785 | J->base[0], &rd->argv[0]); | ||
1786 | if (!tref_isinteger(tr)) | ||
1787 | tr = emitconv(tr, IRT_INT, tref_type(tr), 0); | ||
1788 | J->base[0] = tr; | ||
1789 | } | ||
1790 | |||
1791 | int LJ_FASTCALL recff_bit64_unary(jit_State *J, RecordFFData *rd) | ||
1792 | { | ||
1793 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1794 | CTypeID id = crec_bit64_type(cts, &rd->argv[0]); | ||
1795 | if (id) { | ||
1796 | TRef tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]); | ||
1797 | tr = emitir(IRT(rd->data, id-CTID_INT64+IRT_I64), tr, 0); | ||
1798 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
1799 | return 1; | ||
1800 | } | ||
1801 | return 0; | ||
1802 | } | ||
1803 | |||
1804 | int LJ_FASTCALL recff_bit64_nary(jit_State *J, RecordFFData *rd) | ||
1805 | { | ||
1806 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1807 | CTypeID id = 0; | ||
1808 | MSize i; | ||
1809 | for (i = 0; J->base[i] != 0; i++) { | ||
1810 | CTypeID aid = crec_bit64_type(cts, &rd->argv[i]); | ||
1811 | if (id < aid) id = aid; /* Determine highest type rank of all arguments. */ | ||
1812 | } | ||
1813 | if (id) { | ||
1814 | CType *ct = ctype_get(cts, id); | ||
1815 | uint32_t ot = IRT(rd->data, id-CTID_INT64+IRT_I64); | ||
1816 | TRef tr = crec_ct_tv(J, ct, 0, J->base[0], &rd->argv[0]); | ||
1817 | for (i = 1; J->base[i] != 0; i++) { | ||
1818 | TRef tr2 = crec_ct_tv(J, ct, 0, J->base[i], &rd->argv[i]); | ||
1819 | tr = emitir(ot, tr, tr2); | ||
1820 | } | ||
1821 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
1822 | return 1; | ||
1823 | } | ||
1824 | return 0; | ||
1825 | } | ||
1826 | |||
1827 | int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd) | ||
1828 | { | ||
1829 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1830 | CTypeID id; | ||
1831 | TRef tsh = 0; | ||
1832 | if (J->base[0] && tref_iscdata(J->base[1])) { | ||
1833 | tsh = crec_ct_tv(J, ctype_get(cts, CTID_INT64), 0, | ||
1834 | J->base[1], &rd->argv[1]); | ||
1835 | if (!tref_isinteger(tsh)) | ||
1836 | tsh = emitconv(tsh, IRT_INT, tref_type(tsh), 0); | ||
1837 | J->base[1] = tsh; | ||
1838 | } | ||
1839 | id = crec_bit64_type(cts, &rd->argv[0]); | ||
1840 | if (id) { | ||
1841 | TRef tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]); | ||
1842 | uint32_t op = rd->data; | ||
1843 | if (!tsh) tsh = lj_opt_narrow_tobit(J, J->base[1]); | ||
1844 | if (!(op < IR_BROL ? LJ_TARGET_MASKSHIFT : LJ_TARGET_MASKROT) && | ||
1845 | !tref_isk(tsh)) | ||
1846 | tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 63)); | ||
1847 | #ifdef LJ_TARGET_UNIFYROT | ||
1848 | if (op == (LJ_TARGET_UNIFYROT == 1 ? IR_BROR : IR_BROL)) { | ||
1849 | op = LJ_TARGET_UNIFYROT == 1 ? IR_BROL : IR_BROR; | ||
1850 | tsh = emitir(IRTI(IR_NEG), tsh, tsh); | ||
1851 | } | ||
1852 | #endif | ||
1853 | tr = emitir(IRT(op, id-CTID_INT64+IRT_I64), tr, tsh); | ||
1854 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
1855 | return 1; | ||
1856 | } | ||
1857 | return 0; | ||
1858 | } | ||
1859 | |||
1860 | TRef recff_bit64_tohex(jit_State *J, RecordFFData *rd, TRef hdr) | ||
1861 | { | ||
1862 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1863 | CTypeID id = crec_bit64_type(cts, &rd->argv[0]); | ||
1864 | TRef tr, trsf = J->base[1]; | ||
1865 | SFormat sf = (STRFMT_UINT|STRFMT_T_HEX); | ||
1866 | int32_t n; | ||
1867 | if (trsf) { | ||
1868 | CTypeID id2 = 0; | ||
1869 | n = (int32_t)lj_carith_check64(J->L, 2, &id2); | ||
1870 | if (id2) | ||
1871 | trsf = crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0, trsf, &rd->argv[1]); | ||
1872 | else | ||
1873 | trsf = lj_opt_narrow_tobit(J, trsf); | ||
1874 | emitir(IRTGI(IR_EQ), trsf, lj_ir_kint(J, n)); /* Specialize to n. */ | ||
1875 | } else { | ||
1876 | n = id ? 16 : 8; | ||
1877 | } | ||
1878 | if (n < 0) { n = -n; sf |= STRFMT_F_UPPER; } | ||
1879 | sf |= ((SFormat)((n+1)&255) << STRFMT_SH_PREC); | ||
1880 | if (id) { | ||
1881 | tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]); | ||
1882 | if (n < 16) | ||
1883 | tr = emitir(IRT(IR_BAND, IRT_U64), tr, | ||
1884 | lj_ir_kint64(J, ((uint64_t)1 << 4*n)-1)); | ||
1885 | } else { | ||
1886 | tr = lj_opt_narrow_tobit(J, J->base[0]); | ||
1887 | if (n < 8) | ||
1888 | tr = emitir(IRTI(IR_BAND), tr, lj_ir_kint(J, (int32_t)((1u << 4*n)-1))); | ||
1889 | tr = emitconv(tr, IRT_U64, IRT_INT, 0); /* No sign-extension. */ | ||
1890 | lj_needsplit(J); | ||
1891 | } | ||
1892 | return lj_ir_call(J, IRCALL_lj_strfmt_putfxint, hdr, lj_ir_kint(J, sf), tr); | ||
1654 | } | 1893 | } |
1655 | 1894 | ||
1656 | /* -- Miscellaneous library functions ------------------------------------- */ | 1895 | /* -- Miscellaneous library functions ------------------------------------- */ |
@@ -1674,6 +1913,30 @@ void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd) | |||
1674 | } | 1913 | } |
1675 | } | 1914 | } |
1676 | 1915 | ||
1916 | TRef lj_crecord_loadiu64(jit_State *J, TRef tr, cTValue *o) | ||
1917 | { | ||
1918 | CTypeID id = argv2cdata(J, tr, o)->ctypeid; | ||
1919 | if (!(id == CTID_INT64 || id == CTID_UINT64)) | ||
1920 | lj_trace_err(J, LJ_TRERR_BADTYPE); | ||
1921 | lj_needsplit(J); | ||
1922 | return emitir(IRT(IR_FLOAD, id == CTID_INT64 ? IRT_I64 : IRT_U64), tr, | ||
1923 | IRFL_CDATA_INT64); | ||
1924 | } | ||
1925 | |||
1926 | #if LJ_HASBUFFER | ||
1927 | TRef lj_crecord_topcvoid(jit_State *J, TRef tr, cTValue *o) | ||
1928 | { | ||
1929 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1930 | if (!tref_iscdata(tr)) lj_trace_err(J, LJ_TRERR_BADTYPE); | ||
1931 | return crec_ct_tv(J, ctype_get(cts, CTID_P_CVOID), 0, tr, o); | ||
1932 | } | ||
1933 | |||
1934 | TRef lj_crecord_topuint8(jit_State *J, TRef tr) | ||
1935 | { | ||
1936 | return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, CTID_P_UINT8), tr); | ||
1937 | } | ||
1938 | #endif | ||
1939 | |||
1677 | #undef IR | 1940 | #undef IR |
1678 | #undef emitir | 1941 | #undef emitir |
1679 | #undef emitconv | 1942 | #undef emitconv |