diff options
Diffstat (limited to 'src/lj_crecord.c')
-rw-r--r-- | src/lj_crecord.c | 219 |
1 files changed, 186 insertions, 33 deletions
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 8577de2c..c3b01f63 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)]) |
@@ -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. */ |
@@ -862,21 +863,17 @@ again: | |||
862 | } | 863 | } |
863 | 864 | ||
864 | /* Record setting a finalizer. */ | 865 | /* Record setting a finalizer. */ |
865 | static void crec_finalizer(jit_State *J, TRef trcd, cTValue *fin) | 866 | static void crec_finalizer(jit_State *J, TRef trcd, TRef trfin, cTValue *fin) |
866 | { | 867 | { |
867 | TRef trlo = lj_ir_call(J, IRCALL_lj_cdata_setfin, trcd); | 868 | if (tvisgcv(fin)) { |
868 | TRef trhi = emitir(IRT(IR_ADD, IRT_P32), trlo, lj_ir_kint(J, 4)); | 869 | if (!trfin) trfin = lj_ir_kptr(J, gcval(fin)); |
869 | if (LJ_BE) { TRef tmp = trlo; trlo = trhi; trhi = tmp; } | 870 | } else if (tvisnil(fin)) { |
870 | if (tvisfunc(fin)) { | 871 | trfin = lj_ir_kptr(J, NULL); |
871 | emitir(IRT(IR_XSTORE, IRT_P32), trlo, lj_ir_kfunc(J, funcV(fin))); | ||
872 | emitir(IRTI(IR_XSTORE), trhi, lj_ir_kint(J, LJ_TFUNC)); | ||
873 | } else if (tviscdata(fin)) { | ||
874 | emitir(IRT(IR_XSTORE, IRT_P32), trlo, | ||
875 | lj_ir_kgc(J, obj2gco(cdataV(fin)), IRT_CDATA)); | ||
876 | emitir(IRTI(IR_XSTORE), trhi, lj_ir_kint(J, LJ_TCDATA)); | ||
877 | } else { | 872 | } else { |
878 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 873 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
879 | } | 874 | } |
875 | lj_ir_call(J, IRCALL_lj_cdata_setfin, trcd, | ||
876 | trfin, lj_ir_kint(J, (int32_t)itype(fin))); | ||
880 | J->needsnap = 1; | 877 | J->needsnap = 1; |
881 | } | 878 | } |
882 | 879 | ||
@@ -887,10 +884,8 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
887 | CTSize sz; | 884 | CTSize sz; |
888 | CTInfo info = lj_ctype_info(cts, id, &sz); | 885 | CTInfo info = lj_ctype_info(cts, id, &sz); |
889 | CType *d = ctype_raw(cts, id); | 886 | CType *d = ctype_raw(cts, id); |
890 | TRef trid; | 887 | TRef trcd, trid = lj_ir_kint(J, id); |
891 | if (!sz || sz > 128 || (info & CTF_VLA) || ctype_align(info) > CT_MEMALIGN) | 888 | cTValue *fin; |
892 | lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: large/special allocations. */ | ||
893 | trid = lj_ir_kint(J, id); | ||
894 | /* Use special instruction to box pointer or 32/64 bit integer. */ | 889 | /* Use special instruction to box pointer or 32/64 bit integer. */ |
895 | if (ctype_isptr(info) || (ctype_isinteger(info) && (sz == 4 || sz == 8))) { | 890 | if (ctype_isptr(info) || (ctype_isinteger(info) && (sz == 4 || sz == 8))) { |
896 | TRef sp = J->base[1] ? crec_ct_tv(J, d, 0, J->base[1], &rd->argv[1]) : | 891 | TRef sp = J->base[1] ? crec_ct_tv(J, d, 0, J->base[1], &rd->argv[1]) : |
@@ -898,11 +893,36 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
898 | sz == 4 ? lj_ir_kint(J, 0) : | 893 | sz == 4 ? lj_ir_kint(J, 0) : |
899 | (lj_needsplit(J), lj_ir_kint64(J, 0)); | 894 | (lj_needsplit(J), lj_ir_kint64(J, 0)); |
900 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp); | 895 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp); |
896 | return; | ||
901 | } else { | 897 | } else { |
902 | TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL); | 898 | TRef trsz = TREF_NIL; |
903 | cTValue *fin; | 899 | if ((info & CTF_VLA)) { /* Calculate VLA/VLS size at runtime. */ |
904 | J->base[0] = trcd; | 900 | CTSize sz0, sz1; |
905 | if (J->base[1] && !J->base[2] && | 901 | if (!J->base[1] || J->base[2]) |
902 | lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init VLA/VLS. */ | ||
903 | trsz = crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0, | ||
904 | J->base[1], &rd->argv[1]); | ||
905 | sz0 = lj_ctype_vlsize(cts, d, 0); | ||
906 | sz1 = lj_ctype_vlsize(cts, d, 1); | ||
907 | trsz = emitir(IRTGI(IR_MULOV), trsz, lj_ir_kint(J, (int32_t)(sz1-sz0))); | ||
908 | trsz = emitir(IRTGI(IR_ADDOV), trsz, lj_ir_kint(J, (int32_t)sz0)); | ||
909 | J->base[1] = 0; /* Simplify logic below. */ | ||
910 | } else if (ctype_align(info) > CT_MEMALIGN) { | ||
911 | trsz = lj_ir_kint(J, sz); | ||
912 | } | ||
913 | trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, trsz); | ||
914 | if (sz > 128 || (info & CTF_VLA)) { | ||
915 | TRef dp; | ||
916 | CTSize align; | ||
917 | special: /* Only handle bulk zero-fill for large/VLA/VLS types. */ | ||
918 | if (J->base[1]) | ||
919 | lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init large/VLA/VLS types. */ | ||
920 | dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, lj_ir_kintp(J, sizeof(GCcdata))); | ||
921 | if (trsz == TREF_NIL) trsz = lj_ir_kint(J, sz); | ||
922 | align = ctype_align(info); | ||
923 | if (align < CT_MEMALIGN) align = CT_MEMALIGN; | ||
924 | crec_fill(J, dp, trsz, lj_ir_kint(J, 0), (1u << align)); | ||
925 | } else if (J->base[1] && !J->base[2] && | ||
906 | !lj_cconv_multi_init(cts, d, &rd->argv[1])) { | 926 | !lj_cconv_multi_init(cts, d, &rd->argv[1])) { |
907 | goto single_init; | 927 | goto single_init; |
908 | } else if (ctype_isarray(d->info)) { | 928 | } else if (ctype_isarray(d->info)) { |
@@ -913,8 +933,9 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
913 | TValue *sval = &tv; | 933 | TValue *sval = &tv; |
914 | MSize i; | 934 | MSize i; |
915 | tv.u64 = 0; | 935 | tv.u64 = 0; |
916 | if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info))) | 936 | if (!(ctype_isnum(dc->info) || ctype_isptr(dc->info)) || |
917 | lj_trace_err(J, LJ_TRERR_NYICONV); /* NYI: init array of aggregates. */ | 937 | esize * CREC_FILL_MAXUNROLL < sz) |
938 | goto special; | ||
918 | for (i = 1, ofs = 0; ofs < sz; ofs += esize) { | 939 | for (i = 1, ofs = 0; ofs < sz; ofs += esize) { |
919 | TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, | 940 | TRef dp = emitir(IRT(IR_ADD, IRT_PTR), trcd, |
920 | lj_ir_kintp(J, ofs + sizeof(GCcdata))); | 941 | lj_ir_kintp(J, ofs + sizeof(GCcdata))); |
@@ -971,11 +992,12 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) | |||
971 | crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv); | 992 | crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv); |
972 | } | 993 | } |
973 | } | 994 | } |
974 | /* Handle __gc metamethod. */ | ||
975 | fin = lj_ctype_meta(cts, id, MM_gc); | ||
976 | if (fin) | ||
977 | crec_finalizer(J, trcd, fin); | ||
978 | } | 995 | } |
996 | J->base[0] = trcd; | ||
997 | /* Handle __gc metamethod. */ | ||
998 | fin = lj_ctype_meta(cts, id, MM_gc); | ||
999 | if (fin) | ||
1000 | crec_finalizer(J, trcd, 0, fin); | ||
979 | } | 1001 | } |
980 | 1002 | ||
981 | /* Record argument conversions. */ | 1003 | /* Record argument conversions. */ |
@@ -1228,7 +1250,7 @@ static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm) | |||
1228 | for (i = 0; i < 2; i++) { | 1250 | for (i = 0; i < 2; i++) { |
1229 | IRType st = tref_type(sp[i]); | 1251 | IRType st = tref_type(sp[i]); |
1230 | if (st == IRT_NUM || st == IRT_FLOAT) | 1252 | if (st == IRT_NUM || st == IRT_FLOAT) |
1231 | sp[i] = emitconv(sp[i], dt, st, IRCONV_TRUNC|IRCONV_ANY); | 1253 | sp[i] = emitconv(sp[i], dt, st, IRCONV_ANY); |
1232 | else if (!(st == IRT_I64 || st == IRT_U64)) | 1254 | else if (!(st == IRT_I64 || st == IRT_U64)) |
1233 | sp[i] = emitconv(sp[i], dt, IRT_INT, | 1255 | sp[i] = emitconv(sp[i], dt, IRT_INT, |
1234 | (s[i]->info & CTF_UNSIGNED) ? 0 : IRCONV_SEXT); | 1256 | (s[i]->info & CTF_UNSIGNED) ? 0 : IRCONV_SEXT); |
@@ -1296,15 +1318,14 @@ static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm) | |||
1296 | CTypeID id; | 1318 | CTypeID id; |
1297 | #if LJ_64 | 1319 | #if LJ_64 |
1298 | if (t == IRT_NUM || t == IRT_FLOAT) | 1320 | if (t == IRT_NUM || t == IRT_FLOAT) |
1299 | tr = emitconv(tr, IRT_INTP, t, IRCONV_TRUNC|IRCONV_ANY); | 1321 | tr = emitconv(tr, IRT_INTP, t, IRCONV_ANY); |
1300 | else if (!(t == IRT_I64 || t == IRT_U64)) | 1322 | else if (!(t == IRT_I64 || t == IRT_U64)) |
1301 | tr = emitconv(tr, IRT_INTP, IRT_INT, | 1323 | tr = emitconv(tr, IRT_INTP, IRT_INT, |
1302 | ((t - IRT_I8) & 1) ? 0 : IRCONV_SEXT); | 1324 | ((t - IRT_I8) & 1) ? 0 : IRCONV_SEXT); |
1303 | #else | 1325 | #else |
1304 | if (!tref_typerange(sp[1], IRT_I8, IRT_U32)) { | 1326 | if (!tref_typerange(sp[1], IRT_I8, IRT_U32)) { |
1305 | tr = emitconv(tr, IRT_INTP, t, | 1327 | tr = emitconv(tr, IRT_INTP, t, |
1306 | (t == IRT_NUM || t == IRT_FLOAT) ? | 1328 | (t == IRT_NUM || t == IRT_FLOAT) ? IRCONV_ANY : 0); |
1307 | IRCONV_TRUNC|IRCONV_ANY : 0); | ||
1308 | } | 1329 | } |
1309 | #endif | 1330 | #endif |
1310 | tr = emitir(IRT(IR_MUL, IRT_INTP), tr, lj_ir_kintp(J, sz)); | 1331 | tr = emitir(IRT(IR_MUL, IRT_INTP), tr, lj_ir_kintp(J, sz)); |
@@ -1623,7 +1644,139 @@ void LJ_FASTCALL recff_ffi_xof(jit_State *J, RecordFFData *rd) | |||
1623 | void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd) | 1644 | void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd) |
1624 | { | 1645 | { |
1625 | argv2cdata(J, J->base[0], &rd->argv[0]); | 1646 | argv2cdata(J, J->base[0], &rd->argv[0]); |
1626 | crec_finalizer(J, J->base[0], &rd->argv[1]); | 1647 | if (!J->base[1]) |
1648 | lj_trace_err(J, LJ_TRERR_BADTYPE); | ||
1649 | crec_finalizer(J, J->base[0], J->base[1], &rd->argv[1]); | ||
1650 | } | ||
1651 | |||
1652 | /* -- 64 bit bit.* library functions -------------------------------------- */ | ||
1653 | |||
1654 | /* Determine bit operation type from argument type. */ | ||
1655 | static CTypeID crec_bit64_type(CTState *cts, cTValue *tv) | ||
1656 | { | ||
1657 | if (tviscdata(tv)) { | ||
1658 | CType *ct = lj_ctype_rawref(cts, cdataV(tv)->ctypeid); | ||
1659 | if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); | ||
1660 | if ((ct->info & (CTMASK_NUM|CTF_BOOL|CTF_FP|CTF_UNSIGNED)) == | ||
1661 | CTINFO(CT_NUM, CTF_UNSIGNED) && ct->size == 8) | ||
1662 | return CTID_UINT64; /* Use uint64_t, since it has the highest rank. */ | ||
1663 | return CTID_INT64; /* Otherwise use int64_t. */ | ||
1664 | } | ||
1665 | return 0; /* Use regular 32 bit ops. */ | ||
1666 | } | ||
1667 | |||
1668 | void LJ_FASTCALL recff_bit64_tobit(jit_State *J, RecordFFData *rd) | ||
1669 | { | ||
1670 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1671 | TRef tr = crec_ct_tv(J, ctype_get(cts, CTID_INT64), 0, | ||
1672 | J->base[0], &rd->argv[0]); | ||
1673 | if (!tref_isinteger(tr)) | ||
1674 | tr = emitconv(tr, IRT_INT, tref_type(tr), 0); | ||
1675 | J->base[0] = tr; | ||
1676 | } | ||
1677 | |||
1678 | int LJ_FASTCALL recff_bit64_unary(jit_State *J, RecordFFData *rd) | ||
1679 | { | ||
1680 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1681 | CTypeID id = crec_bit64_type(cts, &rd->argv[0]); | ||
1682 | if (id) { | ||
1683 | TRef tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]); | ||
1684 | tr = emitir(IRT(rd->data, id-CTID_INT64+IRT_I64), tr, 0); | ||
1685 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
1686 | return 1; | ||
1687 | } | ||
1688 | return 0; | ||
1689 | } | ||
1690 | |||
1691 | int LJ_FASTCALL recff_bit64_nary(jit_State *J, RecordFFData *rd) | ||
1692 | { | ||
1693 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1694 | CTypeID id = 0; | ||
1695 | MSize i; | ||
1696 | for (i = 0; J->base[i] != 0; i++) { | ||
1697 | CTypeID aid = crec_bit64_type(cts, &rd->argv[i]); | ||
1698 | if (id < aid) id = aid; /* Determine highest type rank of all arguments. */ | ||
1699 | } | ||
1700 | if (id) { | ||
1701 | CType *ct = ctype_get(cts, id); | ||
1702 | uint32_t ot = IRT(rd->data, id-CTID_INT64+IRT_I64); | ||
1703 | TRef tr = crec_ct_tv(J, ct, 0, J->base[0], &rd->argv[0]); | ||
1704 | for (i = 1; J->base[i] != 0; i++) { | ||
1705 | TRef tr2 = crec_ct_tv(J, ct, 0, J->base[i], &rd->argv[i]); | ||
1706 | tr = emitir(ot, tr, tr2); | ||
1707 | } | ||
1708 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
1709 | return 1; | ||
1710 | } | ||
1711 | return 0; | ||
1712 | } | ||
1713 | |||
1714 | int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd) | ||
1715 | { | ||
1716 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1717 | CTypeID id; | ||
1718 | TRef tsh = 0; | ||
1719 | if (J->base[0] && tref_iscdata(J->base[1])) { | ||
1720 | tsh = crec_ct_tv(J, ctype_get(cts, CTID_INT64), 0, | ||
1721 | J->base[1], &rd->argv[1]); | ||
1722 | if (!tref_isinteger(tsh)) | ||
1723 | tsh = emitconv(tsh, IRT_INT, tref_type(tsh), 0); | ||
1724 | J->base[1] = tsh; | ||
1725 | } | ||
1726 | id = crec_bit64_type(cts, &rd->argv[0]); | ||
1727 | if (id) { | ||
1728 | TRef tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]); | ||
1729 | uint32_t op = rd->data; | ||
1730 | if (!tsh) tsh = lj_opt_narrow_tobit(J, J->base[1]); | ||
1731 | if (!(op < IR_BROL ? LJ_TARGET_MASKSHIFT : LJ_TARGET_MASKROT) && | ||
1732 | !tref_isk(tsh)) | ||
1733 | tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 63)); | ||
1734 | #ifdef LJ_TARGET_UNIFYROT | ||
1735 | if (op == (LJ_TARGET_UNIFYROT == 1 ? IR_BROR : IR_BROL)) { | ||
1736 | op = LJ_TARGET_UNIFYROT == 1 ? IR_BROL : IR_BROR; | ||
1737 | tsh = emitir(IRTI(IR_NEG), tsh, tsh); | ||
1738 | } | ||
1739 | #endif | ||
1740 | tr = emitir(IRT(op, id-CTID_INT64+IRT_I64), tr, tsh); | ||
1741 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
1742 | return 1; | ||
1743 | } | ||
1744 | return 0; | ||
1745 | } | ||
1746 | |||
1747 | TRef recff_bit64_tohex(jit_State *J, RecordFFData *rd, TRef hdr) | ||
1748 | { | ||
1749 | CTState *cts = ctype_ctsG(J2G(J)); | ||
1750 | CTypeID id = crec_bit64_type(cts, &rd->argv[0]); | ||
1751 | TRef tr, trsf = J->base[1]; | ||
1752 | SFormat sf = (STRFMT_UINT|STRFMT_T_HEX); | ||
1753 | int32_t n; | ||
1754 | if (trsf) { | ||
1755 | CTypeID id2 = 0; | ||
1756 | n = (int32_t)lj_carith_check64(J->L, 2, &id2); | ||
1757 | if (id2) | ||
1758 | trsf = crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0, trsf, &rd->argv[1]); | ||
1759 | else | ||
1760 | trsf = lj_opt_narrow_tobit(J, trsf); | ||
1761 | emitir(IRTGI(IR_EQ), trsf, lj_ir_kint(J, n)); /* Specialize to n. */ | ||
1762 | } else { | ||
1763 | n = id ? 16 : 8; | ||
1764 | } | ||
1765 | if (n < 0) { n = -n; sf |= STRFMT_F_UPPER; } | ||
1766 | sf |= ((SFormat)((n+1)&255) << STRFMT_SH_PREC); | ||
1767 | if (id) { | ||
1768 | tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]); | ||
1769 | if (n < 16) | ||
1770 | tr = emitir(IRT(IR_BAND, IRT_U64), tr, | ||
1771 | lj_ir_kint64(J, ((uint64_t)1 << 4*n)-1)); | ||
1772 | } else { | ||
1773 | tr = lj_opt_narrow_tobit(J, J->base[0]); | ||
1774 | if (n < 8) | ||
1775 | tr = emitir(IRTI(IR_BAND), tr, lj_ir_kint(J, (int32_t)((1u << 4*n)-1))); | ||
1776 | tr = emitconv(tr, IRT_U64, IRT_INT, 0); /* No sign-extension. */ | ||
1777 | lj_needsplit(J); | ||
1778 | } | ||
1779 | return lj_ir_call(J, IRCALL_lj_strfmt_putfxint, hdr, lj_ir_kint(J, sf), tr); | ||
1627 | } | 1780 | } |
1628 | 1781 | ||
1629 | /* -- Miscellaneous library functions ------------------------------------- */ | 1782 | /* -- Miscellaneous library functions ------------------------------------- */ |