lib_bit.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. ** Bit manipulation library.
  3. ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
  4. */
  5. #define lib_bit_c
  6. #define LUA_LIB
  7. #include "lua.h"
  8. #include "lauxlib.h"
  9. #include "lualib.h"
  10. #include "lj_obj.h"
  11. #include "lj_err.h"
  12. #include "lj_buf.h"
  13. #include "lj_strscan.h"
  14. #include "lj_strfmt.h"
  15. #if LJ_HASFFI
  16. #include "lj_ctype.h"
  17. #include "lj_cdata.h"
  18. #include "lj_cconv.h"
  19. #include "lj_carith.h"
  20. #endif
  21. #include "lj_ff.h"
  22. #include "lj_lib.h"
  23. /* ------------------------------------------------------------------------ */
  24. #define LJLIB_MODULE_bit
  25. #if LJ_HASFFI
  26. static int bit_result64(lua_State *L, CTypeID id, uint64_t x)
  27. {
  28. GCcdata *cd = lj_cdata_new_(L, id, 8);
  29. *(uint64_t *)cdataptr(cd) = x;
  30. setcdataV(L, L->base-1-LJ_FR2, cd);
  31. return FFH_RES(1);
  32. }
  33. #else
  34. static int32_t bit_checkbit(lua_State *L, int narg)
  35. {
  36. TValue *o = L->base + narg-1;
  37. if (!(o < L->top && lj_strscan_numberobj(o)))
  38. lj_err_argt(L, narg, LUA_TNUMBER);
  39. if (LJ_LIKELY(tvisint(o))) {
  40. return intV(o);
  41. } else {
  42. int32_t i = lj_num2bit(numV(o));
  43. if (LJ_DUALNUM) setintV(o, i);
  44. return i;
  45. }
  46. }
  47. #endif
  48. LJLIB_ASM(bit_tobit) LJLIB_REC(bit_tobit)
  49. {
  50. #if LJ_HASFFI
  51. CTypeID id = 0;
  52. setintV(L->base-1-LJ_FR2, (int32_t)lj_carith_check64(L, 1, &id));
  53. return FFH_RES(1);
  54. #else
  55. lj_lib_checknumber(L, 1);
  56. return FFH_RETRY;
  57. #endif
  58. }
  59. LJLIB_ASM(bit_bnot) LJLIB_REC(bit_unary IR_BNOT)
  60. {
  61. #if LJ_HASFFI
  62. CTypeID id = 0;
  63. uint64_t x = lj_carith_check64(L, 1, &id);
  64. return id ? bit_result64(L, id, ~x) : FFH_RETRY;
  65. #else
  66. lj_lib_checknumber(L, 1);
  67. return FFH_RETRY;
  68. #endif
  69. }
  70. LJLIB_ASM(bit_bswap) LJLIB_REC(bit_unary IR_BSWAP)
  71. {
  72. #if LJ_HASFFI
  73. CTypeID id = 0;
  74. uint64_t x = lj_carith_check64(L, 1, &id);
  75. return id ? bit_result64(L, id, lj_bswap64(x)) : FFH_RETRY;
  76. #else
  77. lj_lib_checknumber(L, 1);
  78. return FFH_RETRY;
  79. #endif
  80. }
  81. LJLIB_ASM(bit_lshift) LJLIB_REC(bit_shift IR_BSHL)
  82. {
  83. #if LJ_HASFFI
  84. CTypeID id = 0, id2 = 0;
  85. uint64_t x = lj_carith_check64(L, 1, &id);
  86. int32_t sh = (int32_t)lj_carith_check64(L, 2, &id2);
  87. if (id) {
  88. x = lj_carith_shift64(x, sh, curr_func(L)->c.ffid - (int)FF_bit_lshift);
  89. return bit_result64(L, id, x);
  90. }
  91. if (id2) setintV(L->base+1, sh);
  92. return FFH_RETRY;
  93. #else
  94. lj_lib_checknumber(L, 1);
  95. bit_checkbit(L, 2);
  96. return FFH_RETRY;
  97. #endif
  98. }
  99. LJLIB_ASM_(bit_rshift) LJLIB_REC(bit_shift IR_BSHR)
  100. LJLIB_ASM_(bit_arshift) LJLIB_REC(bit_shift IR_BSAR)
  101. LJLIB_ASM_(bit_rol) LJLIB_REC(bit_shift IR_BROL)
  102. LJLIB_ASM_(bit_ror) LJLIB_REC(bit_shift IR_BROR)
  103. LJLIB_ASM(bit_band) LJLIB_REC(bit_nary IR_BAND)
  104. {
  105. #if LJ_HASFFI
  106. CTypeID id = 0;
  107. TValue *o = L->base, *top = L->top;
  108. int i = 0;
  109. do { lj_carith_check64(L, ++i, &id); } while (++o < top);
  110. if (id) {
  111. CTState *cts = ctype_cts(L);
  112. CType *ct = ctype_get(cts, id);
  113. int op = curr_func(L)->c.ffid - (int)FF_bit_bor;
  114. uint64_t x, y = op >= 0 ? 0 : ~(uint64_t)0;
  115. o = L->base;
  116. do {
  117. lj_cconv_ct_tv(cts, ct, (uint8_t *)&x, o, 0);
  118. if (op < 0) y &= x; else if (op == 0) y |= x; else y ^= x;
  119. } while (++o < top);
  120. return bit_result64(L, id, y);
  121. }
  122. return FFH_RETRY;
  123. #else
  124. int i = 0;
  125. do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top);
  126. return FFH_RETRY;
  127. #endif
  128. }
  129. LJLIB_ASM_(bit_bor) LJLIB_REC(bit_nary IR_BOR)
  130. LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR)
  131. /* ------------------------------------------------------------------------ */
  132. LJLIB_CF(bit_tohex) LJLIB_REC(.)
  133. {
  134. #if LJ_HASFFI
  135. CTypeID id = 0, id2 = 0;
  136. uint64_t b = lj_carith_check64(L, 1, &id);
  137. int32_t n = L->base+1>=L->top ? (id ? 16 : 8) :
  138. (int32_t)lj_carith_check64(L, 2, &id2);
  139. #else
  140. uint32_t b = (uint32_t)bit_checkbit(L, 1);
  141. int32_t n = L->base+1>=L->top ? 8 : bit_checkbit(L, 2);
  142. #endif
  143. SBuf *sb = lj_buf_tmp_(L);
  144. SFormat sf = (STRFMT_UINT|STRFMT_T_HEX);
  145. if (n < 0) { n = (int32_t)(~(uint32_t)n+1u); sf |= STRFMT_F_UPPER; }
  146. if ((uint32_t)n > 254) n = 254;
  147. sf |= ((SFormat)((n+1)&255) << STRFMT_SH_PREC);
  148. #if LJ_HASFFI
  149. if (n < 16) b &= ((uint64_t)1 << 4*n)-1;
  150. #else
  151. if (n < 8) b &= (1u << 4*n)-1;
  152. #endif
  153. sb = lj_strfmt_putfxint(sb, sf, b);
  154. setstrV(L, L->top-1, lj_buf_str(L, sb));
  155. lj_gc_check(L);
  156. return 1;
  157. }
  158. /* ------------------------------------------------------------------------ */
  159. #include "lj_libdef.h"
  160. LUALIB_API int luaopen_bit(lua_State *L)
  161. {
  162. LJ_LIB_REG(L, LUA_BITLIBNAME, bit);
  163. return 1;
  164. }