diff options
Diffstat (limited to 'src/lj_crecord.c')
-rw-r--r-- | src/lj_crecord.c | 322 |
1 files changed, 270 insertions, 52 deletions
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 99344b79..6e999cc9 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)]) |
@@ -211,7 +212,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); | 212 | ml[i].trval = emitir(IRT(IR_XLOAD, ml[i].tp), trsptr, 0); |
212 | ml[i].trofs = trofs; | 213 | ml[i].trofs = trofs; |
213 | i++; | 214 | i++; |
214 | rwin += (LJ_SOFTFP && ml[i].tp == IRT_NUM) ? 2 : 1; | 215 | rwin += (LJ_SOFTFP32 && ml[i].tp == IRT_NUM) ? 2 : 1; |
215 | if (rwin >= CREC_COPY_REGWIN || i >= mlp) { /* Flush buffered stores. */ | 216 | if (rwin >= CREC_COPY_REGWIN || i >= mlp) { /* Flush buffered stores. */ |
216 | rwin = 0; | 217 | rwin = 0; |
217 | for ( ; j < i; j++) { | 218 | for ( ; j < i; j++) { |
@@ -441,7 +442,7 @@ static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp, | |||
441 | /* fallthrough */ | 442 | /* fallthrough */ |
442 | case CCX(I, F): | 443 | case CCX(I, F): |
443 | if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi; | 444 | if (dt == IRT_CDATA || st == IRT_CDATA) goto err_nyi; |
444 | sp = emitconv(sp, dsize < 4 ? IRT_INT : dt, st, IRCONV_TRUNC|IRCONV_ANY); | 445 | sp = emitconv(sp, dsize < 4 ? IRT_INT : dt, st, IRCONV_ANY); |
445 | goto xstore; | 446 | goto xstore; |
446 | case CCX(I, P): | 447 | case CCX(I, P): |
447 | case CCX(I, A): | 448 | case CCX(I, A): |
@@ -521,7 +522,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; | 522 | if (st == IRT_CDATA) goto err_nyi; |
522 | /* The signed conversion is cheaper. x64 really has 47 bit pointers. */ | 523 | /* The signed conversion is cheaper. x64 really has 47 bit pointers. */ |
523 | sp = emitconv(sp, (LJ_64 && dsize == 8) ? IRT_I64 : IRT_U32, | 524 | sp = emitconv(sp, (LJ_64 && dsize == 8) ? IRT_I64 : IRT_U32, |
524 | st, IRCONV_TRUNC|IRCONV_ANY); | 525 | st, IRCONV_ANY); |
525 | goto xstore; | 526 | goto xstore; |
526 | 527 | ||
527 | /* Destination is an array. */ | 528 | /* Destination is an array. */ |
@@ -640,12 +641,23 @@ 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))); | 641 | sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCstr))); |
641 | sid = CTID_A_CCHAR; | 642 | sid = CTID_A_CCHAR; |
642 | } | 643 | } |
643 | } else { /* NYI: tref_istab(sp), tref_islightud(sp). */ | 644 | } else if (tref_islightud(sp)) { |
645 | #if LJ_64 | ||
646 | sp = emitir(IRT(IR_BAND, IRT_P64), sp, | ||
647 | lj_ir_kint64(J, U64x(00007fff,ffffffff))); | ||
648 | #endif | ||
649 | } else { /* NYI: tref_istab(sp). */ | ||
644 | IRType t; | 650 | IRType t; |
645 | sid = argv2cdata(J, sp, sval)->ctypeid; | 651 | sid = argv2cdata(J, sp, sval)->ctypeid; |
646 | s = ctype_raw(cts, sid); | 652 | s = ctype_raw(cts, sid); |
647 | svisnz = cdataptr(cdataV(sval)); | 653 | svisnz = cdataptr(cdataV(sval)); |
648 | t = crec_ct2irt(cts, s); | 654 | if (ctype_isfunc(s->info)) { |
655 | sid = lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|sid), CTSIZE_PTR); | ||
656 | s = ctype_get(cts, sid); | ||
657 | t = IRT_PTR; | ||
658 | } else { | ||
659 | t = crec_ct2irt(cts, s); | ||
660 | } | ||
649 | if (ctype_isptr(s->info)) { | 661 | if (ctype_isptr(s->info)) { |
650 | sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_PTR); | 662 | sp = emitir(IRT(IR_FLOAD, t), sp, IRFL_CDATA_PTR); |
651 | if (ctype_isref(s->info)) { | 663 | if (ctype_isref(s->info)) { |
@@ -700,6 +712,19 @@ static TRef crec_reassoc_ofs(jit_State *J, TRef tr, ptrdiff_t *ofsp, MSize sz) | |||
700 | return tr; | 712 | return tr; |
701 | } | 713 | } |
702 | 714 | ||
715 | /* Tailcall to function. */ | ||
716 | static void crec_tailcall(jit_State *J, RecordFFData *rd, cTValue *tv) | ||
717 | { | ||
718 | TRef kfunc = lj_ir_kfunc(J, funcV(tv)); | ||
719 | #if LJ_FR2 | ||
720 | J->base[-2] = kfunc; | ||
721 | J->base[-1] = TREF_FRAME; | ||
722 | #else | ||
723 | J->base[-1] = kfunc | TREF_FRAME; | ||
724 | #endif | ||
725 | rd->nres = -1; /* Pending tailcall. */ | ||
726 | } | ||
727 | |||
703 | /* Record ctype __index/__newindex metamethods. */ | 728 | /* Record ctype __index/__newindex metamethods. */ |
704 | static void crec_index_meta(jit_State *J, CTState *cts, CType *ct, | 729 | static void crec_index_meta(jit_State *J, CTState *cts, CType *ct, |
705 | RecordFFData *rd) | 730 | RecordFFData *rd) |
@@ -709,8 +734,7 @@ static void crec_index_meta(jit_State *J, CTState *cts, CType *ct, | |||
709 | if (!tv) | 734 | if (!tv) |
710 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 735 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
711 | if (tvisfunc(tv)) { | 736 | if (tvisfunc(tv)) { |
712 | J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME; | 737 | crec_tailcall(J, rd, tv); |
713 | rd->nres = -1; /* Pending tailcall. */ | ||
714 | } else if (rd->data == 0 && tvistab(tv) && tref_isstr(J->base[1])) { | 738 | } else if (rd->data == 0 && tvistab(tv) && tref_isstr(J->base[1])) { |
715 | /* Specialize to result of __index lookup. */ | 739 | /* Specialize to result of __index lookup. */ |
716 | cTValue *o = lj_tab_get(J->L, tabV(tv), &rd->argv[1]); | 740 | cTValue *o = lj_tab_get(J->L, tabV(tv), &rd->argv[1]); |
@@ -727,6 +751,48 @@ static void crec_index_meta(jit_State *J, CTState *cts, CType *ct, | |||
727 | } | 751 | } |
728 | } | 752 | } |
729 | 753 | ||
754 | /* Record bitfield load/store. */ | ||
755 | static void crec_index_bf(jit_State *J, RecordFFData *rd, TRef ptr, CTInfo info) | ||
756 | { | ||
757 | IRType t = IRT_I8 + 2*lj_fls(ctype_bitcsz(info)) + ((info&CTF_UNSIGNED)?1:0); | ||
758 | TRef tr = emitir(IRT(IR_XLOAD, t), ptr, 0); | ||
759 | CTSize pos = ctype_bitpos(info), bsz = ctype_bitbsz(info), shift = 32 - bsz; | ||
760 | lua_assert(t <= IRT_U32); /* NYI: 64 bit bitfields. */ | ||
761 | if (rd->data == 0) { /* __index metamethod. */ | ||
762 | if ((info & CTF_BOOL)) { | ||
763 | tr = emitir(IRTI(IR_BAND), tr, lj_ir_kint(J, (int32_t)((1u << pos)))); | ||
764 | /* Assume not equal to zero. Fixup and emit pending guard later. */ | ||
765 | lj_ir_set(J, IRTGI(IR_NE), tr, lj_ir_kint(J, 0)); | ||
766 | J->postproc = LJ_POST_FIXGUARD; | ||
767 | tr = TREF_TRUE; | ||
768 | } else if (!(info & CTF_UNSIGNED)) { | ||
769 | tr = emitir(IRTI(IR_BSHL), tr, lj_ir_kint(J, shift - pos)); | ||
770 | tr = emitir(IRTI(IR_BSAR), tr, lj_ir_kint(J, shift)); | ||
771 | } else { | ||
772 | lua_assert(bsz < 32); /* Full-size fields cannot end up here. */ | ||
773 | tr = emitir(IRTI(IR_BSHR), tr, lj_ir_kint(J, pos)); | ||
774 | tr = emitir(IRTI(IR_BAND), tr, lj_ir_kint(J, (int32_t)((1u << bsz)-1))); | ||
775 | /* We can omit the U32 to NUM conversion, since bsz < 32. */ | ||
776 | } | ||
777 | J->base[0] = tr; | ||
778 | } else { /* __newindex metamethod. */ | ||
779 | CTState *cts = ctype_ctsG(J2G(J)); | ||
780 | CType *ct = ctype_get(cts, | ||
781 | (info & CTF_BOOL) ? CTID_BOOL : | ||
782 | (info & CTF_UNSIGNED) ? CTID_UINT32 : CTID_INT32); | ||
783 | int32_t mask = (int32_t)(((1u << bsz)-1) << pos); | ||
784 | TRef sp = crec_ct_tv(J, ct, 0, J->base[2], &rd->argv[2]); | ||
785 | sp = emitir(IRTI(IR_BSHL), sp, lj_ir_kint(J, pos)); | ||
786 | /* Use of the target type avoids forwarding conversions. */ | ||
787 | sp = emitir(IRT(IR_BAND, t), sp, lj_ir_kint(J, mask)); | ||
788 | tr = emitir(IRT(IR_BAND, t), tr, lj_ir_kint(J, (int32_t)~mask)); | ||
789 | tr = emitir(IRT(IR_BOR, t), tr, sp); | ||
790 | emitir(IRT(IR_XSTORE, t), ptr, tr); | ||
791 | rd->nres = 0; | ||
792 | J->needsnap = 1; | ||
793 | } | ||
794 | } | ||
795 | |||
730 | void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd) | 796 | void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd) |
731 | { | 797 | { |
732 | TRef idx, ptr = J->base[0]; | 798 | TRef idx, ptr = J->base[0]; |
@@ -801,6 +867,7 @@ again: | |||
801 | CType *fct; | 867 | CType *fct; |
802 | fct = lj_ctype_getfield(cts, ct, name, &fofs); | 868 | fct = lj_ctype_getfield(cts, ct, name, &fofs); |
803 | if (fct) { | 869 | if (fct) { |
870 | ofs += (ptrdiff_t)fofs; | ||
804 | /* Always specialize to the field name. */ | 871 | /* Always specialize to the field name. */ |
805 | emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, name)); | 872 | emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, name)); |
806 | if (ctype_isconstval(fct->info)) { | 873 | if (ctype_isconstval(fct->info)) { |
@@ -812,12 +879,14 @@ again: | |||
812 | J->base[0] = lj_ir_kint(J, (int32_t)fct->size); | 879 | J->base[0] = lj_ir_kint(J, (int32_t)fct->size); |
813 | return; /* Interpreter will throw for newindex. */ | 880 | return; /* Interpreter will throw for newindex. */ |
814 | } else if (ctype_isbitfield(fct->info)) { | 881 | } else if (ctype_isbitfield(fct->info)) { |
815 | lj_trace_err(J, LJ_TRERR_NYICONV); | 882 | if (ofs) |
883 | ptr = emitir(IRT(IR_ADD, IRT_PTR), ptr, lj_ir_kintp(J, ofs)); | ||
884 | crec_index_bf(J, rd, ptr, fct->info); | ||
885 | return; | ||
816 | } else { | 886 | } else { |
817 | lua_assert(ctype_isfield(fct->info)); | 887 | lua_assert(ctype_isfield(fct->info)); |
818 | sid = ctype_cid(fct->info); | 888 | sid = ctype_cid(fct->info); |
819 | } | 889 | } |
820 | ofs += (ptrdiff_t)fofs; | ||
821 | } | 890 | } |
822 | } else if (ctype_iscomplex(ct->info)) { | 891 | } else if (ctype_iscomplex(ct->info)) { |
823 | if (name->len == 2 && | 892 | if (name->len == 2 && |
@@ -867,21 +936,17 @@ again: | |||
867 | } | 936 | } |
868 | 937 | ||
869 | /* Record setting a finalizer. */ | 938 | /* Record setting a finalizer. */ |
870 | static void crec_finalizer(jit_State *J, TRef trcd, cTValue *fin) | 939 | static void crec_finalizer(jit_State *J, TRef trcd, TRef trfin, cTValue *fin) |
871 | { | 940 | { |
872 | TRef trlo = lj_ir_call(J, IRCALL_lj_cdata_setfin, trcd); | 941 | if (tvisgcv(fin)) { |
873 | TRef trhi = emitir(IRT(IR_ADD, IRT_P32), trlo, lj_ir_kint(J, 4)); | 942 | if (!trfin) trfin = lj_ir_kptr(J, gcval(fin)); |
874 | if (LJ_BE) { TRef tmp = trlo; trlo = trhi; trhi = tmp; } | 943 | } else if (tvisnil(fin)) { |
875 | if (tvisfunc(fin)) { | 944 | 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 { | 945 | } else { |
883 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 946 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
884 | } | 947 | } |
948 | lj_ir_call(J, IRCALL_lj_cdata_setfin, trcd, | ||
949 | trfin, lj_ir_kint(J, (int32_t)itype(fin))); | ||
885 | J->needsnap = 1; | 950 | J->needsnap = 1; |
886 | } | 951 | } |
887 | 952 | ||
@@ -892,10 +957,8 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
892 | CTSize sz; | 957 | CTSize sz; |
893 | CTInfo info = lj_ctype_info(cts, id, &sz); | 958 | CTInfo info = lj_ctype_info(cts, id, &sz); |
894 | CType *d = ctype_raw(cts, id); | 959 | CType *d = ctype_raw(cts, id); |
895 | TRef trid; | 960 | TRef trcd, trid = lj_ir_kint(J, id); |
896 | if (!sz || sz > 128 || (info & CTF_VLA) || ctype_align(info) > CT_MEMALIGN) | 961 | 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. */ | 962 | /* Use special instruction to box pointer or 32/64 bit integer. */ |
900 | if (ctype_isptr(info) || (ctype_isinteger(info) && (sz == 4 || sz == 8))) { | 963 | 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]) : | 964 | TRef sp = J->base[1] ? crec_ct_tv(J, d, 0, J->base[1], &rd->argv[1]) : |
@@ -903,11 +966,36 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
903 | sz == 4 ? lj_ir_kint(J, 0) : | 966 | sz == 4 ? lj_ir_kint(J, 0) : |
904 | (lj_needsplit(J), lj_ir_kint64(J, 0)); | 967 | (lj_needsplit(J), lj_ir_kint64(J, 0)); |
905 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp); | 968 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp); |
969 | return; | ||
906 | } else { | 970 | } else { |
907 | TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL); | 971 | TRef trsz = TREF_NIL; |
908 | cTValue *fin; | 972 | if ((info & CTF_VLA)) { /* Calculate VLA/VLS size at runtime. */ |
909 | J->base[0] = trcd; | 973 | CTSize sz0, sz1; |
910 | if (J->base[1] && !J->base[2] && | 974 | if (!J->base[1] || J->base[2]) |
975 | lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init VLA/VLS. */ | ||
976 | trsz = crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0, | ||
977 | J->base[1], &rd->argv[1]); | ||
978 | sz0 = lj_ctype_vlsize(cts, d, 0); | ||
979 | sz1 = lj_ctype_vlsize(cts, d, 1); | ||
980 | trsz = emitir(IRTGI(IR_MULOV), trsz, lj_ir_kint(J, (int32_t)(sz1-sz0))); | ||
981 | trsz = emitir(IRTGI(IR_ADDOV), trsz, lj_ir_kint(J, (int32_t)sz0)); | ||
982 | J->base[1] = 0; /* Simplify logic below. */ | ||
983 | } else if (ctype_align(info) > CT_MEMALIGN) { | ||
984 | trsz = lj_ir_kint(J, sz); | ||
985 | } | ||
986 | trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, trsz); | ||
987 | if (sz > 128 || (info & CTF_VLA)) { | ||
988 | TRef dp; | ||
989 | CTSize align; | ||
990 | special: /* Only handle bulk zero-fill for large/VLA/VLS types. */ | ||
991 | if (J->base[1]) | ||
992 | lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init large/VLA/VLS types. */ | ||
993 | dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, lj_ir_kintp(J, sizeof(GCcdata))); | ||
994 | if (trsz == TREF_NIL) trsz = lj_ir_kint(J, sz); | ||
995 | align = ctype_align(info); | ||
996 | if (align < CT_MEMALIGN) align = CT_MEMALIGN; | ||
997 | crec_fill(J, dp, trsz, lj_ir_kint(J, 0), (1u << align)); | ||
998 | } else if (J->base[1] && !J->base[2] && | ||
911 | !lj_cconv_multi_init(cts, d, &rd->argv[1])) { | 999 | !lj_cconv_multi_init(cts, d, &rd->argv[1])) { |
912 | goto single_init; | 1000 | goto single_init; |
913 | } else if (ctype_isarray(d->info)) { | 1001 | } else if (ctype_isarray(d->info)) { |
@@ -918,8 +1006,9 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
918 | TValue *sval = &tv; | 1006 | TValue *sval = &tv; |
919 | MSize i; | 1007 | MSize i; |
920 | tv.u64 = 0; | 1008 | tv.u64 = 0; |
921 | if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info))) | 1009 | if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info)) || |
922 | lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init array of aggregates. */ | 1010 | esize * CREC_FILL_MAXUNROLL < sz) |
1011 | goto special; | ||
923 | for (i = 1, ofs = 0; ofs < sz; ofs += esize) { | 1012 | for (i = 1, ofs = 0; ofs < sz; ofs += esize) { |
924 | TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, | 1013 | TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, |
925 | lj_ir_kintp(J, ofs + sizeof(GCcdata))); | 1014 | lj_ir_kintp(J, ofs + sizeof(GCcdata))); |
@@ -976,11 +1065,12 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
976 | crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv); | 1065 | crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv); |
977 | } | 1066 | } |
978 | } | 1067 | } |
979 | /* Handle __gc metamethod. */ | ||
980 | fin = lj_ctype_meta(cts, id, MM_gc); | ||
981 | if (fin) | ||
982 | crec_finalizer(J, trcd, fin); | ||
983 | } | 1068 | } |
1069 | J->base[0] = trcd; | ||
1070 | /* Handle __gc metamethod. */ | ||
1071 | fin = lj_ctype_meta(cts, id, MM_gc); | ||
1072 | if (fin) | ||
1073 | crec_finalizer(J, trcd, 0, fin); | ||
984 | } | 1074 | } |
985 | 1075 | ||
986 | /* Record argument conversions. */ | 1076 | /* Record argument conversions. */ |
@@ -1040,7 +1130,7 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd, | |||
1040 | else | 1130 | else |
1041 | tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_I8 : IRT_I16,IRCONV_SEXT); | 1131 | tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_I8 : IRT_I16,IRCONV_SEXT); |
1042 | } | 1132 | } |
1043 | } else if (LJ_SOFTFP && ctype_isfp(d->info) && d->size > 4) { | 1133 | } else if (LJ_SOFTFP32 && ctype_isfp(d->info) && d->size > 4) { |
1044 | lj_needsplit(J); | 1134 | lj_needsplit(J); |
1045 | } | 1135 | } |
1046 | #if LJ_TARGET_X86 | 1136 | #if LJ_TARGET_X86 |
@@ -1086,20 +1176,20 @@ static void crec_snap_caller(jit_State *J) | |||
1086 | lua_State *L = J->L; | 1176 | lua_State *L = J->L; |
1087 | TValue *base = L->base, *top = L->top; | 1177 | TValue *base = L->base, *top = L->top; |
1088 | const BCIns *pc = J->pc; | 1178 | const BCIns *pc = J->pc; |
1089 | TRef ftr = J->base[-1]; | 1179 | TRef ftr = J->base[-1-LJ_FR2]; |
1090 | ptrdiff_t delta; | 1180 | ptrdiff_t delta; |
1091 | if (!frame_islua(base-1) || J->framedepth <= 0) | 1181 | if (!frame_islua(base-1) || J->framedepth <= 0) |
1092 | lj_trace_err(J, LJ_TRERR_NYICALL); | 1182 | lj_trace_err(J, LJ_TRERR_NYICALL); |
1093 | J->pc = frame_pc(base-1); delta = 1+bc_a(J->pc[-1]); | 1183 | J->pc = frame_pc(base-1); delta = 1+LJ_FR2+bc_a(J->pc[-1]); |
1094 | L->top = base; L->base = base - delta; | 1184 | L->top = base; L->base = base - delta; |
1095 | J->base[-1] = TREF_FALSE; | 1185 | J->base[-1-LJ_FR2] = TREF_FALSE; |
1096 | J->base -= delta; J->baseslot -= (BCReg)delta; | 1186 | J->base -= delta; J->baseslot -= (BCReg)delta; |
1097 | J->maxslot = (BCReg)delta; J->framedepth--; | 1187 | J->maxslot = (BCReg)delta-LJ_FR2; J->framedepth--; |
1098 | lj_snap_add(J); | 1188 | lj_snap_add(J); |
1099 | L->base = base; L->top = top; | 1189 | L->base = base; L->top = top; |
1100 | J->framedepth++; J->maxslot = 1; | 1190 | J->framedepth++; J->maxslot = 1; |
1101 | J->base += delta; J->baseslot += (BCReg)delta; | 1191 | J->base += delta; J->baseslot += (BCReg)delta; |
1102 | J->base[-1] = ftr; J->pc = pc; | 1192 | J->base[-1-LJ_FR2] = ftr; J->pc = pc; |
1103 | } | 1193 | } |
1104 | 1194 | ||
1105 | /* Record function call. */ | 1195 | /* Record function call. */ |
@@ -1191,8 +1281,7 @@ void LJ_FASTCALL recff_cdata_call(jit_State *J, RecordFFData *rd) | |||
1191 | tv = lj_ctype_meta(cts, ctype_isptr(ct->info) ? ctype_cid(ct->info) : id, mm); | 1281 | tv = lj_ctype_meta(cts, ctype_isptr(ct->info) ? ctype_cid(ct->info) : id, mm); |
1192 | if (tv) { | 1282 | if (tv) { |
1193 | if (tvisfunc(tv)) { | 1283 | if (tvisfunc(tv)) { |
1194 | J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME; | 1284 | crec_tailcall(J, rd, tv); |
1195 | rd->nres = -1; /* Pending tailcall. */ | ||
1196 | return; | 1285 | return; |
1197 | } | 1286 | } |
1198 | } else if (mm == MM_new) { | 1287 | } else if (mm == MM_new) { |
@@ -1233,7 +1322,7 @@ static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm) | |||
1233 | for (i = 0; i < 2; i++) { | 1322 | for (i = 0; i < 2; i++) { |
1234 | IRType st = tref_type(sp[i]); | 1323 | IRType st = tref_type(sp[i]); |
1235 | if (st == IRT_NUM || st == IRT_FLOAT) | 1324 | if (st == IRT_NUM || st == IRT_FLOAT) |
1236 | sp[i] = emitconv(sp[i], dt, st, IRCONV_TRUNC|IRCONV_ANY); | 1325 | sp[i] = emitconv(sp[i], dt, st, IRCONV_ANY); |
1237 | else if (!(st == IRT_I64 || st == IRT_U64)) | 1326 | else if (!(st == IRT_I64 || st == IRT_U64)) |
1238 | sp[i] = emitconv(sp[i], dt, IRT_INT, | 1327 | sp[i] = emitconv(sp[i], dt, IRT_INT, |
1239 | (s[i]->info & CTF_UNSIGNED) ? 0 : IRCONV_SEXT); | 1328 | (s[i]->info & CTF_UNSIGNED) ? 0 : IRCONV_SEXT); |
@@ -1302,15 +1391,14 @@ static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm) | |||
1302 | CTypeID id; | 1391 | CTypeID id; |
1303 | #if LJ_64 | 1392 | #if LJ_64 |
1304 | if (t == IRT_NUM || t == IRT_FLOAT) | 1393 | if (t == IRT_NUM || t == IRT_FLOAT) |
1305 | tr = emitconv(tr, IRT_INTP, t, IRCONV_TRUNC|IRCONV_ANY); | 1394 | tr = emitconv(tr, IRT_INTP, t, IRCONV_ANY); |
1306 | else if (!(t == IRT_I64 || t == IRT_U64)) | 1395 | else if (!(t == IRT_I64 || t == IRT_U64)) |
1307 | tr = emitconv(tr, IRT_INTP, IRT_INT, | 1396 | tr = emitconv(tr, IRT_INTP, IRT_INT, |
1308 | ((t - IRT_I8) & 1) ? 0 : IRCONV_SEXT); | 1397 | ((t - IRT_I8) & 1) ? 0 : IRCONV_SEXT); |
1309 | #else | 1398 | #else |
1310 | if (!tref_typerange(sp[1], IRT_I8, IRT_U32)) { | 1399 | if (!tref_typerange(sp[1], IRT_I8, IRT_U32)) { |
1311 | tr = emitconv(tr, IRT_INTP, t, | 1400 | tr = emitconv(tr, IRT_INTP, t, |
1312 | (t == IRT_NUM || t == IRT_FLOAT) ? | 1401 | (t == IRT_NUM || t == IRT_FLOAT) ? IRCONV_ANY : 0); |
1313 | IRCONV_TRUNC|IRCONV_ANY : 0); | ||
1314 | } | 1402 | } |
1315 | #endif | 1403 | #endif |
1316 | tr = emitir(IRT(IR_MUL, IRT_INTP), tr, lj_ir_kintp(J, sz)); | 1404 | tr = emitir(IRT(IR_MUL, IRT_INTP), tr, lj_ir_kintp(J, sz)); |
@@ -1342,8 +1430,7 @@ static TRef crec_arith_meta(jit_State *J, TRef *sp, CType **s, CTState *cts, | |||
1342 | } | 1430 | } |
1343 | if (tv) { | 1431 | if (tv) { |
1344 | if (tvisfunc(tv)) { | 1432 | if (tvisfunc(tv)) { |
1345 | J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME; | 1433 | crec_tailcall(J, rd, tv); |
1346 | rd->nres = -1; /* Pending tailcall. */ | ||
1347 | return 0; | 1434 | return 0; |
1348 | } /* NYI: non-function metamethods. */ | 1435 | } /* NYI: non-function metamethods. */ |
1349 | } else if ((MMS)rd->data == MM_eq) { /* Fallback cdata pointer comparison. */ | 1436 | } else if ((MMS)rd->data == MM_eq) { /* Fallback cdata pointer comparison. */ |
@@ -1453,8 +1540,7 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd) | |||
1453 | !irt_isguard(J->guardemit)) { | 1540 | !irt_isguard(J->guardemit)) { |
1454 | const BCIns *pc = frame_contpc(J->L->base-1) - 1; | 1541 | const BCIns *pc = frame_contpc(J->L->base-1) - 1; |
1455 | if (bc_op(*pc) <= BC_ISNEP) { | 1542 | if (bc_op(*pc) <= BC_ISNEP) { |
1456 | setframe_pc(&J2G(J)->tmptv, pc); | 1543 | J2G(J)->tmptv.u64 = (uint64_t)(uintptr_t)pc; |
1457 | J2G(J)->tmptv.u32.lo = ((tref_istrue(tr) ^ bc_op(*pc)) & 1); | ||
1458 | J->postproc = LJ_POST_FIXCOMP; | 1544 | J->postproc = LJ_POST_FIXCOMP; |
1459 | } | 1545 | } |
1460 | } | 1546 | } |
@@ -1643,7 +1729,139 @@ void LJ_FASTCALL recff_ffi_xof(jit_State *J, RecordFFData *rd) | |||
1643 | void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd) | 1729 | void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd) |
1644 | { | 1730 | { |
1645 | argv2cdata(J, J->base[0], &rd->argv[0]); | 1731 | argv2cdata(J, J->base[0], &rd->argv[0]); |
1646 | crec_finalizer(J, J->base[0], &rd->argv[1]); | 1732 | if (!J->base[1]) |
1733 | lj_trace_err(J, LJ_TRERR_BADTYPE); | ||
1734 | crec_finalizer(J, J->base[0], J->base[1], &rd->argv[1]); | ||
1735 | } | ||
1736 | |||
1737 | /* -- 64 bit bit.* library functions -------------------------------------- */ | ||
1738 | |||
1739 | /* Determine bit operation type from argument type. */ | ||
1740 | static CTypeID crec_bit64_type(CTState *cts, cTValue *tv) | ||
1741 | { | ||
1742 | if (tviscdata(tv)) { | ||
1743 | CType *ct = lj_ctype_rawref(cts, cdataV(tv)->ctypeid); | ||
1744 | if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); | ||
1745 | if ((ct->info & (CTMASK_NUM|CTF_BOOL|CTF_FP|CTF_UNSIGNED)) == | ||
1746 | CTINFO(CT_NUM, CTF_UNSIGNED) && ct->size == 8) | ||
1747 | return CTID_UINT64; /* Use uint64_t, since it has the highest rank. */ | ||
1748 | return CTID_INT64; /* Otherwise use int64_t. */ | ||
1749 | } | ||
1750 | return 0; /* Use regular 32 bit ops. */ | ||
1751 | } | ||
1752 | |||
1753 | void LJ_FASTCALL recff_bit64_tobit(jit_State *J, RecordFFData *rd) | ||
1754 | { | ||
1755 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1756 | TRef tr = crec_ct_tv(J, ctype_get(cts, CTID_INT64), 0, | ||
1757 | J->base[0], &rd->argv[0]); | ||
1758 | if (!tref_isinteger(tr)) | ||
1759 | tr = emitconv(tr, IRT_INT, tref_type(tr), 0); | ||
1760 | J->base[0] = tr; | ||
1761 | } | ||
1762 | |||
1763 | int LJ_FASTCALL recff_bit64_unary(jit_State *J, RecordFFData *rd) | ||
1764 | { | ||
1765 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1766 | CTypeID id = crec_bit64_type(cts, &rd->argv[0]); | ||
1767 | if (id) { | ||
1768 | TRef tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]); | ||
1769 | tr = emitir(IRT(rd->data, id-CTID_INT64+IRT_I64), tr, 0); | ||
1770 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
1771 | return 1; | ||
1772 | } | ||
1773 | return 0; | ||
1774 | } | ||
1775 | |||
1776 | int LJ_FASTCALL recff_bit64_nary(jit_State *J, RecordFFData *rd) | ||
1777 | { | ||
1778 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1779 | CTypeID id = 0; | ||
1780 | MSize i; | ||
1781 | for (i = 0; J->base[i] != 0; i++) { | ||
1782 | CTypeID aid = crec_bit64_type(cts, &rd->argv[i]); | ||
1783 | if (id < aid) id = aid; /* Determine highest type rank of all arguments. */ | ||
1784 | } | ||
1785 | if (id) { | ||
1786 | CType *ct = ctype_get(cts, id); | ||
1787 | uint32_t ot = IRT(rd->data, id-CTID_INT64+IRT_I64); | ||
1788 | TRef tr = crec_ct_tv(J, ct, 0, J->base[0], &rd->argv[0]); | ||
1789 | for (i = 1; J->base[i] != 0; i++) { | ||
1790 | TRef tr2 = crec_ct_tv(J, ct, 0, J->base[i], &rd->argv[i]); | ||
1791 | tr = emitir(ot, tr, tr2); | ||
1792 | } | ||
1793 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
1794 | return 1; | ||
1795 | } | ||
1796 | return 0; | ||
1797 | } | ||
1798 | |||
1799 | int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd) | ||
1800 | { | ||
1801 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1802 | CTypeID id; | ||
1803 | TRef tsh = 0; | ||
1804 | if (J->base[0] && tref_iscdata(J->base[1])) { | ||
1805 | tsh = crec_ct_tv(J, ctype_get(cts, CTID_INT64), 0, | ||
1806 | J->base[1], &rd->argv[1]); | ||
1807 | if (!tref_isinteger(tsh)) | ||
1808 | tsh = emitconv(tsh, IRT_INT, tref_type(tsh), 0); | ||
1809 | J->base[1] = tsh; | ||
1810 | } | ||
1811 | id = crec_bit64_type(cts, &rd->argv[0]); | ||
1812 | if (id) { | ||
1813 | TRef tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]); | ||
1814 | uint32_t op = rd->data; | ||
1815 | if (!tsh) tsh = lj_opt_narrow_tobit(J, J->base[1]); | ||
1816 | if (!(op < IR_BROL ? LJ_TARGET_MASKSHIFT : LJ_TARGET_MASKROT) && | ||
1817 | !tref_isk(tsh)) | ||
1818 | tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 63)); | ||
1819 | #ifdef LJ_TARGET_UNIFYROT | ||
1820 | if (op == (LJ_TARGET_UNIFYROT == 1 ? IR_BROR : IR_BROL)) { | ||
1821 | op = LJ_TARGET_UNIFYROT == 1 ? IR_BROL : IR_BROR; | ||
1822 | tsh = emitir(IRTI(IR_NEG), tsh, tsh); | ||
1823 | } | ||
1824 | #endif | ||
1825 | tr = emitir(IRT(op, id-CTID_INT64+IRT_I64), tr, tsh); | ||
1826 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
1827 | return 1; | ||
1828 | } | ||
1829 | return 0; | ||
1830 | } | ||
1831 | |||
1832 | TRef recff_bit64_tohex(jit_State *J, RecordFFData *rd, TRef hdr) | ||
1833 | { | ||
1834 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1835 | CTypeID id = crec_bit64_type(cts, &rd->argv[0]); | ||
1836 | TRef tr, trsf = J->base[1]; | ||
1837 | SFormat sf = (STRFMT_UINT|STRFMT_T_HEX); | ||
1838 | int32_t n; | ||
1839 | if (trsf) { | ||
1840 | CTypeID id2 = 0; | ||
1841 | n = (int32_t)lj_carith_check64(J->L, 2, &id2); | ||
1842 | if (id2) | ||
1843 | trsf = crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0, trsf, &rd->argv[1]); | ||
1844 | else | ||
1845 | trsf = lj_opt_narrow_tobit(J, trsf); | ||
1846 | emitir(IRTGI(IR_EQ), trsf, lj_ir_kint(J, n)); /* Specialize to n. */ | ||
1847 | } else { | ||
1848 | n = id ? 16 : 8; | ||
1849 | } | ||
1850 | if (n < 0) { n = -n; sf |= STRFMT_F_UPPER; } | ||
1851 | sf |= ((SFormat)((n+1)&255) << STRFMT_SH_PREC); | ||
1852 | if (id) { | ||
1853 | tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]); | ||
1854 | if (n < 16) | ||
1855 | tr = emitir(IRT(IR_BAND, IRT_U64), tr, | ||
1856 | lj_ir_kint64(J, ((uint64_t)1 << 4*n)-1)); | ||
1857 | } else { | ||
1858 | tr = lj_opt_narrow_tobit(J, J->base[0]); | ||
1859 | if (n < 8) | ||
1860 | tr = emitir(IRTI(IR_BAND), tr, lj_ir_kint(J, (int32_t)((1u << 4*n)-1))); | ||
1861 | tr = emitconv(tr, IRT_U64, IRT_INT, 0); /* No sign-extension. */ | ||
1862 | lj_needsplit(J); | ||
1863 | } | ||
1864 | return lj_ir_call(J, IRCALL_lj_strfmt_putfxint, hdr, lj_ir_kint(J, sf), tr); | ||
1647 | } | 1865 | } |
1648 | 1866 | ||
1649 | /* -- Miscellaneous library functions ------------------------------------- */ | 1867 | /* -- Miscellaneous library functions ------------------------------------- */ |