diff options
-rw-r--r-- | src/lib_string.c | 10 | ||||
-rw-r--r-- | src/lj_ffrecord.c | 78 | ||||
-rw-r--r-- | src/lj_ircall.h | 7 | ||||
-rw-r--r-- | src/lj_opt_fold.c | 43 |
4 files changed, 133 insertions, 5 deletions
diff --git a/src/lib_string.c b/src/lib_string.c index cc1affbd..204f6975 100644 --- a/src/lib_string.c +++ b/src/lib_string.c | |||
@@ -658,10 +658,10 @@ static GCstr *string_fmt_tostring(lua_State *L, int arg, int retry) | |||
658 | return lj_strfmt_obj(L, o); | 658 | return lj_strfmt_obj(L, o); |
659 | } | 659 | } |
660 | 660 | ||
661 | LJLIB_CF(string_format) | 661 | LJLIB_CF(string_format) LJLIB_REC(.) |
662 | { | 662 | { |
663 | int arg, top = (int)(L->top - L->base); | 663 | int arg, top = (int)(L->top - L->base); |
664 | GCstr *sfmt; | 664 | GCstr *fmt; |
665 | SBuf *sb; | 665 | SBuf *sb; |
666 | FormatState fs; | 666 | FormatState fs; |
667 | SFormat sf; | 667 | SFormat sf; |
@@ -669,8 +669,8 @@ LJLIB_CF(string_format) | |||
669 | again: | 669 | again: |
670 | arg = 1; | 670 | arg = 1; |
671 | sb = lj_buf_tmp_(L); | 671 | sb = lj_buf_tmp_(L); |
672 | sfmt = lj_lib_checkstr(L, arg); | 672 | fmt = lj_lib_checkstr(L, arg); |
673 | lj_strfmt_init(&fs, strdata(sfmt), sfmt->len); | 673 | lj_strfmt_init(&fs, strdata(fmt), fmt->len); |
674 | while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) { | 674 | while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) { |
675 | if (sf == STRFMT_LIT) { | 675 | if (sf == STRFMT_LIT) { |
676 | lj_buf_putmem(sb, fs.str, fs.len); | 676 | lj_buf_putmem(sb, fs.str, fs.len); |
@@ -705,7 +705,7 @@ again: | |||
705 | if (str == NULL) | 705 | if (str == NULL) |
706 | retry = 1; | 706 | retry = 1; |
707 | else if ((sf & STRFMT_T_QUOTED)) | 707 | else if ((sf & STRFMT_T_QUOTED)) |
708 | lj_strfmt_putquoted(sb, str); | 708 | lj_strfmt_putquoted(sb, str); /* No formatting. */ |
709 | else | 709 | else |
710 | lj_strfmt_putfstr(sb, sf, str); | 710 | lj_strfmt_putfstr(sb, sf, str); |
711 | break; | 711 | break; |
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index 97c24836..31f9b390 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c | |||
@@ -871,6 +871,84 @@ static void LJ_FASTCALL recff_string_find(jit_State *J, RecordFFData *rd) | |||
871 | } | 871 | } |
872 | } | 872 | } |
873 | 873 | ||
874 | static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd) | ||
875 | { | ||
876 | TRef trfmt = lj_ir_tostr(J, J->base[0]); | ||
877 | GCstr *fmt = argv2str(J, &rd->argv[0]); | ||
878 | int arg = 1; | ||
879 | TRef hdr, tr; | ||
880 | FormatState fs; | ||
881 | SFormat sf; | ||
882 | /* Specialize to the format string. */ | ||
883 | emitir(IRTG(IR_EQ, IRT_STR), trfmt, lj_ir_kstr(J, fmt)); | ||
884 | tr = hdr = recff_bufhdr(J); | ||
885 | lj_strfmt_init(&fs, strdata(fmt), fmt->len); | ||
886 | while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) { /* Parse format. */ | ||
887 | TRef tra = sf == STRFMT_LIT ? 0 : J->base[arg++]; | ||
888 | TRef trsf = lj_ir_kint(J, (int32_t)sf); | ||
889 | IRCallID id; | ||
890 | switch (STRFMT_TYPE(sf)) { | ||
891 | case STRFMT_LIT: | ||
892 | tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, | ||
893 | lj_ir_kstr(J, lj_str_new(J->L, fs.str, fs.len))); | ||
894 | break; | ||
895 | case STRFMT_INT: | ||
896 | id = IRCALL_lj_strfmt_putfnum_int; | ||
897 | handle_int: | ||
898 | if (!tref_isinteger(tra)) | ||
899 | goto handle_num; | ||
900 | if (sf == STRFMT_INT) { /* Shortcut for plain %d. */ | ||
901 | tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, | ||
902 | emitir(IRT(IR_TOSTR, IRT_STR), tra, IRTOSTR_INT)); | ||
903 | } else { | ||
904 | #if LJ_HASFFI | ||
905 | tra = emitir(IRT(IR_CONV, IRT_U64), tra, | ||
906 | (IRT_INT|(IRT_U64<<5)|IRCONV_SEXT)); | ||
907 | tr = lj_ir_call(J, IRCALL_lj_strfmt_putfxint, tr, trsf, tra); | ||
908 | lj_needsplit(J); | ||
909 | #else | ||
910 | recff_nyiu(J); /* Don't bother working around this NYI. */ | ||
911 | #endif | ||
912 | } | ||
913 | break; | ||
914 | case STRFMT_UINT: | ||
915 | id = IRCALL_lj_strfmt_putfnum_uint; | ||
916 | goto handle_int; | ||
917 | case STRFMT_NUM: | ||
918 | id = IRCALL_lj_strfmt_putfnum; | ||
919 | handle_num: | ||
920 | tra = lj_ir_tonum(J, tra); | ||
921 | tr = lj_ir_call(J, id, tr, trsf, tra); | ||
922 | if (LJ_SOFTFP) lj_needsplit(J); | ||
923 | break; | ||
924 | case STRFMT_STR: | ||
925 | if (!tref_isstr(tra)) | ||
926 | recff_nyiu(J); /* NYI: __tostring and non-string types for %s. */ | ||
927 | if (sf == STRFMT_STR) /* Shortcut for plain %s. */ | ||
928 | tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, tra); | ||
929 | else if ((sf & STRFMT_T_QUOTED)) | ||
930 | tr = lj_ir_call(J, IRCALL_lj_strfmt_putquoted, tr, tra); | ||
931 | else | ||
932 | tr = lj_ir_call(J, IRCALL_lj_strfmt_putfstr, tr, trsf, tra); | ||
933 | break; | ||
934 | case STRFMT_CHAR: | ||
935 | tra = lj_opt_narrow_toint(J, tra); | ||
936 | if (sf == STRFMT_CHAR) /* Shortcut for plain %c. */ | ||
937 | tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, | ||
938 | emitir(IRT(IR_TOSTR, IRT_STR), tra, IRTOSTR_CHAR)); | ||
939 | else | ||
940 | tr = lj_ir_call(J, IRCALL_lj_strfmt_putfchar, tr, trsf, tra); | ||
941 | break; | ||
942 | case STRFMT_PTR: /* NYI */ | ||
943 | case STRFMT_ERR: | ||
944 | default: | ||
945 | recff_nyiu(J); | ||
946 | break; | ||
947 | } | ||
948 | } | ||
949 | J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); | ||
950 | } | ||
951 | |||
874 | /* -- Table library fast functions ---------------------------------------- */ | 952 | /* -- Table library fast functions ---------------------------------------- */ |
875 | 953 | ||
876 | static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd) | 954 | static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd) |
diff --git a/src/lj_ircall.h b/src/lj_ircall.h index 43bd25d9..7271ceca 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h | |||
@@ -124,6 +124,13 @@ typedef struct CCallInfo { | |||
124 | _(ANY, lj_strfmt_char, 2, FN, STR, CCI_L) \ | 124 | _(ANY, lj_strfmt_char, 2, FN, STR, CCI_L) \ |
125 | _(ANY, lj_strfmt_putint, 2, FL, P32, 0) \ | 125 | _(ANY, lj_strfmt_putint, 2, FL, P32, 0) \ |
126 | _(ANY, lj_strfmt_putnum, 2, FL, P32, 0) \ | 126 | _(ANY, lj_strfmt_putnum, 2, FL, P32, 0) \ |
127 | _(ANY, lj_strfmt_putquoted, 2, FL, P32, 0) \ | ||
128 | _(ANY, lj_strfmt_putfxint, 3, L, P32, XA_64) \ | ||
129 | _(ANY, lj_strfmt_putfnum_int, 3, L, P32, XA_FP) \ | ||
130 | _(ANY, lj_strfmt_putfnum_uint, 3, L, P32, XA_FP) \ | ||
131 | _(ANY, lj_strfmt_putfnum, 3, L, P32, XA_FP) \ | ||
132 | _(ANY, lj_strfmt_putfstr, 3, L, P32, 0) \ | ||
133 | _(ANY, lj_strfmt_putfchar, 3, L, P32, 0) \ | ||
127 | _(ANY, lj_buf_putmem, 3, S, P32, 0) \ | 134 | _(ANY, lj_buf_putmem, 3, S, P32, 0) \ |
128 | _(ANY, lj_buf_putstr, 2, FL, P32, 0) \ | 135 | _(ANY, lj_buf_putstr, 2, FL, P32, 0) \ |
129 | _(ANY, lj_buf_putchar, 2, FL, P32, 0) \ | 136 | _(ANY, lj_buf_putchar, 2, FL, P32, 0) \ |
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index e2ac28f2..f3abe8ea 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c | |||
@@ -617,6 +617,7 @@ LJFOLDF(bufstr_kfold_cse) | |||
617 | LJFOLD(CALLL CARG IRCALL_lj_buf_putstr_reverse) | 617 | LJFOLD(CALLL CARG IRCALL_lj_buf_putstr_reverse) |
618 | LJFOLD(CALLL CARG IRCALL_lj_buf_putstr_upper) | 618 | LJFOLD(CALLL CARG IRCALL_lj_buf_putstr_upper) |
619 | LJFOLD(CALLL CARG IRCALL_lj_buf_putstr_lower) | 619 | LJFOLD(CALLL CARG IRCALL_lj_buf_putstr_lower) |
620 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putquoted) | ||
620 | LJFOLDF(bufput_kfold_op) | 621 | LJFOLDF(bufput_kfold_op) |
621 | { | 622 | { |
622 | if (irref_isk(fleft->op2)) { | 623 | if (irref_isk(fleft->op2)) { |
@@ -649,6 +650,48 @@ LJFOLDF(bufput_kfold_rep) | |||
649 | return EMITFOLD; /* Always emit, CSE later. */ | 650 | return EMITFOLD; /* Always emit, CSE later. */ |
650 | } | 651 | } |
651 | 652 | ||
653 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putfxint) | ||
654 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putfnum_int) | ||
655 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putfnum_uint) | ||
656 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putfnum) | ||
657 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putfstr) | ||
658 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putfchar) | ||
659 | LJFOLDF(bufput_kfold_fmt) | ||
660 | { | ||
661 | IRIns *irc = IR(fleft->op1); | ||
662 | lua_assert(irref_isk(irc->op2)); /* SFormat must be const. */ | ||
663 | if (irref_isk(fleft->op2)) { | ||
664 | SFormat sf = (SFormat)IR(irc->op2)->i; | ||
665 | IRIns *ira = IR(fleft->op2); | ||
666 | SBuf *sb = lj_buf_tmp_(J->L); | ||
667 | switch (fins->op2) { | ||
668 | case IRCALL_lj_strfmt_putfxint: | ||
669 | sb = lj_strfmt_putfxint(sb, sf, ir_k64(ira)->u64); | ||
670 | break; | ||
671 | case IRCALL_lj_strfmt_putfstr: | ||
672 | sb = lj_strfmt_putfstr(sb, sf, ir_kstr(ira)); | ||
673 | break; | ||
674 | case IRCALL_lj_strfmt_putfchar: | ||
675 | sb = lj_strfmt_putfchar(sb, sf, ira->i); | ||
676 | break; | ||
677 | case IRCALL_lj_strfmt_putfnum_int: | ||
678 | case IRCALL_lj_strfmt_putfnum_uint: | ||
679 | case IRCALL_lj_strfmt_putfnum: | ||
680 | default: { | ||
681 | const CCallInfo *ci = &lj_ir_callinfo[fins->op2]; | ||
682 | sb = ((SBuf * (*)(SBuf *, SFormat, lua_Number))ci->func)(sb, sf, | ||
683 | ir_knum(ira)->n); | ||
684 | break; | ||
685 | } | ||
686 | } | ||
687 | fins->o = IR_BUFPUT; | ||
688 | fins->op1 = irc->op1; | ||
689 | fins->op2 = lj_ir_kstr(J, lj_buf_tostr(sb)); | ||
690 | return RETRYFOLD; | ||
691 | } | ||
692 | return EMITFOLD; /* Always emit, CSE later. */ | ||
693 | } | ||
694 | |||
652 | /* -- Constant folding of pointer arithmetic ------------------------------ */ | 695 | /* -- Constant folding of pointer arithmetic ------------------------------ */ |
653 | 696 | ||
654 | LJFOLD(ADD KGC KINT) | 697 | LJFOLD(ADD KGC KINT) |