diff options
| author | Mike Pall <mike> | 2013-03-13 22:44:01 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2013-03-14 06:03:18 +0100 |
| commit | a98aede37772797b4471e1a094452051edff5862 (patch) | |
| tree | 6e8c86838e359b899ffa0021bf3149087caa71da | |
| parent | 3e8f5ac7186ecac63e17688b9ba6e72697143dbb (diff) | |
| download | luajit-a98aede37772797b4471e1a094452051edff5862.tar.gz luajit-a98aede37772797b4471e1a094452051edff5862.tar.bz2 luajit-a98aede37772797b4471e1a094452051edff5862.zip | |
FFI: Add 64 bit bitwise operations.
| -rw-r--r-- | doc/ext_ffi_semantics.html | 17 | ||||
| -rw-r--r-- | doc/extensions.html | 3 | ||||
| -rw-r--r-- | src/Makefile.dep | 9 | ||||
| -rw-r--r-- | src/lib_bit.c | 98 | ||||
| -rw-r--r-- | src/lj_carith.c | 76 | ||||
| -rw-r--r-- | src/lj_carith.h | 10 | ||||
| -rw-r--r-- | src/lj_crecord.c | 95 | ||||
| -rw-r--r-- | src/lj_crecord.h | 6 | ||||
| -rw-r--r-- | src/lj_ffrecord.c | 66 | ||||
| -rw-r--r-- | src/lj_ircall.h | 7 | ||||
| -rw-r--r-- | src/lj_opt_fold.c | 41 | ||||
| -rw-r--r-- | src/lj_opt_split.c | 127 |
12 files changed, 495 insertions, 60 deletions
diff --git a/doc/ext_ffi_semantics.html b/doc/ext_ffi_semantics.html index 03229012..15c9a6db 100644 --- a/doc/ext_ffi_semantics.html +++ b/doc/ext_ffi_semantics.html | |||
| @@ -730,6 +730,22 @@ You'll have to explicitly convert a 64 bit integer to a Lua | |||
| 730 | number (e.g. for regular floating-point calculations) with | 730 | number (e.g. for regular floating-point calculations) with |
| 731 | <tt>tonumber()</tt>. But note this may incur a precision loss.</li> | 731 | <tt>tonumber()</tt>. But note this may incur a precision loss.</li> |
| 732 | 732 | ||
| 733 | <li><b>64 bit bitwise operations</b>: the rules for 64 bit | ||
| 734 | arithmetic operators apply analogously.<br> | ||
| 735 | |||
| 736 | Unlike the other <tt>bit.*</tt> operations, <tt>bit.tobit()</tt> | ||
| 737 | converts a cdata number via <tt>int64_t</tt> to <tt>int32_t</tt> and | ||
| 738 | returns a Lua number.<br> | ||
| 739 | |||
| 740 | For <tt>bit.band()</tt>, <tt>bit.bor()</tt> and <tt>bit.bxor()</tt>, the | ||
| 741 | conversion to <tt>int64_t</tt> or <tt>uint64_t</tt> applies to | ||
| 742 | <em>all</em> arguments, if <em>any</em> argument is a cdata number.<br> | ||
| 743 | |||
| 744 | For all other operations, only the first argument is used to determine | ||
| 745 | the output type. This implies that a cdata number as a shift count for | ||
| 746 | shifts and rotates is accepted, but that alone does <em>not</em> cause | ||
| 747 | a cdata number output. | ||
| 748 | |||
| 733 | </ul> | 749 | </ul> |
| 734 | 750 | ||
| 735 | <h3 id="cdata_comp">Comparisons of cdata objects</h3> | 751 | <h3 id="cdata_comp">Comparisons of cdata objects</h3> |
| @@ -1222,7 +1238,6 @@ value.</li> | |||
| 1222 | Other missing features: | 1238 | Other missing features: |
| 1223 | </p> | 1239 | </p> |
| 1224 | <ul> | 1240 | <ul> |
| 1225 | <li>Bit operations for 64 bit types.</li> | ||
| 1226 | <li>Arithmetic for <tt>complex</tt> numbers.</li> | 1241 | <li>Arithmetic for <tt>complex</tt> numbers.</li> |
| 1227 | <li>Passing structs by value to vararg C functions.</li> | 1242 | <li>Passing structs by value to vararg C functions.</li> |
| 1228 | <li><a href="extensions.html#exceptions">C++ exception interoperability</a> | 1243 | <li><a href="extensions.html#exceptions">C++ exception interoperability</a> |
diff --git a/doc/extensions.html b/doc/extensions.html index 2bfcc76c..f288fbde 100644 --- a/doc/extensions.html +++ b/doc/extensions.html | |||
| @@ -113,6 +113,9 @@ bit.lshift bit.rshift bit.arshift bit.rol bit.ror bit.bswap | |||
| 113 | This module is a LuaJIT built-in — you don't need to download or | 113 | This module is a LuaJIT built-in — you don't need to download or |
| 114 | install Lua BitOp. The Lua BitOp site has full documentation for all | 114 | install Lua BitOp. The Lua BitOp site has full documentation for all |
| 115 | <a href="http://bitop.luajit.org/api.html"><span class="ext">»</span> Lua BitOp API functions</a>. | 115 | <a href="http://bitop.luajit.org/api.html"><span class="ext">»</span> Lua BitOp API functions</a>. |
| 116 | The FFI adds support for | ||
| 117 | <a href="ext_ffi_semantics.html#cdata_arith">64 bit bitwise operations<a>, | ||
| 118 | using the same API functions. | ||
| 116 | </p> | 119 | </p> |
| 117 | <p> | 120 | <p> |
| 118 | Please make sure to <tt>require</tt> the module before using any of | 121 | Please make sure to <tt>require</tt> the module before using any of |
diff --git a/src/Makefile.dep b/src/Makefile.dep index f841767b..902d2912 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep | |||
| @@ -7,7 +7,8 @@ lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ | |||
| 7 | lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_strscan.h \ | 7 | lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_strscan.h \ |
| 8 | lj_lib.h lj_libdef.h | 8 | lj_lib.h lj_libdef.h |
| 9 | lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | 9 | lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ |
| 10 | lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_lib.h lj_libdef.h | 10 | lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_gc.h lj_cdata.h \ |
| 11 | lj_cconv.h lj_carith.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h | ||
| 11 | lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ | 12 | lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ |
| 12 | lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_lib.h \ | 13 | lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_lib.h \ |
| 13 | lj_libdef.h | 14 | lj_libdef.h |
| @@ -17,7 +18,7 @@ lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | |||
| 17 | lj_ccallback.h lj_clib.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h | 18 | lj_ccallback.h lj_clib.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h |
| 18 | lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h | 19 | lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h |
| 19 | lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | 20 | lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ |
| 20 | lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_state.h \ | 21 | lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_state.h \ |
| 21 | lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h | 22 | lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h |
| 22 | lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h \ | 23 | lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h \ |
| 23 | lj_obj.h lj_def.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h \ | 24 | lj_obj.h lj_def.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h \ |
| @@ -58,8 +59,8 @@ lj_bcwrite.o: lj_bcwrite.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | |||
| 58 | lj_buf.o: lj_buf.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 59 | lj_buf.o: lj_buf.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 59 | lj_err.h lj_errmsg.h lj_buf.h lj_str.h | 60 | lj_err.h lj_errmsg.h lj_buf.h lj_str.h |
| 60 | lj_carith.o: lj_carith.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 61 | lj_carith.o: lj_carith.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 61 | lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_meta.h lj_ctype.h lj_cconv.h \ | 62 | lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_meta.h lj_ir.h lj_ctype.h \ |
| 62 | lj_cdata.h lj_carith.h | 63 | lj_cconv.h lj_cdata.h lj_carith.h lj_strscan.h |
| 63 | lj_ccall.o: lj_ccall.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 64 | lj_ccall.o: lj_ccall.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 64 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cconv.h \ | 65 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cconv.h \ |
| 65 | lj_cdata.h lj_ccall.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \ | 66 | lj_cdata.h lj_ccall.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \ |
diff --git a/src/lib_bit.c b/src/lib_bit.c index 93fead92..85821b81 100644 --- a/src/lib_bit.c +++ b/src/lib_bit.c | |||
| @@ -13,25 +13,82 @@ | |||
| 13 | #include "lj_obj.h" | 13 | #include "lj_obj.h" |
| 14 | #include "lj_err.h" | 14 | #include "lj_err.h" |
| 15 | #include "lj_str.h" | 15 | #include "lj_str.h" |
| 16 | #if LJ_HASFFI | ||
| 17 | #include "lj_ctype.h" | ||
| 18 | #include "lj_cdata.h" | ||
| 19 | #include "lj_cconv.h" | ||
| 20 | #include "lj_carith.h" | ||
| 21 | #endif | ||
| 22 | #include "lj_ff.h" | ||
| 16 | #include "lj_lib.h" | 23 | #include "lj_lib.h" |
| 17 | 24 | ||
| 18 | /* ------------------------------------------------------------------------ */ | 25 | /* ------------------------------------------------------------------------ */ |
| 19 | 26 | ||
| 20 | #define LJLIB_MODULE_bit | 27 | #define LJLIB_MODULE_bit |
| 21 | 28 | ||
| 22 | LJLIB_ASM(bit_tobit) LJLIB_REC(bit_unary IR_TOBIT) | 29 | #if LJ_HASFFI |
| 30 | static int bit_result64(lua_State *L, CTypeID id, uint64_t x) | ||
| 23 | { | 31 | { |
| 32 | GCcdata *cd = lj_cdata_new_(L, id, 8); | ||
| 33 | *(uint64_t *)cdataptr(cd) = x; | ||
| 34 | setcdataV(L, L->base-1, cd); | ||
| 35 | return FFH_RES(1); | ||
| 36 | } | ||
| 37 | #endif | ||
| 38 | |||
| 39 | LJLIB_ASM(bit_tobit) LJLIB_REC(bit_tobit) | ||
| 40 | { | ||
| 41 | #if LJ_HASFFI | ||
| 42 | CTypeID id = 0; | ||
| 43 | setintV(L->base-1, (int32_t)lj_carith_check64(L, 1, &id)); | ||
| 44 | return FFH_RES(1); | ||
| 45 | #else | ||
| 46 | lj_lib_checknumber(L, 1); | ||
| 47 | return FFH_RETRY; | ||
| 48 | #endif | ||
| 49 | } | ||
| 50 | |||
| 51 | LJLIB_ASM(bit_bnot) LJLIB_REC(bit_unary IR_BNOT) | ||
| 52 | { | ||
| 53 | #if LJ_HASFFI | ||
| 54 | CTypeID id = 0; | ||
| 55 | uint64_t x = lj_carith_check64(L, 1, &id); | ||
| 56 | return id ? bit_result64(L, id, ~x) : FFH_RETRY; | ||
| 57 | #else | ||
| 58 | lj_lib_checknumber(L, 1); | ||
| 59 | return FFH_RETRY; | ||
| 60 | #endif | ||
| 61 | } | ||
| 62 | |||
| 63 | LJLIB_ASM(bit_bswap) LJLIB_REC(bit_unary IR_BSWAP) | ||
| 64 | { | ||
| 65 | #if LJ_HASFFI | ||
| 66 | CTypeID id = 0; | ||
| 67 | uint64_t x = lj_carith_check64(L, 1, &id); | ||
| 68 | return id ? bit_result64(L, id, lj_bswap64(x)) : FFH_RETRY; | ||
| 69 | #else | ||
| 24 | lj_lib_checknumber(L, 1); | 70 | lj_lib_checknumber(L, 1); |
| 25 | return FFH_RETRY; | 71 | return FFH_RETRY; |
| 72 | #endif | ||
| 26 | } | 73 | } |
| 27 | LJLIB_ASM_(bit_bnot) LJLIB_REC(bit_unary IR_BNOT) | ||
| 28 | LJLIB_ASM_(bit_bswap) LJLIB_REC(bit_unary IR_BSWAP) | ||
| 29 | 74 | ||
| 30 | LJLIB_ASM(bit_lshift) LJLIB_REC(bit_shift IR_BSHL) | 75 | LJLIB_ASM(bit_lshift) LJLIB_REC(bit_shift IR_BSHL) |
| 31 | { | 76 | { |
| 77 | #if LJ_HASFFI | ||
| 78 | CTypeID id = 0, id2 = 0; | ||
| 79 | uint64_t x = lj_carith_check64(L, 1, &id); | ||
| 80 | int32_t sh = (int32_t)lj_carith_check64(L, 2, &id2); | ||
| 81 | if (id) { | ||
| 82 | x = lj_carith_shift64(x, sh, curr_func(L)->c.ffid - (int)FF_bit_lshift); | ||
| 83 | return bit_result64(L, id, x); | ||
| 84 | } | ||
| 85 | if (id2) setintV(L->base+1, sh); | ||
| 86 | return FFH_RETRY; | ||
| 87 | #else | ||
| 32 | lj_lib_checknumber(L, 1); | 88 | lj_lib_checknumber(L, 1); |
| 33 | lj_lib_checkbit(L, 2); | 89 | lj_lib_checkbit(L, 2); |
| 34 | return FFH_RETRY; | 90 | return FFH_RETRY; |
| 91 | #endif | ||
| 35 | } | 92 | } |
| 36 | LJLIB_ASM_(bit_rshift) LJLIB_REC(bit_shift IR_BSHR) | 93 | LJLIB_ASM_(bit_rshift) LJLIB_REC(bit_shift IR_BSHR) |
| 37 | LJLIB_ASM_(bit_arshift) LJLIB_REC(bit_shift IR_BSAR) | 94 | LJLIB_ASM_(bit_arshift) LJLIB_REC(bit_shift IR_BSAR) |
| @@ -40,9 +97,29 @@ LJLIB_ASM_(bit_ror) LJLIB_REC(bit_shift IR_BROR) | |||
| 40 | 97 | ||
| 41 | LJLIB_ASM(bit_band) LJLIB_REC(bit_nary IR_BAND) | 98 | LJLIB_ASM(bit_band) LJLIB_REC(bit_nary IR_BAND) |
| 42 | { | 99 | { |
| 100 | #if LJ_HASFFI | ||
| 101 | CTypeID id = 0; | ||
| 102 | TValue *o = L->base, *top = L->top; | ||
| 103 | int i = 0; | ||
| 104 | do { lj_carith_check64(L, ++i, &id); } while (++o < top); | ||
| 105 | if (id) { | ||
| 106 | CTState *cts = ctype_cts(L); | ||
| 107 | CType *ct = ctype_get(cts, id); | ||
| 108 | int op = curr_func(L)->c.ffid - (int)FF_bit_bor; | ||
| 109 | uint64_t x, y = op >= 0 ? 0 : ~(uint64_t)0; | ||
| 110 | o = L->base; | ||
| 111 | do { | ||
| 112 | lj_cconv_ct_tv(cts, ct, (uint8_t *)&x, o, 0); | ||
| 113 | if (op < 0) y &= x; else if (op == 0) y |= x; else y ^= x; | ||
| 114 | } while (++o < top); | ||
| 115 | return bit_result64(L, id, y); | ||
| 116 | } | ||
| 117 | return FFH_RETRY; | ||
| 118 | #else | ||
| 43 | int i = 0; | 119 | int i = 0; |
| 44 | do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top); | 120 | do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top); |
| 45 | return FFH_RETRY; | 121 | return FFH_RETRY; |
| 122 | #endif | ||
| 46 | } | 123 | } |
| 47 | LJLIB_ASM_(bit_bor) LJLIB_REC(bit_nary IR_BOR) | 124 | LJLIB_ASM_(bit_bor) LJLIB_REC(bit_nary IR_BOR) |
| 48 | LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR) | 125 | LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR) |
| @@ -51,12 +128,21 @@ LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR) | |||
| 51 | 128 | ||
| 52 | LJLIB_CF(bit_tohex) | 129 | LJLIB_CF(bit_tohex) |
| 53 | { | 130 | { |
| 131 | #if LJ_HASFFI | ||
| 132 | CTypeID id = 0, id2 = 0; | ||
| 133 | uint64_t b = lj_carith_check64(L, 1, &id); | ||
| 134 | int32_t i, dig = id ? 16 : 8; | ||
| 135 | int32_t n = L->base+1>=L->top ? dig : (int32_t)lj_carith_check64(L, 2, &id2); | ||
| 136 | char buf[16]; | ||
| 137 | #else | ||
| 54 | uint32_t b = (uint32_t)lj_lib_checkbit(L, 1); | 138 | uint32_t b = (uint32_t)lj_lib_checkbit(L, 1); |
| 55 | int32_t i, n = L->base+1 >= L->top ? 8 : lj_lib_checkbit(L, 2); | 139 | int32_t i, dig = 8; |
| 56 | const char *hexdigits = "0123456789abcdef"; | 140 | int32_t n = L->base+1>=L->top ? dig : lj_lib_checkbit(L, 2); |
| 57 | char buf[8]; | 141 | char buf[8]; |
| 142 | #endif | ||
| 143 | const char *hexdigits = "0123456789abcdef"; | ||
| 58 | if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } | 144 | if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } |
| 59 | if (n > 8) n = 8; | 145 | if (n > dig) n = dig; |
| 60 | for (i = n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } | 146 | for (i = n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } |
| 61 | lua_pushlstring(L, buf, (size_t)n); | 147 | lua_pushlstring(L, buf, (size_t)n); |
| 62 | return 1; | 148 | return 1; |
diff --git a/src/lj_carith.c b/src/lj_carith.c index 18708d66..9f3208a8 100644 --- a/src/lj_carith.c +++ b/src/lj_carith.c | |||
| @@ -11,10 +11,12 @@ | |||
| 11 | #include "lj_err.h" | 11 | #include "lj_err.h" |
| 12 | #include "lj_tab.h" | 12 | #include "lj_tab.h" |
| 13 | #include "lj_meta.h" | 13 | #include "lj_meta.h" |
| 14 | #include "lj_ir.h" | ||
| 14 | #include "lj_ctype.h" | 15 | #include "lj_ctype.h" |
| 15 | #include "lj_cconv.h" | 16 | #include "lj_cconv.h" |
| 16 | #include "lj_cdata.h" | 17 | #include "lj_cdata.h" |
| 17 | #include "lj_carith.h" | 18 | #include "lj_carith.h" |
| 19 | #include "lj_strscan.h" | ||
| 18 | 20 | ||
| 19 | /* -- C data arithmetic --------------------------------------------------- */ | 21 | /* -- C data arithmetic --------------------------------------------------- */ |
| 20 | 22 | ||
| @@ -270,6 +272,80 @@ int lj_carith_op(lua_State *L, MMS mm) | |||
| 270 | return lj_carith_meta(L, cts, &ca, mm); | 272 | return lj_carith_meta(L, cts, &ca, mm); |
| 271 | } | 273 | } |
| 272 | 274 | ||
| 275 | /* -- 64 bit bit operations helpers --------------------------------------- */ | ||
| 276 | |||
| 277 | #if LJ_64 | ||
| 278 | #define B64DEF(name) \ | ||
| 279 | static LJ_AINLINE uint64_t lj_carith_##name(uint64_t x, int32_t sh) | ||
| 280 | #else | ||
| 281 | /* Not inlined on 32 bit archs, since some of these are quite lengthy. */ | ||
| 282 | #define B64DEF(name) \ | ||
| 283 | uint64_t LJ_NOINLINE lj_carith_##name(uint64_t x, int32_t sh) | ||
| 284 | #endif | ||
| 285 | |||
| 286 | B64DEF(shl64) { return x << (sh&63); } | ||
| 287 | B64DEF(shr64) { return x >> (sh&63); } | ||
| 288 | B64DEF(sar64) { return (uint64_t)((int64_t)x >> (sh&63)); } | ||
| 289 | B64DEF(rol64) { return lj_rol(x, (sh&63)); } | ||
| 290 | B64DEF(ror64) { return lj_ror(x, (sh&63)); } | ||
| 291 | |||
| 292 | #undef B64DEF | ||
| 293 | |||
| 294 | uint64_t lj_carith_shift64(uint64_t x, int32_t sh, int op) | ||
| 295 | { | ||
| 296 | switch (op) { | ||
| 297 | case IR_BSHL-IR_BSHL: x = lj_carith_shl64(x, sh); break; | ||
| 298 | case IR_BSHR-IR_BSHL: x = lj_carith_shr64(x, sh); break; | ||
| 299 | case IR_BSAR-IR_BSHL: x = lj_carith_sar64(x, sh); break; | ||
| 300 | case IR_BROL-IR_BSHL: x = lj_carith_rol64(x, sh); break; | ||
| 301 | case IR_BROR-IR_BSHL: x = lj_carith_ror64(x, sh); break; | ||
| 302 | default: lua_assert(0); break; | ||
| 303 | } | ||
| 304 | return x; | ||
| 305 | } | ||
| 306 | |||
| 307 | /* Equivalent to lj_lib_checkbit(), but handles cdata. */ | ||
| 308 | uint64_t lj_carith_check64(lua_State *L, int narg, CTypeID *id) | ||
| 309 | { | ||
| 310 | TValue *o = L->base + narg-1; | ||
| 311 | if (o >= L->top) { | ||
| 312 | err: | ||
| 313 | lj_err_argt(L, narg, LUA_TNUMBER); | ||
| 314 | } else if (LJ_LIKELY(tvisnumber(o))) { | ||
| 315 | /* Handled below. */ | ||
| 316 | } else if (tviscdata(o)) { | ||
| 317 | CTState *cts = ctype_cts(L); | ||
| 318 | uint8_t *sp = (uint8_t *)cdataptr(cdataV(o)); | ||
| 319 | CTypeID sid = cdataV(o)->ctypeid; | ||
| 320 | CType *s = ctype_get(cts, sid); | ||
| 321 | uint64_t x; | ||
| 322 | if (ctype_isref(s->info)) { | ||
| 323 | sp = *(void **)sp; | ||
| 324 | sid = ctype_cid(s->info); | ||
| 325 | } | ||
| 326 | s = ctype_raw(cts, sid); | ||
| 327 | if (ctype_isenum(s->info)) s = ctype_child(cts, s); | ||
| 328 | if ((s->info & (CTMASK_NUM|CTF_BOOL|CTF_FP|CTF_UNSIGNED)) == | ||
| 329 | CTINFO(CT_NUM, CTF_UNSIGNED) && s->size == 8) | ||
| 330 | *id = CTID_UINT64; /* Use uint64_t, since it has the highest rank. */ | ||
| 331 | else if (!*id) | ||
| 332 | *id = CTID_INT64; /* Use int64_t, unless already set. */ | ||
| 333 | lj_cconv_ct_ct(cts, ctype_get(cts, *id), s, | ||
| 334 | (uint8_t *)&x, sp, CCF_ARG(narg)); | ||
| 335 | return x; | ||
| 336 | } else if (!(tvisstr(o) && lj_strscan_number(strV(o), o))) { | ||
| 337 | goto err; | ||
| 338 | } | ||
| 339 | if (LJ_LIKELY(tvisint(o))) { | ||
| 340 | return intV(o); | ||
| 341 | } else { | ||
| 342 | int32_t i = lj_num2bit(numV(o)); | ||
| 343 | if (LJ_DUALNUM) setintV(o, i); | ||
| 344 | return i; | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 348 | |||
| 273 | /* -- 64 bit integer arithmetic helpers ----------------------------------- */ | 349 | /* -- 64 bit integer arithmetic helpers ----------------------------------- */ |
| 274 | 350 | ||
| 275 | #if LJ_32 && LJ_HASJIT | 351 | #if LJ_32 && LJ_HASJIT |
diff --git a/src/lj_carith.h b/src/lj_carith.h index ae17df00..b1a65d35 100644 --- a/src/lj_carith.h +++ b/src/lj_carith.h | |||
| @@ -12,6 +12,16 @@ | |||
| 12 | 12 | ||
| 13 | LJ_FUNC int lj_carith_op(lua_State *L, MMS mm); | 13 | LJ_FUNC int lj_carith_op(lua_State *L, MMS mm); |
| 14 | 14 | ||
| 15 | #if LJ_32 | ||
| 16 | LJ_FUNC uint64_t lj_carith_shl64(uint64_t x, int32_t sh); | ||
| 17 | LJ_FUNC uint64_t lj_carith_shr64(uint64_t x, int32_t sh); | ||
| 18 | LJ_FUNC uint64_t lj_carith_sar64(uint64_t x, int32_t sh); | ||
| 19 | LJ_FUNC uint64_t lj_carith_rol64(uint64_t x, int32_t sh); | ||
| 20 | LJ_FUNC uint64_t lj_carith_ror64(uint64_t x, int32_t sh); | ||
| 21 | #endif | ||
| 22 | LJ_FUNC uint64_t lj_carith_shift64(uint64_t x, int32_t sh, int op); | ||
| 23 | LJ_FUNC uint64_t lj_carith_check64(lua_State *L, int narg, CTypeID *id); | ||
| 24 | |||
| 15 | #if LJ_32 && LJ_HASJIT | 25 | #if LJ_32 && LJ_HASJIT |
| 16 | LJ_FUNC int64_t lj_carith_mul64(int64_t x, int64_t k); | 26 | LJ_FUNC int64_t lj_carith_mul64(int64_t x, int64_t k); |
| 17 | #endif | 27 | #endif |
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index a5d896eb..2bf0bc1d 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c | |||
| @@ -1626,6 +1626,101 @@ void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd) | |||
| 1626 | crec_finalizer(J, J->base[0], &rd->argv[1]); | 1626 | crec_finalizer(J, J->base[0], &rd->argv[1]); |
| 1627 | } | 1627 | } |
| 1628 | 1628 | ||
| 1629 | /* -- 64 bit bit.* library functions -------------------------------------- */ | ||
| 1630 | |||
| 1631 | /* Determine bit operation type from argument type. */ | ||
| 1632 | static CTypeID crec_bit64_type(CTState *cts, cTValue *tv) | ||
| 1633 | { | ||
| 1634 | if (tviscdata(tv)) { | ||
| 1635 | CType *ct = lj_ctype_rawref(cts, cdataV(tv)->ctypeid); | ||
| 1636 | if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); | ||
| 1637 | if ((ct->info & (CTMASK_NUM|CTF_BOOL|CTF_FP|CTF_UNSIGNED)) == | ||
| 1638 | CTINFO(CT_NUM, CTF_UNSIGNED) && ct->size == 8) | ||
| 1639 | return CTID_UINT64; /* Use uint64_t, since it has the highest rank. */ | ||
| 1640 | return CTID_INT64; /* Otherwise use int64_t. */ | ||
| 1641 | } | ||
| 1642 | return 0; /* Use regular 32 bit ops. */ | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | void LJ_FASTCALL recff_bit64_tobit(jit_State *J, RecordFFData *rd) | ||
| 1646 | { | ||
| 1647 | CTState *cts = ctype_ctsG(J2G(J)); | ||
| 1648 | TRef tr = crec_ct_tv(J, ctype_get(cts, CTID_INT64), 0, | ||
| 1649 | J->base[0], &rd->argv[0]); | ||
| 1650 | if (!tref_isinteger(tr)) | ||
| 1651 | tr = emitconv(tr, IRT_INT, tref_type(tr), 0); | ||
| 1652 | J->base[0] = tr; | ||
| 1653 | } | ||
| 1654 | |||
| 1655 | int LJ_FASTCALL recff_bit64_unary(jit_State *J, RecordFFData *rd) | ||
| 1656 | { | ||
| 1657 | CTState *cts = ctype_ctsG(J2G(J)); | ||
| 1658 | CTypeID id = crec_bit64_type(cts, &rd->argv[0]); | ||
| 1659 | if (id) { | ||
| 1660 | TRef tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]); | ||
| 1661 | tr = emitir(IRT(rd->data, id-CTID_INT64+IRT_I64), tr, 0); | ||
| 1662 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
| 1663 | return 1; | ||
| 1664 | } | ||
| 1665 | return 0; | ||
| 1666 | } | ||
| 1667 | |||
| 1668 | int LJ_FASTCALL recff_bit64_nary(jit_State *J, RecordFFData *rd) | ||
| 1669 | { | ||
| 1670 | CTState *cts = ctype_ctsG(J2G(J)); | ||
| 1671 | CTypeID id = 0; | ||
| 1672 | MSize i; | ||
| 1673 | for (i = 0; J->base[i] != 0; i++) { | ||
| 1674 | CTypeID aid = crec_bit64_type(cts, &rd->argv[i]); | ||
| 1675 | if (id < aid) id = aid; /* Determine highest type rank of all arguments. */ | ||
| 1676 | } | ||
| 1677 | if (id) { | ||
| 1678 | CType *ct = ctype_get(cts, id); | ||
| 1679 | uint32_t ot = IRT(rd->data, id-CTID_INT64+IRT_I64); | ||
| 1680 | TRef tr = crec_ct_tv(J, ct, 0, J->base[0], &rd->argv[0]); | ||
| 1681 | for (i = 1; J->base[i] != 0; i++) { | ||
| 1682 | TRef tr2 = crec_ct_tv(J, ct, 0, J->base[i], &rd->argv[i]); | ||
| 1683 | tr = emitir(ot, tr, tr2); | ||
| 1684 | } | ||
| 1685 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
| 1686 | return 1; | ||
| 1687 | } | ||
| 1688 | return 0; | ||
| 1689 | } | ||
| 1690 | |||
| 1691 | int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd) | ||
| 1692 | { | ||
| 1693 | CTState *cts = ctype_ctsG(J2G(J)); | ||
| 1694 | CTypeID id; | ||
| 1695 | TRef tsh = 0; | ||
| 1696 | if (J->base[0] && tref_iscdata(J->base[1])) { | ||
| 1697 | tsh = crec_ct_tv(J, ctype_get(cts, CTID_INT64), 0, | ||
| 1698 | J->base[1], &rd->argv[1]); | ||
| 1699 | if (!tref_isinteger(tsh)) | ||
| 1700 | tsh = emitconv(tsh, IRT_INT, tref_type(tsh), 0); | ||
| 1701 | J->base[1] = tsh; | ||
| 1702 | } | ||
| 1703 | id = crec_bit64_type(cts, &rd->argv[0]); | ||
| 1704 | if (id) { | ||
| 1705 | TRef tr = crec_ct_tv(J, ctype_get(cts, id), 0, J->base[0], &rd->argv[0]); | ||
| 1706 | uint32_t op = rd->data; | ||
| 1707 | if (!tsh) tsh = lj_opt_narrow_tobit(J, J->base[1]); | ||
| 1708 | if (!(op < IR_BROL ? LJ_TARGET_MASKSHIFT : LJ_TARGET_MASKROT) && | ||
| 1709 | !tref_isk(tsh)) | ||
| 1710 | tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 63)); | ||
| 1711 | #ifdef LJ_TARGET_UNIFYROT | ||
| 1712 | if (op == (LJ_TARGET_UNIFYROT == 1 ? IR_BROR : IR_BROL)) { | ||
| 1713 | op = LJ_TARGET_UNIFYROT == 1 ? IR_BROL : IR_BROR; | ||
| 1714 | tsh = emitir(IRTI(IR_NEG), tsh, tsh); | ||
| 1715 | } | ||
| 1716 | #endif | ||
| 1717 | tr = emitir(IRT(op, id-CTID_INT64+IRT_I64), tr, tsh); | ||
| 1718 | J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr); | ||
| 1719 | return 1; | ||
| 1720 | } | ||
| 1721 | return 0; | ||
| 1722 | } | ||
| 1723 | |||
| 1629 | /* -- Miscellaneous library functions ------------------------------------- */ | 1724 | /* -- Miscellaneous library functions ------------------------------------- */ |
| 1630 | 1725 | ||
| 1631 | void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd) | 1726 | void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd) |
diff --git a/src/lj_crecord.h b/src/lj_crecord.h index dea05f78..92d777b8 100644 --- a/src/lj_crecord.h +++ b/src/lj_crecord.h | |||
| @@ -25,6 +25,12 @@ LJ_FUNC void LJ_FASTCALL recff_ffi_istype(jit_State *J, RecordFFData *rd); | |||
| 25 | LJ_FUNC void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd); | 25 | LJ_FUNC void LJ_FASTCALL recff_ffi_abi(jit_State *J, RecordFFData *rd); |
| 26 | LJ_FUNC void LJ_FASTCALL recff_ffi_xof(jit_State *J, RecordFFData *rd); | 26 | LJ_FUNC void LJ_FASTCALL recff_ffi_xof(jit_State *J, RecordFFData *rd); |
| 27 | LJ_FUNC void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd); | 27 | LJ_FUNC void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd); |
| 28 | |||
| 29 | LJ_FUNC void LJ_FASTCALL recff_bit64_tobit(jit_State *J, RecordFFData *rd); | ||
| 30 | LJ_FUNC int LJ_FASTCALL recff_bit64_unary(jit_State *J, RecordFFData *rd); | ||
| 31 | LJ_FUNC int LJ_FASTCALL recff_bit64_nary(jit_State *J, RecordFFData *rd); | ||
| 32 | LJ_FUNC int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd); | ||
| 33 | |||
| 28 | LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); | 34 | LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); |
| 29 | #endif | 35 | #endif |
| 30 | 36 | ||
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index 730d5c39..4f6aeb37 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c | |||
| @@ -584,40 +584,66 @@ static void LJ_FASTCALL recff_math_random(jit_State *J, RecordFFData *rd) | |||
| 584 | 584 | ||
| 585 | /* -- Bit library fast functions ------------------------------------------ */ | 585 | /* -- Bit library fast functions ------------------------------------------ */ |
| 586 | 586 | ||
| 587 | /* Record unary bit.tobit, bit.bnot, bit.bswap. */ | 587 | /* Record bit.tobit. */ |
| 588 | static void LJ_FASTCALL recff_bit_tobit(jit_State *J, RecordFFData *rd) | ||
| 589 | { | ||
| 590 | TRef tr = J->base[0]; | ||
| 591 | #if LJ_HASFFI | ||
| 592 | if (tref_iscdata(tr)) { recff_bit64_tobit(J, rd); return; } | ||
| 593 | #endif | ||
| 594 | J->base[0] = lj_opt_narrow_tobit(J, tr); | ||
| 595 | UNUSED(rd); | ||
| 596 | } | ||
| 597 | |||
| 598 | /* Record unary bit.bnot, bit.bswap. */ | ||
| 588 | static void LJ_FASTCALL recff_bit_unary(jit_State *J, RecordFFData *rd) | 599 | static void LJ_FASTCALL recff_bit_unary(jit_State *J, RecordFFData *rd) |
| 589 | { | 600 | { |
| 590 | TRef tr = lj_opt_narrow_tobit(J, J->base[0]); | 601 | #if LJ_HASFFI |
| 591 | J->base[0] = (rd->data == IR_TOBIT) ? tr : emitir(IRTI(rd->data), tr, 0); | 602 | if (recff_bit64_unary(J, rd)) |
| 603 | return; | ||
| 604 | #endif | ||
| 605 | J->base[0] = emitir(IRTI(rd->data), lj_opt_narrow_tobit(J, J->base[0]), 0); | ||
| 592 | } | 606 | } |
| 593 | 607 | ||
| 594 | /* Record N-ary bit.band, bit.bor, bit.bxor. */ | 608 | /* Record N-ary bit.band, bit.bor, bit.bxor. */ |
| 595 | static void LJ_FASTCALL recff_bit_nary(jit_State *J, RecordFFData *rd) | 609 | static void LJ_FASTCALL recff_bit_nary(jit_State *J, RecordFFData *rd) |
| 596 | { | 610 | { |
| 597 | TRef tr = lj_opt_narrow_tobit(J, J->base[0]); | 611 | #if LJ_HASFFI |
| 598 | uint32_t op = rd->data; | 612 | if (recff_bit64_nary(J, rd)) |
| 599 | BCReg i; | 613 | return; |
| 600 | for (i = 1; J->base[i] != 0; i++) | 614 | #endif |
| 601 | tr = emitir(IRTI(op), tr, lj_opt_narrow_tobit(J, J->base[i])); | 615 | { |
| 602 | J->base[0] = tr; | 616 | TRef tr = lj_opt_narrow_tobit(J, J->base[0]); |
| 617 | uint32_t ot = IRTI(rd->data); | ||
| 618 | BCReg i; | ||
| 619 | for (i = 1; J->base[i] != 0; i++) | ||
| 620 | tr = emitir(ot, tr, lj_opt_narrow_tobit(J, J->base[i])); | ||
| 621 | J->base[0] = tr; | ||
| 622 | } | ||
| 603 | } | 623 | } |
| 604 | 624 | ||
| 605 | /* Record bit shifts. */ | 625 | /* Record bit shifts. */ |
| 606 | static void LJ_FASTCALL recff_bit_shift(jit_State *J, RecordFFData *rd) | 626 | static void LJ_FASTCALL recff_bit_shift(jit_State *J, RecordFFData *rd) |
| 607 | { | 627 | { |
| 608 | TRef tr = lj_opt_narrow_tobit(J, J->base[0]); | 628 | #if LJ_HASFFI |
| 609 | TRef tsh = lj_opt_narrow_tobit(J, J->base[1]); | 629 | if (recff_bit64_shift(J, rd)) |
| 610 | IROp op = (IROp)rd->data; | 630 | return; |
| 611 | if (!(op < IR_BROL ? LJ_TARGET_MASKSHIFT : LJ_TARGET_MASKROT) && | 631 | #endif |
| 612 | !tref_isk(tsh)) | 632 | { |
| 613 | tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 31)); | 633 | TRef tr = lj_opt_narrow_tobit(J, J->base[0]); |
| 634 | TRef tsh = lj_opt_narrow_tobit(J, J->base[1]); | ||
| 635 | IROp op = (IROp)rd->data; | ||
| 636 | if (!(op < IR_BROL ? LJ_TARGET_MASKSHIFT : LJ_TARGET_MASKROT) && | ||
| 637 | !tref_isk(tsh)) | ||
| 638 | tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 31)); | ||
| 614 | #ifdef LJ_TARGET_UNIFYROT | 639 | #ifdef LJ_TARGET_UNIFYROT |
| 615 | if (op == (LJ_TARGET_UNIFYROT == 1 ? IR_BROR : IR_BROL)) { | 640 | if (op == (LJ_TARGET_UNIFYROT == 1 ? IR_BROR : IR_BROL)) { |
| 616 | op = LJ_TARGET_UNIFYROT == 1 ? IR_BROL : IR_BROR; | 641 | op = LJ_TARGET_UNIFYROT == 1 ? IR_BROL : IR_BROR; |
| 617 | tsh = emitir(IRTI(IR_NEG), tsh, tsh); | 642 | tsh = emitir(IRTI(IR_NEG), tsh, tsh); |
| 618 | } | 643 | } |
| 619 | #endif | 644 | #endif |
| 620 | J->base[0] = emitir(IRTI(op), tr, tsh); | 645 | J->base[0] = emitir(IRTI(op), tr, tsh); |
| 646 | } | ||
| 621 | } | 647 | } |
| 622 | 648 | ||
| 623 | /* -- String library fast functions --------------------------------------- */ | 649 | /* -- String library fast functions --------------------------------------- */ |
diff --git a/src/lj_ircall.h b/src/lj_ircall.h index 7fcc532e..2c160bdf 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h | |||
| @@ -172,7 +172,12 @@ typedef struct CCallInfo { | |||
| 172 | _(FFI, memcpy, 3, S, PTR, 0) \ | 172 | _(FFI, memcpy, 3, S, PTR, 0) \ |
| 173 | _(FFI, memset, 3, S, PTR, 0) \ | 173 | _(FFI, memset, 3, S, PTR, 0) \ |
| 174 | _(FFI, lj_vm_errno, 0, S, INT, CCI_NOFPRCLOBBER) \ | 174 | _(FFI, lj_vm_errno, 0, S, INT, CCI_NOFPRCLOBBER) \ |
| 175 | _(FFI32, lj_carith_mul64, ARG2_64, N, I64, CCI_NOFPRCLOBBER) | 175 | _(FFI32, lj_carith_mul64, ARG2_64, N, I64, CCI_NOFPRCLOBBER) \ |
| 176 | _(FFI32, lj_carith_shl64, 3, N, U64, CCI_NOFPRCLOBBER) \ | ||
| 177 | _(FFI32, lj_carith_shr64, 3, N, U64, CCI_NOFPRCLOBBER) \ | ||
| 178 | _(FFI32, lj_carith_sar64, 3, N, U64, CCI_NOFPRCLOBBER) \ | ||
| 179 | _(FFI32, lj_carith_rol64, 3, N, U64, CCI_NOFPRCLOBBER) \ | ||
| 180 | _(FFI32, lj_carith_ror64, 3, N, U64, CCI_NOFPRCLOBBER) \ | ||
| 176 | \ | 181 | \ |
| 177 | /* End of list. */ | 182 | /* End of list. */ |
| 178 | 183 | ||
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index e67f3ee6..75db47df 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c | |||
| @@ -22,8 +22,8 @@ | |||
| 22 | #include "lj_trace.h" | 22 | #include "lj_trace.h" |
| 23 | #if LJ_HASFFI | 23 | #if LJ_HASFFI |
| 24 | #include "lj_ctype.h" | 24 | #include "lj_ctype.h" |
| 25 | #endif | ||
| 26 | #include "lj_carith.h" | 25 | #include "lj_carith.h" |
| 26 | #endif | ||
| 27 | #include "lj_vm.h" | 27 | #include "lj_vm.h" |
| 28 | #include "lj_strscan.h" | 28 | #include "lj_strscan.h" |
| 29 | 29 | ||
| @@ -336,11 +336,9 @@ LJFOLDF(kfold_intcomp0) | |||
| 336 | static uint64_t kfold_int64arith(uint64_t k1, uint64_t k2, IROp op) | 336 | static uint64_t kfold_int64arith(uint64_t k1, uint64_t k2, IROp op) |
| 337 | { | 337 | { |
| 338 | switch (op) { | 338 | switch (op) { |
| 339 | #if LJ_64 || LJ_HASFFI | 339 | #if LJ_HASFFI |
| 340 | case IR_ADD: k1 += k2; break; | 340 | case IR_ADD: k1 += k2; break; |
| 341 | case IR_SUB: k1 -= k2; break; | 341 | case IR_SUB: k1 -= k2; break; |
| 342 | #endif | ||
| 343 | #if LJ_HASFFI | ||
| 344 | case IR_MUL: k1 *= k2; break; | 342 | case IR_MUL: k1 *= k2; break; |
| 345 | case IR_BAND: k1 &= k2; break; | 343 | case IR_BAND: k1 &= k2; break; |
| 346 | case IR_BOR: k1 |= k2; break; | 344 | case IR_BOR: k1 |= k2; break; |
| @@ -392,20 +390,10 @@ LJFOLD(BROL KINT64 KINT) | |||
| 392 | LJFOLD(BROR KINT64 KINT) | 390 | LJFOLD(BROR KINT64 KINT) |
| 393 | LJFOLDF(kfold_int64shift) | 391 | LJFOLDF(kfold_int64shift) |
| 394 | { | 392 | { |
| 395 | #if LJ_HASFFI || LJ_64 | 393 | #if LJ_HASFFI |
| 396 | uint64_t k = ir_k64(fleft)->u64; | 394 | uint64_t k = ir_k64(fleft)->u64; |
| 397 | int32_t sh = (fright->i & 63); | 395 | int32_t sh = (fright->i & 63); |
| 398 | switch ((IROp)fins->o) { | 396 | return INT64FOLD(lj_carith_shift64(k, sh, fins->o - IR_BSHL)); |
| 399 | case IR_BSHL: k <<= sh; break; | ||
| 400 | #if LJ_HASFFI | ||
| 401 | case IR_BSHR: k >>= sh; break; | ||
| 402 | case IR_BSAR: k = (uint64_t)((int64_t)k >> sh); break; | ||
| 403 | case IR_BROL: k = lj_rol(k, sh); break; | ||
| 404 | case IR_BROR: k = lj_ror(k, sh); break; | ||
| 405 | #endif | ||
| 406 | default: lua_assert(0); break; | ||
| 407 | } | ||
| 408 | return INT64FOLD(k); | ||
| 409 | #else | 397 | #else |
| 410 | UNUSED(J); lua_assert(0); return FAILFOLD; | 398 | UNUSED(J); lua_assert(0); return FAILFOLD; |
| 411 | #endif | 399 | #endif |
| @@ -1192,7 +1180,9 @@ static TRef simplify_intmul_k(jit_State *J, int32_t k) | |||
| 1192 | ** But this is mainly intended for simple address arithmetic. | 1180 | ** But this is mainly intended for simple address arithmetic. |
| 1193 | ** Also it's easier for the backend to optimize the original multiplies. | 1181 | ** Also it's easier for the backend to optimize the original multiplies. |
| 1194 | */ | 1182 | */ |
| 1195 | if (k == 1) { /* i * 1 ==> i */ | 1183 | if (k == 0) { /* i * 0 ==> 0 */ |
| 1184 | return RIGHTFOLD; | ||
| 1185 | } else if (k == 1) { /* i * 1 ==> i */ | ||
| 1196 | return LEFTFOLD; | 1186 | return LEFTFOLD; |
| 1197 | } else if ((k & (k-1)) == 0) { /* i * 2^k ==> i << k */ | 1187 | } else if ((k & (k-1)) == 0) { /* i * 2^k ==> i << k */ |
| 1198 | fins->o = IR_BSHL; | 1188 | fins->o = IR_BSHL; |
| @@ -1205,9 +1195,7 @@ static TRef simplify_intmul_k(jit_State *J, int32_t k) | |||
| 1205 | LJFOLD(MUL any KINT) | 1195 | LJFOLD(MUL any KINT) |
| 1206 | LJFOLDF(simplify_intmul_k32) | 1196 | LJFOLDF(simplify_intmul_k32) |
| 1207 | { | 1197 | { |
| 1208 | if (fright->i == 0) /* i * 0 ==> 0 */ | 1198 | if (fright->i >= 0) |
| 1209 | return INTFOLD(0); | ||
| 1210 | else if (fright->i > 0) | ||
| 1211 | return simplify_intmul_k(J, fright->i); | 1199 | return simplify_intmul_k(J, fright->i); |
| 1212 | return NEXTFOLD; | 1200 | return NEXTFOLD; |
| 1213 | } | 1201 | } |
| @@ -1215,14 +1203,13 @@ LJFOLDF(simplify_intmul_k32) | |||
| 1215 | LJFOLD(MUL any KINT64) | 1203 | LJFOLD(MUL any KINT64) |
| 1216 | LJFOLDF(simplify_intmul_k64) | 1204 | LJFOLDF(simplify_intmul_k64) |
| 1217 | { | 1205 | { |
| 1218 | if (ir_kint64(fright)->u64 == 0) /* i * 0 ==> 0 */ | 1206 | #if LJ_HASFFI |
| 1219 | return INT64FOLD(0); | 1207 | if (ir_kint64(fright)->u64 < 0x80000000u) |
| 1220 | #if LJ_64 | ||
| 1221 | /* NYI: SPLIT for BSHL and 32 bit backend support. */ | ||
| 1222 | else if (ir_kint64(fright)->u64 < 0x80000000u) | ||
| 1223 | return simplify_intmul_k(J, (int32_t)ir_kint64(fright)->u64); | 1208 | return simplify_intmul_k(J, (int32_t)ir_kint64(fright)->u64); |
| 1224 | #endif | ||
| 1225 | return NEXTFOLD; | 1209 | return NEXTFOLD; |
| 1210 | #else | ||
| 1211 | UNUSED(J); lua_assert(0); return FAILFOLD; | ||
| 1212 | #endif | ||
| 1226 | } | 1213 | } |
| 1227 | 1214 | ||
| 1228 | LJFOLD(MOD any KINT) | 1215 | LJFOLD(MOD any KINT) |
| @@ -1522,7 +1509,7 @@ LJFOLD(BOR BOR KINT64) | |||
| 1522 | LJFOLD(BXOR BXOR KINT64) | 1509 | LJFOLD(BXOR BXOR KINT64) |
| 1523 | LJFOLDF(reassoc_intarith_k64) | 1510 | LJFOLDF(reassoc_intarith_k64) |
| 1524 | { | 1511 | { |
| 1525 | #if LJ_HASFFI || LJ_64 | 1512 | #if LJ_HASFFI |
| 1526 | IRIns *irk = IR(fleft->op2); | 1513 | IRIns *irk = IR(fleft->op2); |
| 1527 | if (irk->o == IR_KINT64) { | 1514 | if (irk->o == IR_KINT64) { |
| 1528 | uint64_t k = kfold_int64arith(ir_k64(irk)->u64, | 1515 | uint64_t k = kfold_int64arith(ir_k64(irk)->u64, |
diff --git a/src/lj_opt_split.c b/src/lj_opt_split.c index 2b04e77d..a0526c9d 100644 --- a/src/lj_opt_split.c +++ b/src/lj_opt_split.c | |||
| @@ -140,6 +140,7 @@ static IRRef split_call_l(jit_State *J, IRRef1 *hisubst, IRIns *oir, | |||
| 140 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); | 140 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); |
| 141 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); | 141 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); |
| 142 | } | 142 | } |
| 143 | #endif | ||
| 143 | 144 | ||
| 144 | /* Emit a CALLN with one split 64 bit argument and a 32 bit argument. */ | 145 | /* Emit a CALLN with one split 64 bit argument and a 32 bit argument. */ |
| 145 | static IRRef split_call_li(jit_State *J, IRRef1 *hisubst, IRIns *oir, | 146 | static IRRef split_call_li(jit_State *J, IRRef1 *hisubst, IRIns *oir, |
| @@ -156,7 +157,6 @@ static IRRef split_call_li(jit_State *J, IRRef1 *hisubst, IRIns *oir, | |||
| 156 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); | 157 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); |
| 157 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); | 158 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); |
| 158 | } | 159 | } |
| 159 | #endif | ||
| 160 | 160 | ||
| 161 | /* Emit a CALLN with two split 64 bit arguments. */ | 161 | /* Emit a CALLN with two split 64 bit arguments. */ |
| 162 | static IRRef split_call_ll(jit_State *J, IRRef1 *hisubst, IRIns *oir, | 162 | static IRRef split_call_ll(jit_State *J, IRRef1 *hisubst, IRIns *oir, |
| @@ -196,6 +196,118 @@ static IRRef split_ptr(jit_State *J, IRIns *oir, IRRef ref) | |||
| 196 | return split_emit(J, IRTI(IR_ADD), nref, lj_ir_kint(J, ofs)); | 196 | return split_emit(J, IRTI(IR_ADD), nref, lj_ir_kint(J, ofs)); |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | #if LJ_HASFFI | ||
| 200 | static IRRef split_bitshift(jit_State *J, IRRef1 *hisubst, | ||
| 201 | IRIns *oir, IRIns *nir, IRIns *ir) | ||
| 202 | { | ||
| 203 | IROp op = ir->o; | ||
| 204 | IRRef kref = nir->op2; | ||
| 205 | if (irref_isk(kref)) { /* Optimize constant shifts. */ | ||
| 206 | int32_t k = (IR(kref)->i & 63); | ||
| 207 | IRRef lo = nir->op1, hi = hisubst[ir->op1]; | ||
| 208 | if (op == IR_BROL || op == IR_BROR) { | ||
| 209 | if (op == IR_BROR) k = (-k & 63); | ||
| 210 | if (k >= 32) { IRRef t = lo; lo = hi; hi = t; k -= 32; } | ||
| 211 | if (k == 0) { | ||
| 212 | passthrough: | ||
| 213 | J->cur.nins--; | ||
| 214 | ir->prev = lo; | ||
| 215 | return hi; | ||
| 216 | } else { | ||
| 217 | TRef k1, k2; | ||
| 218 | IRRef t1, t2, t3, t4; | ||
| 219 | J->cur.nins--; | ||
| 220 | k1 = lj_ir_kint(J, k); | ||
| 221 | k2 = lj_ir_kint(J, (-k & 31)); | ||
| 222 | t1 = split_emit(J, IRTI(IR_BSHL), lo, k1); | ||
| 223 | t2 = split_emit(J, IRTI(IR_BSHL), hi, k1); | ||
| 224 | t3 = split_emit(J, IRTI(IR_BSHR), lo, k2); | ||
| 225 | t4 = split_emit(J, IRTI(IR_BSHR), hi, k2); | ||
| 226 | ir->prev = split_emit(J, IRTI(IR_BOR), t1, t4); | ||
| 227 | return split_emit(J, IRTI(IR_BOR), t2, t3); | ||
| 228 | } | ||
| 229 | } else if (k == 0) { | ||
| 230 | goto passthrough; | ||
| 231 | } else if (k < 32) { | ||
| 232 | if (op == IR_BSHL) { | ||
| 233 | IRRef t1 = split_emit(J, IRTI(IR_BSHL), hi, kref); | ||
| 234 | IRRef t2 = split_emit(J, IRTI(IR_BSHR), lo, lj_ir_kint(J, (-k&31))); | ||
| 235 | return split_emit(J, IRTI(IR_BOR), t1, t2); | ||
| 236 | } else { | ||
| 237 | IRRef t1 = ir->prev, t2; | ||
| 238 | lua_assert(op == IR_BSHR || op == IR_BSAR); | ||
| 239 | nir->o = IR_BSHR; | ||
| 240 | t2 = split_emit(J, IRTI(IR_BSHL), hi, lj_ir_kint(J, (-k&31))); | ||
| 241 | ir->prev = split_emit(J, IRTI(IR_BOR), t1, t2); | ||
| 242 | return split_emit(J, IRTI(op), hi, kref); | ||
| 243 | } | ||
| 244 | } else { | ||
| 245 | if (op == IR_BSHL) { | ||
| 246 | if (k == 32) | ||
| 247 | J->cur.nins--; | ||
| 248 | else | ||
| 249 | lo = ir->prev; | ||
| 250 | ir->prev = lj_ir_kint(J, 0); | ||
| 251 | return lo; | ||
| 252 | } else { | ||
| 253 | lua_assert(op == IR_BSHR || op == IR_BSAR); | ||
| 254 | if (k == 32) { | ||
| 255 | J->cur.nins--; | ||
| 256 | ir->prev = hi; | ||
| 257 | } else { | ||
| 258 | nir->op1 = hi; | ||
| 259 | } | ||
| 260 | if (op == IR_BSHR) | ||
| 261 | return lj_ir_kint(J, 0); | ||
| 262 | else | ||
| 263 | return split_emit(J, IRTI(IR_BSAR), hi, lj_ir_kint(J, 31)); | ||
| 264 | } | ||
| 265 | } | ||
| 266 | } | ||
| 267 | return split_call_li(J, hisubst, oir, ir, | ||
| 268 | op - IR_BSHL + IRCALL_lj_carith_shl64); | ||
| 269 | } | ||
| 270 | |||
| 271 | static IRRef split_bitop(jit_State *J, IRRef1 *hisubst, | ||
| 272 | IRIns *nir, IRIns *ir) | ||
| 273 | { | ||
| 274 | IROp op = ir->o; | ||
| 275 | IRRef hi, kref = nir->op2; | ||
| 276 | if (irref_isk(kref)) { /* Optimize bit operations with lo constant. */ | ||
| 277 | int32_t k = IR(kref)->i; | ||
| 278 | if (k == 0 || k == -1) { | ||
| 279 | if (op == IR_BAND) k = ~k; | ||
| 280 | if (k == 0) { | ||
| 281 | J->cur.nins--; | ||
| 282 | ir->prev = nir->op1; | ||
| 283 | } else if (op == IR_BXOR) { | ||
| 284 | nir->o = IR_BNOT; | ||
| 285 | nir->op2 = 0; | ||
| 286 | } else { | ||
| 287 | J->cur.nins--; | ||
| 288 | ir->prev = kref; | ||
| 289 | } | ||
| 290 | } | ||
| 291 | } | ||
| 292 | hi = hisubst[ir->op1]; | ||
| 293 | kref = hisubst[ir->op2]; | ||
| 294 | if (irref_isk(kref)) { /* Optimize bit operations with hi constant. */ | ||
| 295 | int32_t k = IR(kref)->i; | ||
| 296 | if (k == 0 || k == -1) { | ||
| 297 | if (op == IR_BAND) k = ~k; | ||
| 298 | if (k == 0) { | ||
| 299 | return hi; | ||
| 300 | } else if (op == IR_BXOR) { | ||
| 301 | return split_emit(J, IRTI(IR_BNOT), hi, 0); | ||
| 302 | } else { | ||
| 303 | return kref; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | } | ||
| 307 | return split_emit(J, IRTI(op), hi, kref); | ||
| 308 | } | ||
| 309 | #endif | ||
| 310 | |||
| 199 | /* Transform the old IR to the new IR. */ | 311 | /* Transform the old IR to the new IR. */ |
| 200 | static void split_ir(jit_State *J) | 312 | static void split_ir(jit_State *J) |
| 201 | { | 313 | { |
| @@ -417,6 +529,19 @@ static void split_ir(jit_State *J) | |||
| 417 | irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : | 529 | irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : |
| 418 | IRCALL_lj_carith_powu64); | 530 | IRCALL_lj_carith_powu64); |
| 419 | break; | 531 | break; |
| 532 | case IR_BNOT: | ||
| 533 | hi = split_emit(J, IRTI(IR_BNOT), hiref, 0); | ||
| 534 | break; | ||
| 535 | case IR_BSWAP: | ||
| 536 | ir->prev = split_emit(J, IRTI(IR_BSWAP), hiref, 0); | ||
| 537 | hi = nref; | ||
| 538 | break; | ||
| 539 | case IR_BAND: case IR_BOR: case IR_BXOR: | ||
| 540 | hi = split_bitop(J, hisubst, nir, ir); | ||
| 541 | break; | ||
| 542 | case IR_BSHL: case IR_BSHR: case IR_BSAR: case IR_BROL: case IR_BROR: | ||
| 543 | hi = split_bitshift(J, hisubst, oir, nir, ir); | ||
| 544 | break; | ||
| 420 | case IR_FLOAD: | 545 | case IR_FLOAD: |
| 421 | lua_assert(ir->op2 == IRFL_CDATA_INT64); | 546 | lua_assert(ir->op2 == IRFL_CDATA_INT64); |
| 422 | hi = split_emit(J, IRTI(IR_FLOAD), nir->op1, IRFL_CDATA_INT64_4); | 547 | hi = split_emit(J, IRTI(IR_FLOAD), nir->op1, IRFL_CDATA_INT64_4); |
