src/lj_ffrecord.c - luajit-2.0-src

Data types defined

Functions defined

Macros defined

Source code

  1. /*
  2. ** Fast function call recorder.
  3. ** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
  4. */

  5. #define lj_ffrecord_c
  6. #define LUA_CORE

  7. #include "lj_obj.h"

  8. #if LJ_HASJIT

  9. #include "lj_err.h"
  10. #include "lj_str.h"
  11. #include "lj_tab.h"
  12. #include "lj_frame.h"
  13. #include "lj_bc.h"
  14. #include "lj_ff.h"
  15. #include "lj_ir.h"
  16. #include "lj_jit.h"
  17. #include "lj_ircall.h"
  18. #include "lj_iropt.h"
  19. #include "lj_trace.h"
  20. #include "lj_record.h"
  21. #include "lj_ffrecord.h"
  22. #include "lj_crecord.h"
  23. #include "lj_dispatch.h"
  24. #include "lj_vm.h"
  25. #include "lj_strscan.h"
  26. #include "lj_strfmt.h"

  27. /* Some local macros to save typing. Undef'd at the end. */
  28. #define IR(ref)                        (&J->cur.ir[(ref)])

  29. /* Pass IR on to next optimization in chain (FOLD). */
  30. #define emitir(ot, a, b)        (lj_ir_set(J, (ot), (a), (b)), lj_opt_fold(J))

  31. /* -- Fast function recording handlers ------------------------------------ */

  32. /* Conventions for fast function call handlers:
  33. **
  34. ** The argument slots start at J->base[0]. All of them are guaranteed to be
  35. ** valid and type-specialized references. J->base[J->maxslot] is set to 0
  36. ** as a sentinel. The runtime argument values start at rd->argv[0].
  37. **
  38. ** In general fast functions should check for presence of all of their
  39. ** arguments and for the correct argument types. Some simplifications
  40. ** are allowed if the interpreter throws instead. But even if recording
  41. ** is aborted, the generated IR must be consistent (no zero-refs).
  42. **
  43. ** The number of results in rd->nres is set to 1. Handlers that return
  44. ** a different number of results need to override it. A negative value
  45. ** prevents return processing (e.g. for pending calls).
  46. **
  47. ** Results need to be stored starting at J->base[0]. Return processing
  48. ** moves them to the right slots later.
  49. **
  50. ** The per-ffid auxiliary data is the value of the 2nd part of the
  51. ** LJLIB_REC() annotation. This allows handling similar functionality
  52. ** in a common handler.
  53. */

  54. /* Type of handler to record a fast function. */
  55. typedef void (LJ_FASTCALL *RecordFunc)(jit_State *J, RecordFFData *rd);

  56. /* Get runtime value of int argument. */
  57. static int32_t argv2int(jit_State *J, TValue *o)
  58. {
  59.   if (!lj_strscan_numberobj(o))
  60.     lj_trace_err(J, LJ_TRERR_BADTYPE);
  61.   return tvisint(o) ? intV(o) : lj_num2int(numV(o));
  62. }

  63. /* Get runtime value of string argument. */
  64. static GCstr *argv2str(jit_State *J, TValue *o)
  65. {
  66.   if (LJ_LIKELY(tvisstr(o))) {
  67.     return strV(o);
  68.   } else {
  69.     GCstr *s;
  70.     if (!tvisnumber(o))
  71.       lj_trace_err(J, LJ_TRERR_BADTYPE);
  72.     s = lj_strfmt_number(J->L, o);
  73.     setstrV(J->L, o, s);
  74.     return s;
  75.   }
  76. }

  77. /* Return number of results wanted by caller. */
  78. static ptrdiff_t results_wanted(jit_State *J)
  79. {
  80.   TValue *frame = J->L->base-1;
  81.   if (frame_islua(frame))
  82.     return (ptrdiff_t)bc_b(frame_pc(frame)[-1]) - 1;
  83.   else
  84.     return -1;
  85. }

  86. /* Trace stitching: add continuation below frame to start a new trace. */
  87. static void recff_stitch(jit_State *J)
  88. {
  89.   ASMFunction cont = lj_cont_stitch;
  90.   TraceNo traceno = J->cur.traceno;
  91.   lua_State *L = J->L;
  92.   TValue *base = L->base;
  93.   const BCIns *pc = frame_pc(base-1);
  94.   TValue *pframe = frame_prevl(base-1);
  95.   TRef trcont;

  96.   lua_assert(!LJ_FR2);  /* TODO_FR2: handle frame shift. */
  97.   /* Move func + args up in Lua stack and insert continuation. */
  98.   memmove(&base[1], &base[-1], sizeof(TValue)*(J->maxslot+1));
  99.   setframe_ftsz(base+1, ((char *)(base+1) - (char *)pframe) + FRAME_CONT);
  100.   setcont(base, cont);
  101.   setframe_pc(base, pc);
  102.   if (LJ_DUALNUM) setintV(base-1, traceno); else base[-1].u64 = traceno;
  103.   L->base += 2;
  104.   L->top += 2;

  105.   /* Ditto for the IR. */
  106.   memmove(&J->base[1], &J->base[-1], sizeof(TRef)*(J->maxslot+1));
  107. #if LJ_64
  108.   trcont = lj_ir_kptr(J, (void *)((int64_t)cont-(int64_t)lj_vm_asm_begin));
  109. #else
  110.   trcont = lj_ir_kptr(J, (void *)cont);
  111. #endif
  112.   J->base[0] = trcont | TREF_CONT;
  113.   J->base[-1] = LJ_DUALNUM ? lj_ir_kint(J,traceno) : lj_ir_knum_u64(J,traceno);
  114.   J->base += 2;
  115.   J->baseslot += 2;
  116.   J->framedepth++;

  117.   lj_record_stop(J, LJ_TRLINK_STITCH, 0);

  118.   /* Undo Lua stack changes. */
  119.   memmove(&base[-1], &base[1], sizeof(TValue)*(J->maxslot+1));
  120.   setframe_pc(base-1, pc);
  121.   L->base -= 2;
  122.   L->top -= 2;
  123. }

  124. /* Fallback handler for fast functions that are not recorded (yet). */
  125. static void LJ_FASTCALL recff_nyi(jit_State *J, RecordFFData *rd)
  126. {
  127.   if (J->cur.nins < (IRRef)J->param[JIT_P_minstitch] + REF_BASE) {
  128.     lj_trace_err_info(J, LJ_TRERR_TRACEUV);
  129.   } else {
  130.     /* Can only stitch from Lua call. */
  131.     if (J->framedepth && frame_islua(J->L->base-1)) {
  132.       BCOp op = bc_op(*frame_pc(J->L->base-1));
  133.       /* Stitched trace cannot start with *M op with variable # of args. */
  134.       if (!(op == BC_CALLM || op == BC_CALLMT ||
  135.             op == BC_RETM || op == BC_TSETM)) {
  136.         switch (J->fn->c.ffid) {
  137.         case FF_error:
  138.         case FF_debug_sethook:
  139.         case FF_jit_flush:
  140.           break/* Don't stitch across special builtins. */
  141.         default:
  142.           recff_stitch(J);  /* Use trace stitching. */
  143.           rd->nres = -1;
  144.           return;
  145.         }
  146.       }
  147.     }
  148.     /* Otherwise stop trace and return to interpreter. */
  149.     lj_record_stop(J, LJ_TRLINK_RETURN, 0);
  150.     rd->nres = -1;
  151.   }
  152. }

  153. /* Fallback handler for unsupported variants of fast functions. */
  154. #define recff_nyiu        recff_nyi

  155. /* Must stop the trace for classic C functions with arbitrary side-effects. */
  156. #define recff_c                recff_nyi

  157. /* Emit BUFHDR for the global temporary buffer. */
  158. static TRef recff_bufhdr(jit_State *J)
  159. {
  160.   return emitir(IRT(IR_BUFHDR, IRT_P32),
  161.                 lj_ir_kptr(J, &J2G(J)->tmpbuf), IRBUFHDR_RESET);
  162. }

  163. /* -- Base library fast functions ----------------------------------------- */

  164. static void LJ_FASTCALL recff_assert(jit_State *J, RecordFFData *rd)
  165. {
  166.   /* Arguments already specialized. The interpreter throws for nil/false. */
  167.   rd->nres = J->maxslot;  /* Pass through all arguments. */
  168. }

  169. static void LJ_FASTCALL recff_type(jit_State *J, RecordFFData *rd)
  170. {
  171.   /* Arguments already specialized. Result is a constant string. Neat, huh? */
  172.   uint32_t t;
  173.   if (tvisnumber(&rd->argv[0]))
  174.     t = ~LJ_TNUMX;
  175.   else if (LJ_64 && !LJ_GC64 && tvislightud(&rd->argv[0]))
  176.     t = ~LJ_TLIGHTUD;
  177.   else
  178.     t = ~itype(&rd->argv[0]);
  179.   J->base[0] = lj_ir_kstr(J, strV(&J->fn->c.upvalue[t]));
  180.   UNUSED(rd);
  181. }

  182. static void LJ_FASTCALL recff_getmetatable(jit_State *J, RecordFFData *rd)
  183. {
  184.   TRef tr = J->base[0];
  185.   if (tr) {
  186.     RecordIndex ix;
  187.     ix.tab = tr;
  188.     copyTV(J->L, &ix.tabv, &rd->argv[0]);
  189.     if (lj_record_mm_lookup(J, &ix, MM_metatable))
  190.       J->base[0] = ix.mobj;
  191.     else
  192.       J->base[0] = ix.mt;
  193.   }  /* else: Interpreter will throw. */
  194. }

  195. static void LJ_FASTCALL recff_setmetatable(jit_State *J, RecordFFData *rd)
  196. {
  197.   TRef tr = J->base[0];
  198.   TRef mt = J->base[1];
  199.   if (tref_istab(tr) && (tref_istab(mt) || (mt && tref_isnil(mt)))) {
  200.     TRef fref, mtref;
  201.     RecordIndex ix;
  202.     ix.tab = tr;
  203.     copyTV(J->L, &ix.tabv, &rd->argv[0]);
  204.     lj_record_mm_lookup(J, &ix, MM_metatable); /* Guard for no __metatable. */
  205.     fref = emitir(IRT(IR_FREF, IRT_P32), tr, IRFL_TAB_META);
  206.     mtref = tref_isnil(mt) ? lj_ir_knull(J, IRT_TAB) : mt;
  207.     emitir(IRT(IR_FSTORE, IRT_TAB), fref, mtref);
  208.     if (!tref_isnil(mt))
  209.       emitir(IRT(IR_TBAR, IRT_TAB), tr, 0);
  210.     J->base[0] = tr;
  211.     J->needsnap = 1;
  212.   }  /* else: Interpreter will throw. */
  213. }

  214. static void LJ_FASTCALL recff_rawget(jit_State *J, RecordFFData *rd)
  215. {
  216.   RecordIndex ix;
  217.   ix.tab = J->base[0]; ix.key = J->base[1];
  218.   if (tref_istab(ix.tab) && ix.key) {
  219.     ix.val = 0; ix.idxchain = 0;
  220.     settabV(J->L, &ix.tabv, tabV(&rd->argv[0]));
  221.     copyTV(J->L, &ix.keyv, &rd->argv[1]);
  222.     J->base[0] = lj_record_idx(J, &ix);
  223.   }  /* else: Interpreter will throw. */
  224. }

  225. static void LJ_FASTCALL recff_rawset(jit_State *J, RecordFFData *rd)
  226. {
  227.   RecordIndex ix;
  228.   ix.tab = J->base[0]; ix.key = J->base[1]; ix.val = J->base[2];
  229.   if (tref_istab(ix.tab) && ix.key && ix.val) {
  230.     ix.idxchain = 0;
  231.     settabV(J->L, &ix.tabv, tabV(&rd->argv[0]));
  232.     copyTV(J->L, &ix.keyv, &rd->argv[1]);
  233.     copyTV(J->L, &ix.valv, &rd->argv[2]);
  234.     lj_record_idx(J, &ix);
  235.     /* Pass through table at J->base[0] as result. */
  236.   }  /* else: Interpreter will throw. */
  237. }

  238. static void LJ_FASTCALL recff_rawequal(jit_State *J, RecordFFData *rd)
  239. {
  240.   TRef tra = J->base[0];
  241.   TRef trb = J->base[1];
  242.   if (tra && trb) {
  243.     int diff = lj_record_objcmp(J, tra, trb, &rd->argv[0], &rd->argv[1]);
  244.     J->base[0] = diff ? TREF_FALSE : TREF_TRUE;
  245.   }  /* else: Interpreter will throw. */
  246. }

  247. #if LJ_52
  248. static void LJ_FASTCALL recff_rawlen(jit_State *J, RecordFFData *rd)
  249. {
  250.   TRef tr = J->base[0];
  251.   if (tref_isstr(tr))
  252.     J->base[0] = emitir(IRTI(IR_FLOAD), tr, IRFL_STR_LEN);
  253.   else if (tref_istab(tr))
  254.     J->base[0] = lj_ir_call(J, IRCALL_lj_tab_len, tr);
  255.   /* else: Interpreter will throw. */
  256.   UNUSED(rd);
  257. }
  258. #endif

  259. /* Determine mode of select() call. */
  260. int32_t lj_ffrecord_select_mode(jit_State *J, TRef tr, TValue *tv)
  261. {
  262.   if (tref_isstr(tr) && *strVdata(tv) == '#') {  /* select('#', ...) */
  263.     if (strV(tv)->len == 1) {
  264.       emitir(IRTG(IR_EQ, IRT_STR), tr, lj_ir_kstr(J, strV(tv)));
  265.     } else {
  266.       TRef trptr = emitir(IRT(IR_STRREF, IRT_P32), tr, lj_ir_kint(J, 0));
  267.       TRef trchar = emitir(IRT(IR_XLOAD, IRT_U8), trptr, IRXLOAD_READONLY);
  268.       emitir(IRTG(IR_EQ, IRT_INT), trchar, lj_ir_kint(J, '#'));
  269.     }
  270.     return 0;
  271.   } else/* select(n, ...) */
  272.     int32_t start = argv2int(J, tv);
  273.     if (start == 0) lj_trace_err(J, LJ_TRERR_BADTYPE);  /* A bit misleading. */
  274.     return start;
  275.   }
  276. }

  277. static void LJ_FASTCALL recff_select(jit_State *J, RecordFFData *rd)
  278. {
  279.   TRef tr = J->base[0];
  280.   if (tr) {
  281.     ptrdiff_t start = lj_ffrecord_select_mode(J, tr, &rd->argv[0]);
  282.     if (start == 0) {  /* select('#', ...) */
  283.       J->base[0] = lj_ir_kint(J, J->maxslot - 1);
  284.     } else if (tref_isk(tr)) {  /* select(k, ...) */
  285.       ptrdiff_t n = (ptrdiff_t)J->maxslot;
  286.       if (start < 0) start += n;
  287.       else if (start > n) start = n;
  288.       rd->nres = n - start;
  289.       if (start >= 1) {
  290.         ptrdiff_t i;
  291.         for (i = 0; i < n - start; i++)
  292.           J->base[i] = J->base[start+i];
  293.       }  /* else: Interpreter will throw. */
  294.     } else {
  295.       recff_nyiu(J, rd);
  296.       return;
  297.     }
  298.   }  /* else: Interpreter will throw. */
  299. }

  300. static void LJ_FASTCALL recff_tonumber(jit_State *J, RecordFFData *rd)
  301. {
  302.   TRef tr = J->base[0];
  303.   TRef base = J->base[1];
  304.   if (tr && !tref_isnil(base)) {
  305.     base = lj_opt_narrow_toint(J, base);
  306.     if (!tref_isk(base) || IR(tref_ref(base))->i != 10) {
  307.       recff_nyiu(J, rd);
  308.       return;
  309.     }
  310.   }
  311.   if (tref_isnumber_str(tr)) {
  312.     if (tref_isstr(tr)) {
  313.       TValue tmp;
  314.       if (!lj_strscan_num(strV(&rd->argv[0]), &tmp)) {
  315.         recff_nyiu(J, rd);  /* Would need an inverted STRTO for this case. */
  316.         return;
  317.       }
  318.       tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0);
  319.     }
  320. #if LJ_HASFFI
  321.   } else if (tref_iscdata(tr)) {
  322.     lj_crecord_tonumber(J, rd);
  323.     return;
  324. #endif
  325.   } else {
  326.     tr = TREF_NIL;
  327.   }
  328.   J->base[0] = tr;
  329.   UNUSED(rd);
  330. }

  331. static TValue *recff_metacall_cp(lua_State *L, lua_CFunction dummy, void *ud)
  332. {
  333.   jit_State *J = (jit_State *)ud;
  334.   lj_record_tailcall(J, 0, 1);
  335.   UNUSED(L); UNUSED(dummy);
  336.   return NULL;
  337. }

  338. static int recff_metacall(jit_State *J, RecordFFData *rd, MMS mm)
  339. {
  340.   RecordIndex ix;
  341.   ix.tab = J->base[0];
  342.   copyTV(J->L, &ix.tabv, &rd->argv[0]);
  343.   if (lj_record_mm_lookup(J, &ix, mm)) {  /* Has metamethod? */
  344.     int errcode;
  345.     TValue argv0;
  346.     /* Temporarily insert metamethod below object. */
  347.     J->base[1] = J->base[0];
  348.     J->base[0] = ix.mobj;
  349.     copyTV(J->L, &argv0, &rd->argv[0]);
  350.     copyTV(J->L, &rd->argv[1], &rd->argv[0]);
  351.     copyTV(J->L, &rd->argv[0], &ix.mobjv);
  352.     /* Need to protect lj_record_tailcall because it may throw. */
  353.     errcode = lj_vm_cpcall(J->L, NULL, J, recff_metacall_cp);
  354.     /* Always undo Lua stack changes to avoid confusing the interpreter. */
  355.     copyTV(J->L, &rd->argv[0], &argv0);
  356.     if (errcode)
  357.       lj_err_throw(J->L, errcode);  /* Propagate errors. */
  358.     rd->nres = -1/* Pending call. */
  359.     return 1/* Tailcalled to metamethod. */
  360.   }
  361.   return 0;
  362. }

  363. static void LJ_FASTCALL recff_tostring(jit_State *J, RecordFFData *rd)
  364. {
  365.   TRef tr = J->base[0];
  366.   if (tref_isstr(tr)) {
  367.     /* Ignore __tostring in the string base metatable. */
  368.     /* Pass on result in J->base[0]. */
  369.   } else if (tr && !recff_metacall(J, rd, MM_tostring)) {
  370.     if (tref_isnumber(tr)) {
  371.       J->base[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr,
  372.                           tref_isnum(tr) ? IRTOSTR_NUM : IRTOSTR_INT);
  373.     } else if (tref_ispri(tr)) {
  374.       J->base[0] = lj_ir_kstr(J, lj_strfmt_obj(J->L, &rd->argv[0]));
  375.     } else {
  376.       recff_nyiu(J, rd);
  377.       return;
  378.     }
  379.   }
  380. }

  381. static void LJ_FASTCALL recff_ipairs_aux(jit_State *J, RecordFFData *rd)
  382. {
  383.   RecordIndex ix;
  384.   ix.tab = J->base[0];
  385.   if (tref_istab(ix.tab)) {
  386.     if (!tvisnumber(&rd->argv[1]))  /* No support for string coercion. */
  387.       lj_trace_err(J, LJ_TRERR_BADTYPE);
  388.     setintV(&ix.keyv, numberVint(&rd->argv[1])+1);
  389.     settabV(J->L, &ix.tabv, tabV(&rd->argv[0]));
  390.     ix.val = 0; ix.idxchain = 0;
  391.     ix.key = lj_opt_narrow_toint(J, J->base[1]);
  392.     J->base[0] = ix.key = emitir(IRTI(IR_ADD), ix.key, lj_ir_kint(J, 1));
  393.     J->base[1] = lj_record_idx(J, &ix);
  394.     rd->nres = tref_isnil(J->base[1]) ? 0 : 2;
  395.   }  /* else: Interpreter will throw. */
  396. }

  397. static void LJ_FASTCALL recff_xpairs(jit_State *J, RecordFFData *rd)
  398. {
  399.   if (!(LJ_52 && recff_metacall(J, rd, MM_ipairs))) {
  400.     TRef tab = J->base[0];
  401.     if (tref_istab(tab)) {
  402.       J->base[0] = lj_ir_kfunc(J, funcV(&J->fn->c.upvalue[0]));
  403.       J->base[1] = tab;
  404.       J->base[2] = rd->data ? lj_ir_kint(J, 0) : TREF_NIL;
  405.       rd->nres = 3;
  406.     }  /* else: Interpreter will throw. */
  407.   }
  408. }

  409. static void LJ_FASTCALL recff_pcall(jit_State *J, RecordFFData *rd)
  410. {
  411.   if (J->maxslot >= 1) {
  412.     lj_record_call(J, 0, J->maxslot - 1);
  413.     rd->nres = -1/* Pending call. */
  414.   }  /* else: Interpreter will throw. */
  415. }

  416. static TValue *recff_xpcall_cp(lua_State *L, lua_CFunction dummy, void *ud)
  417. {
  418.   jit_State *J = (jit_State *)ud;
  419.   lj_record_call(J, 1, J->maxslot - 2);
  420.   UNUSED(L); UNUSED(dummy);
  421.   return NULL;
  422. }

  423. static void LJ_FASTCALL recff_xpcall(jit_State *J, RecordFFData *rd)
  424. {
  425.   if (J->maxslot >= 2) {
  426.     TValue argv0, argv1;
  427.     TRef tmp;
  428.     int errcode;
  429.     lua_assert(!LJ_FR2);  /* TODO_FR2: handle different frame setup. */
  430.     /* Swap function and traceback. */
  431.     tmp = J->base[0]; J->base[0] = J->base[1]; J->base[1] = tmp;
  432.     copyTV(J->L, &argv0, &rd->argv[0]);
  433.     copyTV(J->L, &argv1, &rd->argv[1]);
  434.     copyTV(J->L, &rd->argv[0], &argv1);
  435.     copyTV(J->L, &rd->argv[1], &argv0);
  436.     /* Need to protect lj_record_call because it may throw. */
  437.     errcode = lj_vm_cpcall(J->L, NULL, J, recff_xpcall_cp);
  438.     /* Always undo Lua stack swap to avoid confusing the interpreter. */
  439.     copyTV(J->L, &rd->argv[0], &argv0);
  440.     copyTV(J->L, &rd->argv[1], &argv1);
  441.     if (errcode)
  442.       lj_err_throw(J->L, errcode);  /* Propagate errors. */
  443.     rd->nres = -1/* Pending call. */
  444.   }  /* else: Interpreter will throw. */
  445. }

  446. static void LJ_FASTCALL recff_getfenv(jit_State *J, RecordFFData *rd)
  447. {
  448.   TRef tr = J->base[0];
  449.   /* Only support getfenv(0) for now. */
  450.   if (tref_isint(tr) && tref_isk(tr) && IR(tref_ref(tr))->i == 0) {
  451.     TRef trl = emitir(IRT(IR_LREF, IRT_THREAD), 0, 0);
  452.     J->base[0] = emitir(IRT(IR_FLOAD, IRT_TAB), trl, IRFL_THREAD_ENV);
  453.     return;
  454.   }
  455.   recff_nyiu(J, rd);
  456. }

  457. /* -- Math library fast functions ----------------------------------------- */

  458. static void LJ_FASTCALL recff_math_abs(jit_State *J, RecordFFData *rd)
  459. {
  460.   TRef tr = lj_ir_tonum(J, J->base[0]);
  461.   J->base[0] = emitir(IRTN(IR_ABS), tr, lj_ir_knum_abs(J));
  462.   UNUSED(rd);
  463. }

  464. /* Record rounding functions math.floor and math.ceil. */
  465. static void LJ_FASTCALL recff_math_round(jit_State *J, RecordFFData *rd)
  466. {
  467.   TRef tr = J->base[0];
  468.   if (!tref_isinteger(tr)) {  /* Pass through integers unmodified. */
  469.     tr = emitir(IRTN(IR_FPMATH), lj_ir_tonum(J, tr), rd->data);
  470.     /* Result is integral (or NaN/Inf), but may not fit an int32_t. */
  471.     if (LJ_DUALNUM) {  /* Try to narrow using a guarded conversion to int. */
  472.       lua_Number n = lj_vm_foldfpm(numberVnum(&rd->argv[0]), rd->data);
  473.       if (n == (lua_Number)lj_num2int(n))
  474.         tr = emitir(IRTGI(IR_CONV), tr, IRCONV_INT_NUM|IRCONV_CHECK);
  475.     }
  476.     J->base[0] = tr;
  477.   }
  478. }

  479. /* Record unary math.* functions, mapped to IR_FPMATH opcode. */
  480. static void LJ_FASTCALL recff_math_unary(jit_State *J, RecordFFData *rd)
  481. {
  482.   J->base[0] = emitir(IRTN(IR_FPMATH), lj_ir_tonum(J, J->base[0]), rd->data);
  483. }

  484. /* Record math.log. */
  485. static void LJ_FASTCALL recff_math_log(jit_State *J, RecordFFData *rd)
  486. {
  487.   TRef tr = lj_ir_tonum(J, J->base[0]);
  488.   if (J->base[1]) {
  489. #ifdef LUAJIT_NO_LOG2
  490.     uint32_t fpm = IRFPM_LOG;
  491. #else
  492.     uint32_t fpm = IRFPM_LOG2;
  493. #endif
  494.     TRef trb = lj_ir_tonum(J, J->base[1]);
  495.     tr = emitir(IRTN(IR_FPMATH), tr, fpm);
  496.     trb = emitir(IRTN(IR_FPMATH), trb, fpm);
  497.     trb = emitir(IRTN(IR_DIV), lj_ir_knum_one(J), trb);
  498.     tr = emitir(IRTN(IR_MUL), tr, trb);
  499.   } else {
  500.     tr = emitir(IRTN(IR_FPMATH), tr, IRFPM_LOG);
  501.   }
  502.   J->base[0] = tr;
  503.   UNUSED(rd);
  504. }

  505. /* Record math.atan2. */
  506. static void LJ_FASTCALL recff_math_atan2(jit_State *J, RecordFFData *rd)
  507. {
  508.   TRef tr = lj_ir_tonum(J, J->base[0]);
  509.   TRef tr2 = lj_ir_tonum(J, J->base[1]);
  510.   J->base[0] = emitir(IRTN(IR_ATAN2), tr, tr2);
  511.   UNUSED(rd);
  512. }

  513. /* Record math.ldexp. */
  514. static void LJ_FASTCALL recff_math_ldexp(jit_State *J, RecordFFData *rd)
  515. {
  516.   TRef tr = lj_ir_tonum(J, J->base[0]);
  517. #if LJ_TARGET_X86ORX64
  518.   TRef tr2 = lj_ir_tonum(J, J->base[1]);
  519. #else
  520.   TRef tr2 = lj_opt_narrow_toint(J, J->base[1]);
  521. #endif
  522.   J->base[0] = emitir(IRTN(IR_LDEXP), tr, tr2);
  523.   UNUSED(rd);
  524. }

  525. /* Record math.asin, math.acos, math.atan. */
  526. static void LJ_FASTCALL recff_math_atrig(jit_State *J, RecordFFData *rd)
  527. {
  528.   TRef y = lj_ir_tonum(J, J->base[0]);
  529.   TRef x = lj_ir_knum_one(J);
  530.   uint32_t ffid = rd->data;
  531.   if (ffid != FF_math_atan) {
  532.     TRef tmp = emitir(IRTN(IR_MUL), y, y);
  533.     tmp = emitir(IRTN(IR_SUB), x, tmp);
  534.     tmp = emitir(IRTN(IR_FPMATH), tmp, IRFPM_SQRT);
  535.     if (ffid == FF_math_asin) { x = tmp; } else { x = y; y = tmp; }
  536.   }
  537.   J->base[0] = emitir(IRTN(IR_ATAN2), y, x);
  538. }

  539. static void LJ_FASTCALL recff_math_htrig(jit_State *J, RecordFFData *rd)
  540. {
  541.   TRef tr = lj_ir_tonum(J, J->base[0]);
  542.   J->base[0] = emitir(IRTN(IR_CALLN), tr, rd->data);
  543. }

  544. static void LJ_FASTCALL recff_math_modf(jit_State *J, RecordFFData *rd)
  545. {
  546.   TRef tr = J->base[0];
  547.   if (tref_isinteger(tr)) {
  548.     J->base[0] = tr;
  549.     J->base[1] = lj_ir_kint(J, 0);
  550.   } else {
  551.     TRef trt;
  552.     tr = lj_ir_tonum(J, tr);
  553.     trt = emitir(IRTN(IR_FPMATH), tr, IRFPM_TRUNC);
  554.     J->base[0] = trt;
  555.     J->base[1] = emitir(IRTN(IR_SUB), tr, trt);
  556.   }
  557.   rd->nres = 2;
  558. }

  559. static void LJ_FASTCALL recff_math_pow(jit_State *J, RecordFFData *rd)
  560. {
  561.   TRef tr = lj_ir_tonum(J, J->base[0]);
  562.   if (!tref_isnumber_str(J->base[1]))
  563.     lj_trace_err(J, LJ_TRERR_BADTYPE);
  564.   J->base[0] = lj_opt_narrow_pow(J, tr, J->base[1], &rd->argv[1]);
  565.   UNUSED(rd);
  566. }

  567. static void LJ_FASTCALL recff_math_minmax(jit_State *J, RecordFFData *rd)
  568. {
  569.   TRef tr = lj_ir_tonumber(J, J->base[0]);
  570.   uint32_t op = rd->data;
  571.   BCReg i;
  572.   for (i = 1; J->base[i] != 0; i++) {
  573.     TRef tr2 = lj_ir_tonumber(J, J->base[i]);
  574.     IRType t = IRT_INT;
  575.     if (!(tref_isinteger(tr) && tref_isinteger(tr2))) {
  576.       if (tref_isinteger(tr)) tr = emitir(IRTN(IR_CONV), tr, IRCONV_NUM_INT);
  577.       if (tref_isinteger(tr2)) tr2 = emitir(IRTN(IR_CONV), tr2, IRCONV_NUM_INT);
  578.       t = IRT_NUM;
  579.     }
  580.     tr = emitir(IRT(op, t), tr, tr2);
  581.   }
  582.   J->base[0] = tr;
  583. }

  584. static void LJ_FASTCALL recff_math_random(jit_State *J, RecordFFData *rd)
  585. {
  586.   GCudata *ud = udataV(&J->fn->c.upvalue[0]);
  587.   TRef tr, one;
  588.   lj_ir_kgc(J, obj2gco(ud), IRT_UDATA);  /* Prevent collection. */
  589.   tr = lj_ir_call(J, IRCALL_lj_math_random_step, lj_ir_kptr(J, uddata(ud)));
  590.   one = lj_ir_knum_one(J);
  591.   tr = emitir(IRTN(IR_SUB), tr, one);
  592.   if (J->base[0]) {
  593.     TRef tr1 = lj_ir_tonum(J, J->base[0]);
  594.     if (J->base[1]) {  /* d = floor(d*(r2-r1+1.0)) + r1 */
  595.       TRef tr2 = lj_ir_tonum(J, J->base[1]);
  596.       tr2 = emitir(IRTN(IR_SUB), tr2, tr1);
  597.       tr2 = emitir(IRTN(IR_ADD), tr2, one);
  598.       tr = emitir(IRTN(IR_MUL), tr, tr2);
  599.       tr = emitir(IRTN(IR_FPMATH), tr, IRFPM_FLOOR);
  600.       tr = emitir(IRTN(IR_ADD), tr, tr1);
  601.     } else/* d = floor(d*r1) + 1.0 */
  602.       tr = emitir(IRTN(IR_MUL), tr, tr1);
  603.       tr = emitir(IRTN(IR_FPMATH), tr, IRFPM_FLOOR);
  604.       tr = emitir(IRTN(IR_ADD), tr, one);
  605.     }
  606.   }
  607.   J->base[0] = tr;
  608.   UNUSED(rd);
  609. }

  610. /* -- Bit library fast functions ------------------------------------------ */

  611. /* Record bit.tobit. */
  612. static void LJ_FASTCALL recff_bit_tobit(jit_State *J, RecordFFData *rd)
  613. {
  614.   TRef tr = J->base[0];
  615. #if LJ_HASFFI
  616.   if (tref_iscdata(tr)) { recff_bit64_tobit(J, rd); return; }
  617. #endif
  618.   J->base[0] = lj_opt_narrow_tobit(J, tr);
  619.   UNUSED(rd);
  620. }

  621. /* Record unary bit.bnot, bit.bswap. */
  622. static void LJ_FASTCALL recff_bit_unary(jit_State *J, RecordFFData *rd)
  623. {
  624. #if LJ_HASFFI
  625.   if (recff_bit64_unary(J, rd))
  626.     return;
  627. #endif
  628.   J->base[0] = emitir(IRTI(rd->data), lj_opt_narrow_tobit(J, J->base[0]), 0);
  629. }

  630. /* Record N-ary bit.band, bit.bor, bit.bxor. */
  631. static void LJ_FASTCALL recff_bit_nary(jit_State *J, RecordFFData *rd)
  632. {
  633. #if LJ_HASFFI
  634.   if (recff_bit64_nary(J, rd))
  635.     return;
  636. #endif
  637.   {
  638.     TRef tr = lj_opt_narrow_tobit(J, J->base[0]);
  639.     uint32_t ot = IRTI(rd->data);
  640.     BCReg i;
  641.     for (i = 1; J->base[i] != 0; i++)
  642.       tr = emitir(ot, tr, lj_opt_narrow_tobit(J, J->base[i]));
  643.     J->base[0] = tr;
  644.   }
  645. }

  646. /* Record bit shifts. */
  647. static void LJ_FASTCALL recff_bit_shift(jit_State *J, RecordFFData *rd)
  648. {
  649. #if LJ_HASFFI
  650.   if (recff_bit64_shift(J, rd))
  651.     return;
  652. #endif
  653.   {
  654.     TRef tr = lj_opt_narrow_tobit(J, J->base[0]);
  655.     TRef tsh = lj_opt_narrow_tobit(J, J->base[1]);
  656.     IROp op = (IROp)rd->data;
  657.     if (!(op < IR_BROL ? LJ_TARGET_MASKSHIFT : LJ_TARGET_MASKROT) &&
  658.         !tref_isk(tsh))
  659.       tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 31));
  660. #ifdef LJ_TARGET_UNIFYROT
  661.     if (op == (LJ_TARGET_UNIFYROT == 1 ? IR_BROR : IR_BROL)) {
  662.       op = LJ_TARGET_UNIFYROT == 1 ? IR_BROL : IR_BROR;
  663.       tsh = emitir(IRTI(IR_NEG), tsh, tsh);
  664.     }
  665. #endif
  666.     J->base[0] = emitir(IRTI(op), tr, tsh);
  667.   }
  668. }

  669. static void LJ_FASTCALL recff_bit_tohex(jit_State *J, RecordFFData *rd)
  670. {
  671. #if LJ_HASFFI
  672.   TRef hdr = recff_bufhdr(J);
  673.   TRef tr = recff_bit64_tohex(J, rd, hdr);
  674.   J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
  675. #else
  676.   recff_nyiu(J, rd);  /* Don't bother working around this NYI. */
  677. #endif
  678. }

  679. /* -- String library fast functions --------------------------------------- */

  680. /* Specialize to relative starting position for string. */
  681. static TRef recff_string_start(jit_State *J, GCstr *s, int32_t *st, TRef tr,
  682.                                TRef trlen, TRef tr0)
  683. {
  684.   int32_t start = *st;
  685.   if (start < 0) {
  686.     emitir(IRTGI(IR_LT), tr, tr0);
  687.     tr = emitir(IRTI(IR_ADD), trlen, tr);
  688.     start = start + (int32_t)s->len;
  689.     emitir(start < 0 ? IRTGI(IR_LT) : IRTGI(IR_GE), tr, tr0);
  690.     if (start < 0) {
  691.       tr = tr0;
  692.       start = 0;
  693.     }
  694.   } else if (start == 0) {
  695.     emitir(IRTGI(IR_EQ), tr, tr0);
  696.     tr = tr0;
  697.   } else {
  698.     tr = emitir(IRTI(IR_ADD), tr, lj_ir_kint(J, -1));
  699.     emitir(IRTGI(IR_GE), tr, tr0);
  700.     start--;
  701.   }
  702.   *st = start;
  703.   return tr;
  704. }

  705. /* Handle string.byte (rd->data = 0) and string.sub (rd->data = 1). */
  706. static void LJ_FASTCALL recff_string_range(jit_State *J, RecordFFData *rd)
  707. {
  708.   TRef trstr = lj_ir_tostr(J, J->base[0]);
  709.   TRef trlen = emitir(IRTI(IR_FLOAD), trstr, IRFL_STR_LEN);
  710.   TRef tr0 = lj_ir_kint(J, 0);
  711.   TRef trstart, trend;
  712.   GCstr *str = argv2str(J, &rd->argv[0]);
  713.   int32_t start, end;
  714.   if (rd->data) {  /* string.sub(str, start [,end]) */
  715.     start = argv2int(J, &rd->argv[1]);
  716.     trstart = lj_opt_narrow_toint(J, J->base[1]);
  717.     trend = J->base[2];
  718.     if (tref_isnil(trend)) {
  719.       trend = lj_ir_kint(J, -1);
  720.       end = -1;
  721.     } else {
  722.       trend = lj_opt_narrow_toint(J, trend);
  723.       end = argv2int(J, &rd->argv[2]);
  724.     }
  725.   } else/* string.byte(str, [,start [,end]]) */
  726.     if (tref_isnil(J->base[1])) {
  727.       start = 1;
  728.       trstart = lj_ir_kint(J, 1);
  729.     } else {
  730.       start = argv2int(J, &rd->argv[1]);
  731.       trstart = lj_opt_narrow_toint(J, J->base[1]);
  732.     }
  733.     if (J->base[1] && !tref_isnil(J->base[2])) {
  734.       trend = lj_opt_narrow_toint(J, J->base[2]);
  735.       end = argv2int(J, &rd->argv[2]);
  736.     } else {
  737.       trend = trstart;
  738.       end = start;
  739.     }
  740.   }
  741.   if (end < 0) {
  742.     emitir(IRTGI(IR_LT), trend, tr0);
  743.     trend = emitir(IRTI(IR_ADD), emitir(IRTI(IR_ADD), trlen, trend),
  744.                    lj_ir_kint(J, 1));
  745.     end = end+(int32_t)str->len+1;
  746.   } else if ((MSize)end <= str->len) {
  747.     emitir(IRTGI(IR_ULE), trend, trlen);
  748.   } else {
  749.     emitir(IRTGI(IR_UGT), trend, trlen);
  750.     end = (int32_t)str->len;
  751.     trend = trlen;
  752.   }
  753.   trstart = recff_string_start(J, str, &start, trstart, trlen, tr0);
  754.   if (rd->data) {  /* Return string.sub result. */
  755.     if (end - start >= 0) {
  756.       /* Also handle empty range here, to avoid extra traces. */
  757.       TRef trptr, trslen = emitir(IRTI(IR_SUB), trend, trstart);
  758.       emitir(IRTGI(IR_GE), trslen, tr0);
  759.       trptr = emitir(IRT(IR_STRREF, IRT_P32), trstr, trstart);
  760.       J->base[0] = emitir(IRT(IR_SNEW, IRT_STR), trptr, trslen);
  761.     } else/* Range underflow: return empty string. */
  762.       emitir(IRTGI(IR_LT), trend, trstart);
  763.       J->base[0] = lj_ir_kstr(J, &J2G(J)->strempty);
  764.     }
  765.   } else/* Return string.byte result(s). */
  766.     ptrdiff_t i, len = end - start;
  767.     if (len > 0) {
  768.       TRef trslen = emitir(IRTI(IR_SUB), trend, trstart);
  769.       emitir(IRTGI(IR_EQ), trslen, lj_ir_kint(J, (int32_t)len));
  770.       if (J->baseslot + len > LJ_MAX_JSLOTS)
  771.         lj_trace_err_info(J, LJ_TRERR_STACKOV);
  772.       rd->nres = len;
  773.       for (i = 0; i < len; i++) {
  774.         TRef tmp = emitir(IRTI(IR_ADD), trstart, lj_ir_kint(J, (int32_t)i));
  775.         tmp = emitir(IRT(IR_STRREF, IRT_P32), trstr, tmp);
  776.         J->base[i] = emitir(IRT(IR_XLOAD, IRT_U8), tmp, IRXLOAD_READONLY);
  777.       }
  778.     } else/* Empty range or range underflow: return no results. */
  779.       emitir(IRTGI(IR_LE), trend, trstart);
  780.       rd->nres = 0;
  781.     }
  782.   }
  783. }

  784. static void LJ_FASTCALL recff_string_char(jit_State *J, RecordFFData *rd)
  785. {
  786.   TRef k255 = lj_ir_kint(J, 255);
  787.   BCReg i;
  788.   for (i = 0; J->base[i] != 0; i++) {  /* Convert char values to strings. */
  789.     TRef tr = lj_opt_narrow_toint(J, J->base[i]);
  790.     emitir(IRTGI(IR_ULE), tr, k255);
  791.     J->base[i] = emitir(IRT(IR_TOSTR, IRT_STR), tr, IRTOSTR_CHAR);
  792.   }
  793.   if (i > 1) {  /* Concatenate the strings, if there's more than one. */
  794.     TRef hdr = recff_bufhdr(J), tr = hdr;
  795.     for (i = 0; J->base[i] != 0; i++)
  796.       tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, J->base[i]);
  797.     J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
  798.   }
  799.   UNUSED(rd);
  800. }

  801. static void LJ_FASTCALL recff_string_rep(jit_State *J, RecordFFData *rd)
  802. {
  803.   TRef str = lj_ir_tostr(J, J->base[0]);
  804.   TRef rep = lj_opt_narrow_toint(J, J->base[1]);
  805.   TRef hdr, tr, str2 = 0;
  806.   if (!tref_isnil(J->base[2])) {
  807.     TRef sep = lj_ir_tostr(J, J->base[2]);
  808.     int32_t vrep = argv2int(J, &rd->argv[1]);
  809.     emitir(IRTGI(vrep > 1 ? IR_GT : IR_LE), rep, lj_ir_kint(J, 1));
  810.     if (vrep > 1) {
  811.       TRef hdr2 = recff_bufhdr(J);
  812.       TRef tr2 = emitir(IRT(IR_BUFPUT, IRT_P32), hdr2, sep);
  813.       tr2 = emitir(IRT(IR_BUFPUT, IRT_P32), tr2, str);
  814.       str2 = emitir(IRT(IR_BUFSTR, IRT_STR), tr2, hdr2);
  815.     }
  816.   }
  817.   tr = hdr = recff_bufhdr(J);
  818.   if (str2) {
  819.     tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, str);
  820.     str = str2;
  821.     rep = emitir(IRTI(IR_ADD), rep, lj_ir_kint(J, -1));
  822.   }
  823.   tr = lj_ir_call(J, IRCALL_lj_buf_putstr_rep, tr, str, rep);
  824.   J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
  825. }

  826. static void LJ_FASTCALL recff_string_op(jit_State *J, RecordFFData *rd)
  827. {
  828.   TRef str = lj_ir_tostr(J, J->base[0]);
  829.   TRef hdr = recff_bufhdr(J);
  830.   TRef tr = lj_ir_call(J, rd->data, hdr, str);
  831.   J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
  832. }

  833. static void LJ_FASTCALL recff_string_find(jit_State *J, RecordFFData *rd)
  834. {
  835.   TRef trstr = lj_ir_tostr(J, J->base[0]);
  836.   TRef trpat = lj_ir_tostr(J, J->base[1]);
  837.   TRef trlen = emitir(IRTI(IR_FLOAD), trstr, IRFL_STR_LEN);
  838.   TRef tr0 = lj_ir_kint(J, 0);
  839.   TRef trstart;
  840.   GCstr *str = argv2str(J, &rd->argv[0]);
  841.   GCstr *pat = argv2str(J, &rd->argv[1]);
  842.   int32_t start;
  843.   J->needsnap = 1;
  844.   if (tref_isnil(J->base[2])) {
  845.     trstart = lj_ir_kint(J, 1);
  846.     start = 1;
  847.   } else {
  848.     trstart = lj_opt_narrow_toint(J, J->base[2]);
  849.     start = argv2int(J, &rd->argv[2]);
  850.   }
  851.   trstart = recff_string_start(J, str, &start, trstart, trlen, tr0);
  852.   if ((MSize)start <= str->len) {
  853.     emitir(IRTGI(IR_ULE), trstart, trlen);
  854.   } else {
  855.     emitir(IRTGI(IR_UGT), trstart, trlen);
  856. #if LJ_52
  857.     J->base[0] = TREF_NIL;
  858.     return;
  859. #else
  860.     trstart = trlen;
  861.     start = str->len;
  862. #endif
  863.   }
  864.   /* Fixed arg or no pattern matching chars? (Specialized to pattern string.) */
  865.   if ((J->base[2] && tref_istruecond(J->base[3])) ||
  866.       (emitir(IRTG(IR_EQ, IRT_STR), trpat, lj_ir_kstr(J, pat)),
  867.        !lj_str_haspattern(pat))) {  /* Search for fixed string. */
  868.     TRef trsptr = emitir(IRT(IR_STRREF, IRT_P32), trstr, trstart);
  869.     TRef trpptr = emitir(IRT(IR_STRREF, IRT_P32), trpat, tr0);
  870.     TRef trslen = emitir(IRTI(IR_SUB), trlen, trstart);
  871.     TRef trplen = emitir(IRTI(IR_FLOAD), trpat, IRFL_STR_LEN);
  872.     TRef tr = lj_ir_call(J, IRCALL_lj_str_find, trsptr, trpptr, trslen, trplen);
  873.     TRef trp0 = lj_ir_kkptr(J, NULL);
  874.     if (lj_str_find(strdata(str)+(MSize)start, strdata(pat),
  875.                     str->len-(MSize)start, pat->len)) {
  876.       TRef pos;
  877.       emitir(IRTG(IR_NE, IRT_P32), tr, trp0);
  878.       pos = emitir(IRTI(IR_SUB), tr, emitir(IRT(IR_STRREF, IRT_P32), trstr, tr0));
  879.       J->base[0] = emitir(IRTI(IR_ADD), pos, lj_ir_kint(J, 1));
  880.       J->base[1] = emitir(IRTI(IR_ADD), pos, trplen);
  881.       rd->nres = 2;
  882.     } else {
  883.       emitir(IRTG(IR_EQ, IRT_P32), tr, trp0);
  884.       J->base[0] = TREF_NIL;
  885.     }
  886.   } else/* Search for pattern. */
  887.     recff_nyiu(J, rd);
  888.     return;
  889.   }
  890. }

  891. static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd)
  892. {
  893.   TRef trfmt = lj_ir_tostr(J, J->base[0]);
  894.   GCstr *fmt = argv2str(J, &rd->argv[0]);
  895.   int arg = 1;
  896.   TRef hdr, tr;
  897.   FormatState fs;
  898.   SFormat sf;
  899.   /* Specialize to the format string. */
  900.   emitir(IRTG(IR_EQ, IRT_STR), trfmt, lj_ir_kstr(J, fmt));
  901.   tr = hdr = recff_bufhdr(J);
  902.   lj_strfmt_init(&fs, strdata(fmt), fmt->len);
  903.   while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) {  /* Parse format. */
  904.     TRef tra = sf == STRFMT_LIT ? 0 : J->base[arg++];
  905.     TRef trsf = lj_ir_kint(J, (int32_t)sf);
  906.     IRCallID id;
  907.     switch (STRFMT_TYPE(sf)) {
  908.     case STRFMT_LIT:
  909.       tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr,
  910.                   lj_ir_kstr(J, lj_str_new(J->L, fs.str, fs.len)));
  911.       break;
  912.     case STRFMT_INT:
  913.       id = IRCALL_lj_strfmt_putfnum_int;
  914.     handle_int:
  915.       if (!tref_isinteger(tra))
  916.         goto handle_num;
  917.       if (sf == STRFMT_INT) { /* Shortcut for plain %d. */
  918.         tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr,
  919.                     emitir(IRT(IR_TOSTR, IRT_STR), tra, IRTOSTR_INT));
  920.       } else {
  921. #if LJ_HASFFI
  922.         tra = emitir(IRT(IR_CONV, IRT_U64), tra,
  923.                      (IRT_INT|(IRT_U64<<5)|IRCONV_SEXT));
  924.         tr = lj_ir_call(J, IRCALL_lj_strfmt_putfxint, tr, trsf, tra);
  925.         lj_needsplit(J);
  926. #else
  927.         recff_nyiu(J, rd);  /* Don't bother working around this NYI. */
  928.         return;
  929. #endif
  930.       }
  931.       break;
  932.     case STRFMT_UINT:
  933.       id = IRCALL_lj_strfmt_putfnum_uint;
  934.       goto handle_int;
  935.     case STRFMT_NUM:
  936.       id = IRCALL_lj_strfmt_putfnum;
  937.     handle_num:
  938.       tra = lj_ir_tonum(J, tra);
  939.       tr = lj_ir_call(J, id, tr, trsf, tra);
  940.       if (LJ_SOFTFP) lj_needsplit(J);
  941.       break;
  942.     case STRFMT_STR:
  943.       if (!tref_isstr(tra)) {
  944.         recff_nyiu(J, rd);  /* NYI: __tostring and non-string types for %s. */
  945.         return;
  946.       }
  947.       if (sf == STRFMT_STR)  /* Shortcut for plain %s. */
  948.         tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, tra);
  949.       else if ((sf & STRFMT_T_QUOTED))
  950.         tr = lj_ir_call(J, IRCALL_lj_strfmt_putquoted, tr, tra);
  951.       else
  952.         tr = lj_ir_call(J, IRCALL_lj_strfmt_putfstr, tr, trsf, tra);
  953.       break;
  954.     case STRFMT_CHAR:
  955.       tra = lj_opt_narrow_toint(J, tra);
  956.       if (sf == STRFMT_CHAR)  /* Shortcut for plain %c. */
  957.         tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr,
  958.                     emitir(IRT(IR_TOSTR, IRT_STR), tra, IRTOSTR_CHAR));
  959.       else
  960.         tr = lj_ir_call(J, IRCALL_lj_strfmt_putfchar, tr, trsf, tra);
  961.       break;
  962.     case STRFMT_PTR:  /* NYI */
  963.     case STRFMT_ERR:
  964.     default:
  965.       recff_nyiu(J, rd);
  966.       return;
  967.     }
  968.   }
  969.   J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
  970. }

  971. /* -- Table library fast functions ---------------------------------------- */

  972. static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd)
  973. {
  974.   RecordIndex ix;
  975.   ix.tab = J->base[0];
  976.   ix.val = J->base[1];
  977.   rd->nres = 0;
  978.   if (tref_istab(ix.tab) && ix.val) {
  979.     if (!J->base[2]) {  /* Simple push: t[#t+1] = v */
  980.       TRef trlen = lj_ir_call(J, IRCALL_lj_tab_len, ix.tab);
  981.       GCtab *t = tabV(&rd->argv[0]);
  982.       ix.key = emitir(IRTI(IR_ADD), trlen, lj_ir_kint(J, 1));
  983.       settabV(J->L, &ix.tabv, t);
  984.       setintV(&ix.keyv, lj_tab_len(t) + 1);
  985.       ix.idxchain = 0;
  986.       lj_record_idx(J, &ix);  /* Set new value. */
  987.     } else/* Complex case: insert in the middle. */
  988.       recff_nyiu(J, rd);
  989.       return;
  990.     }
  991.   }  /* else: Interpreter will throw. */
  992. }

  993. static void LJ_FASTCALL recff_table_concat(jit_State *J, RecordFFData *rd)
  994. {
  995.   TRef tab = J->base[0];
  996.   if (tref_istab(tab)) {
  997.     TRef sep = !tref_isnil(J->base[1]) ?
  998.                lj_ir_tostr(J, J->base[1]) : lj_ir_knull(J, IRT_STR);
  999.     TRef tri = (J->base[1] && !tref_isnil(J->base[2])) ?
  1000.                lj_opt_narrow_toint(J, J->base[2]) : lj_ir_kint(J, 1);
  1001.     TRef tre = (J->base[1] && J->base[2] && !tref_isnil(J->base[3])) ?
  1002.                lj_opt_narrow_toint(J, J->base[3]) :
  1003.                lj_ir_call(J, IRCALL_lj_tab_len, tab);
  1004.     TRef hdr = recff_bufhdr(J);
  1005.     TRef tr = lj_ir_call(J, IRCALL_lj_buf_puttab, hdr, tab, sep, tri, tre);
  1006.     emitir(IRTG(IR_NE, IRT_PTR), tr, lj_ir_kptr(J, NULL));
  1007.     J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
  1008.   }  /* else: Interpreter will throw. */
  1009.   UNUSED(rd);
  1010. }

  1011. static void LJ_FASTCALL recff_table_new(jit_State *J, RecordFFData *rd)
  1012. {
  1013.   TRef tra = lj_opt_narrow_toint(J, J->base[0]);
  1014.   TRef trh = lj_opt_narrow_toint(J, J->base[1]);
  1015.   J->base[0] = lj_ir_call(J, IRCALL_lj_tab_new_ah, tra, trh);
  1016.   UNUSED(rd);
  1017. }

  1018. static void LJ_FASTCALL recff_table_clear(jit_State *J, RecordFFData *rd)
  1019. {
  1020.   TRef tr = J->base[0];
  1021.   if (tref_istab(tr)) {
  1022.     rd->nres = 0;
  1023.     lj_ir_call(J, IRCALL_lj_tab_clear, tr);
  1024.     J->needsnap = 1;
  1025.   }  /* else: Interpreter will throw. */
  1026. }

  1027. /* -- I/O library fast functions ------------------------------------------ */

  1028. /* Get FILE* for I/O function. Any I/O error aborts recording, so there's
  1029. ** no need to encode the alternate cases for any of the guards.
  1030. */
  1031. static TRef recff_io_fp(jit_State *J, TRef *udp, int32_t id)
  1032. {
  1033.   TRef tr, ud, fp;
  1034.   if (id) {  /* io.func() */
  1035.     tr = lj_ir_kptr(J, &J2G(J)->gcroot[id]);
  1036.     ud = emitir(IRT(IR_XLOAD, IRT_UDATA), tr, 0);
  1037.   } else/* fp:method() */
  1038.     ud = J->base[0];
  1039.     if (!tref_isudata(ud))
  1040.       lj_trace_err(J, LJ_TRERR_BADTYPE);
  1041.     tr = emitir(IRT(IR_FLOAD, IRT_U8), ud, IRFL_UDATA_UDTYPE);
  1042.     emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, UDTYPE_IO_FILE));
  1043.   }
  1044.   *udp = ud;
  1045.   fp = emitir(IRT(IR_FLOAD, IRT_PTR), ud, IRFL_UDATA_FILE);
  1046.   emitir(IRTG(IR_NE, IRT_PTR), fp, lj_ir_knull(J, IRT_PTR));
  1047.   return fp;
  1048. }

  1049. static void LJ_FASTCALL recff_io_write(jit_State *J, RecordFFData *rd)
  1050. {
  1051.   TRef ud, fp = recff_io_fp(J, &ud, rd->data);
  1052.   TRef zero = lj_ir_kint(J, 0);
  1053.   TRef one = lj_ir_kint(J, 1);
  1054.   ptrdiff_t i = rd->data == 0 ? 1 : 0;
  1055.   for (; J->base[i]; i++) {
  1056.     TRef str = lj_ir_tostr(J, J->base[i]);
  1057.     TRef buf = emitir(IRT(IR_STRREF, IRT_P32), str, zero);
  1058.     TRef len = emitir(IRTI(IR_FLOAD), str, IRFL_STR_LEN);
  1059.     if (tref_isk(len) && IR(tref_ref(len))->i == 1) {
  1060.       IRIns *irs = IR(tref_ref(str));
  1061.       TRef tr = (irs->o == IR_TOSTR && irs->op2 == IRTOSTR_CHAR) ?
  1062.                 irs->op1 :
  1063.                 emitir(IRT(IR_XLOAD, IRT_U8), buf, IRXLOAD_READONLY);
  1064.       tr = lj_ir_call(J, IRCALL_fputc, tr, fp);
  1065.       if (results_wanted(J) != 0/* Check result only if not ignored. */
  1066.         emitir(IRTGI(IR_NE), tr, lj_ir_kint(J, -1));
  1067.     } else {
  1068.       TRef tr = lj_ir_call(J, IRCALL_fwrite, buf, one, len, fp);
  1069.       if (results_wanted(J) != 0/* Check result only if not ignored. */
  1070.         emitir(IRTGI(IR_EQ), tr, len);
  1071.     }
  1072.   }
  1073.   J->base[0] = LJ_52 ? ud : TREF_TRUE;
  1074. }

  1075. static void LJ_FASTCALL recff_io_flush(jit_State *J, RecordFFData *rd)
  1076. {
  1077.   TRef ud, fp = recff_io_fp(J, &ud, rd->data);
  1078.   TRef tr = lj_ir_call(J, IRCALL_fflush, fp);
  1079.   if (results_wanted(J) != 0/* Check result only if not ignored. */
  1080.     emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, 0));
  1081.   J->base[0] = TREF_TRUE;
  1082. }

  1083. /* -- Debug library fast functions ---------------------------------------- */

  1084. static void LJ_FASTCALL recff_debug_getmetatable(jit_State *J, RecordFFData *rd)
  1085. {
  1086.   GCtab *mt;
  1087.   TRef mtref;
  1088.   TRef tr = J->base[0];
  1089.   if (tref_istab(tr)) {
  1090.     mt = tabref(tabV(&rd->argv[0])->metatable);
  1091.     mtref = emitir(IRT(IR_FLOAD, IRT_TAB), tr, IRFL_TAB_META);
  1092.   } else if (tref_isudata(tr)) {
  1093.     mt = tabref(udataV(&rd->argv[0])->metatable);
  1094.     mtref = emitir(IRT(IR_FLOAD, IRT_TAB), tr, IRFL_UDATA_META);
  1095.   } else {
  1096.     mt = tabref(basemt_obj(J2G(J), &rd->argv[0]));
  1097.     J->base[0] = mt ? lj_ir_ktab(J, mt) : TREF_NIL;
  1098.     return;
  1099.   }
  1100.   emitir(IRTG(mt ? IR_NE : IR_EQ, IRT_TAB), mtref, lj_ir_knull(J, IRT_TAB));
  1101.   J->base[0] = mt ? mtref : TREF_NIL;
  1102. }

  1103. /* -- Record calls to fast functions -------------------------------------- */

  1104. #include "lj_recdef.h"

  1105. static uint32_t recdef_lookup(GCfunc *fn)
  1106. {
  1107.   if (fn->c.ffid < sizeof(recff_idmap)/sizeof(recff_idmap[0]))
  1108.     return recff_idmap[fn->c.ffid];
  1109.   else
  1110.     return 0;
  1111. }

  1112. /* Record entry to a fast function or C function. */
  1113. void lj_ffrecord_func(jit_State *J)
  1114. {
  1115.   RecordFFData rd;
  1116.   uint32_t m = recdef_lookup(J->fn);
  1117.   rd.data = m & 0xff;
  1118.   rd.nres = 1/* Default is one result. */
  1119.   rd.argv = J->L->base;
  1120.   J->base[J->maxslot] = 0/* Mark end of arguments. */
  1121.   (recff_func[m >> 8])(J, &rd);  /* Call recff_* handler. */
  1122.   if (rd.nres >= 0) {
  1123.     if (J->postproc == LJ_POST_NONE) J->postproc = LJ_POST_FFRETRY;
  1124.     lj_record_ret(J, 0, rd.nres);
  1125.   }
  1126. }

  1127. #undef IR
  1128. #undef emitir

  1129. #endif