ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

ljx_bitwise.c (4736B)


      1 #include "lj_obj.h"
      2 #include "lj_strscan.h"
      3 #if LJ_HASFFI
      4 #include "lj_ctype.h"
      5 #include "lj_cdata.h"
      6 #include "lj_cconv.h"
      7 #endif
      8 #include "ljx_bitwise.h"
      9 #include "lj_crecord.h"
     10 #include "lj_dispatch.h"
     11 #include "lj_iropt.h"
     12 
     13 #if LJ_53
     14 /* Decode arguments for interpreter dispatch */
     15 static int get_arg(lua_State *L, cTValue *o, int64_t *res)
     16 {
     17   TValue tmp;
     18 #if LJ_HASFFI
     19   CTypeID id = 0;
     20   *res = 0;
     21   if (tviscdata(o)) {
     22     CTState *cts = ctype_cts(L);
     23     uint8_t *sp = (uint8_t *)cdataptr(cdataV(o));
     24     CTypeID sid = cdataV(o)->ctypeid;
     25     CType *s = ctype_get(cts, sid);
     26     if (ctype_isref(s->info)) {
     27       sp = *(void **)sp;
     28       sid = ctype_cid(s->info);
     29     }
     30     s = ctype_raw(cts, sid);
     31     if (ctype_isenum(s->info)) s = ctype_child(cts, s);
     32     if ((s->info & (CTMASK_NUM|CTF_BOOL|CTF_FP|CTF_UNSIGNED)) ==
     33         CTINFO(CT_NUM, CTF_UNSIGNED) && s->size == 8)
     34       id = CTID_UINT64;  /* Use uint64_t, since it has the highest rank. */
     35     else
     36       id = CTID_INT64;  /* Use int64_t, unless already set. */
     37     if (lj_cconv_ct_ct(cts, ctype_get(cts, id), s,
     38 		   (uint8_t *)res, sp, CCF_NOERROR) < 0)
     39       return -1;
     40     return id;
     41   } else
     42 #endif
     43   if (tvisstr(o)) {
     44     if (!lj_strscan_number(strV(o), &tmp))
     45       return -1;
     46     o = &tmp;
     47   }
     48   if (LJ_LIKELY(tvisint(o))) {
     49     *res = (uint32_t)intV(o);
     50     return 0;
     51   } 
     52   if (LJ_LIKELY(tvisnumber(o))) {
     53     *res = (uint32_t)lj_num2bit(numV(o));
     54     return 0;
     55   }
     56   return -1;
     57 }
     58 
     59 #define B_METHODS(_) \
     60 _(bnot,=~x) _(idiv, /=y) _(band, &=y) _(bor, |=y) \
     61 _(bxor, ^=y) _(shl, <<=y) _(shr, >>=y)
     62 #define CASE(name, suff) \
     63   case MM_##name: x suff; break;
     64 
     65 int ljx_vm_foldbit(lua_State *L, TValue *ra, cTValue *rb, cTValue *rc,
     66 		      MMS mm)
     67 {
     68   int id1, id2;
     69   int64_t a,b;
     70 
     71   if (((id1 = get_arg(L, rb, &a)) == -1) || ((id2 = get_arg(L, rc, &b)) == -1))
     72     return -1; /* call metamethod */
     73   /* expand to common type, with the exception of shifts */
     74   if (mm < MM_shl && id2 > id1)
     75     id1 = id2;
     76   /* int32 */
     77   if (!id1) {
     78     uint32_t x = a;
     79     uint32_t y = b;
     80     switch (mm) {
     81       B_METHODS(CASE)
     82       default: return -1;
     83     }
     84     setintV(ra, x);
     85   }
     86 #if LJ_HASFFI
     87   else {
     88     uint64_t x = a;
     89     uint64_t y = b;
     90     GCcdata *cd;
     91     switch (mm) {
     92       B_METHODS(CASE)
     93       default: return -1;
     94     }
     95     cd = lj_cdata_new_(L, id1, 8);
     96     *(uint64_t *)cdataptr(cd) = x;
     97     setcdataV(L, ra, cd);
     98   }
     99 #endif
    100   return id1;
    101 }
    102 
    103 #define emitir(ot, a, b)	(lj_ir_set(J, (ot), (a), (b)), lj_opt_fold(J))
    104 #define emitconv(a, dt, st, flags) \
    105   emitir(IRT(IR_CONV, (dt)), (a), (st)|((dt) << 5)|(flags))
    106 
    107 /* Same as lj_opt_narrow_tobit, but does not raise trace error. */
    108 static TRef bit_narrow_int(jit_State *J, TRef r)
    109 {
    110   if (tref_isstr(r))
    111     r = emitir(IRTG(IR_STRTO, IRT_NUM), r, 0);
    112   if (tref_isnum(r))  /* Conversion may be narrowed, too. See above. */
    113     return emitir(IRTI(IR_TOBIT), r, lj_ir_knum_tobit(J));
    114   if (!tref_isinteger(r))
    115     return 0;
    116   return lj_opt_narrow_stripov(J, r, IR_SUBOV, (IRT_INT<<5)|IRT_INT|IRCONV_TOBIT);
    117 }
    118 
    119 /* Narrow to specified type. */
    120 static TRef bit_narrow_id(jit_State *J, CTypeID wantid, TRef tr, cTValue *o)
    121 {
    122   CTState *cts = ctype_ctsG(J2G(J));
    123   if (!wantid)
    124     return bit_narrow_int(J, tr);
    125 #if LJ_HASJIT && LJ_HASFFI
    126   return lj_crec_ct_tv(J, ctype_get(cts, wantid), 0, tr, o);
    127 #else
    128   return 0;
    129 #endif
    130 }
    131 
    132 /* Record. */
    133 TRef ljx_rec_bitwise(jit_State *J, TRef rb, TRef rc, cTValue *rbv, cTValue *rcv, MMS mm)
    134 {
    135   CTState *cts = ctype_ctsG(J2G(J));
    136   TRef r1, r2 = 0;
    137   CTypeID id1 = 0, id2 = 0;
    138 #if LJ_HASJIT && LJ_HASFFI
    139   id1 = lj_crec_bit64_type(cts, rbv);
    140   id2 = lj_crec_bit64_type(cts, rcv);
    141 #endif
    142   /* For shifts, the shift arg might stay as int */
    143   if (mm >= MM_shl) {
    144     if (id2) {
    145       r2 = bit_narrow_id(J, CTID_INT64, rc, rcv);
    146       if (!tref_isinteger(r2))
    147         r2 = emitconv(r2, IRT_INT, tref_type(r2), 0);
    148     } else {
    149       r2 = bit_narrow_int(J, rc);
    150       if (!r2) return 0; /* Not even int? Bail. */
    151     }
    152     id2 = 0; /* The arg is never widest */
    153   }
    154   if (id2 > id1) /* Determine widest type */
    155     id1 = id2;
    156   r1 = bit_narrow_id(J, id1, rb, rbv); /* And resolve those */
    157   if (!r1) return 0;
    158 
    159   if (!r2 && mm != MM_bnot) { /* Only if not shift or unary */
    160     r2 = bit_narrow_id(J, id1, rc, rcv);
    161     if (!r2) return 0;
    162   }
    163 
    164   /* All set now. id1 holds the output type (or 0 if INT). */
    165   uint32_t irop = IR_BNOT + mm - MM_bnot;
    166   if (mm == MM_idiv)
    167     irop = IR_DIV;
    168   /* Type-specific and boxed? */
    169 #if LJ_HASJIT && LJ_HASFFI
    170   if (id1) {
    171     TRef tr = emitir(IRT(irop, id1-CTID_INT64+IRT_I64), r1, r2);
    172     return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id1), tr);
    173   }
    174 #endif
    175   /* Otherwise plain I32 */
    176   return emitir(IRTI(irop), r1, r2);
    177 }
    178 
    179 #endif