diff options
Diffstat (limited to 'src/lj_ffrecord.c')
-rw-r--r-- | src/lj_ffrecord.c | 78 |
1 files changed, 78 insertions, 0 deletions
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) |